X-Git-Url: http://git.linex4red.de/pub/USBasp.git/blobdiff_plain/39f1c0c136520a3f4746ad6381d1242979125ff3..deb181ae2c27db872c471a77e85d7190f32962c3:/firmware/tpi.S diff --git a/firmware/tpi.S b/firmware/tpi.S new file mode 100644 index 000000000..e597e7452 --- /dev/null +++ b/firmware/tpi.S @@ -0,0 +1,258 @@ +/** + * \brief Size-optimized code for TPI + * \file tpi.s + * \author S³awomir Fraœ + */ +#include +#include "tpi_defs.h" + + +#define TPI_CLK_PORT PORTB +#define TPI_CLK_DDR DDRB +#define TPI_CLK_BIT 5 +#define TPI_DATAOUT_PORT PORTB +#define TPI_DATAOUT_DDR DDRB +#define TPI_DATAOUT_BIT 3 +#ifdef TPI_WITH_OPTO +# define TPI_DATAIN_PIN PINB +# define TPI_DATAIN_DDR DDRB +# define TPI_DATAIN_BIT 4 +#else +# define TPI_DATAIN_PIN PINB +# define TPI_DATAIN_BIT 3 +#endif + +.comm tpi_dly_cnt, 2 + + +/** + * TPI init + */ +.global tpi_init +tpi_init: + /* CLK <= out */ + sbi _SFR_IO_ADDR(TPI_CLK_DDR), TPI_CLK_BIT +#ifdef TPI_WITH_OPTO + /* DATAIN <= pull-up */ + cbi _SFR_IO_ADDR(TPI_DATAIN_DDR), TPI_DATAIN_BIT + sbi _SFR_IO_ADDR(TPI_DATAIN_PORT), TPI_DATAIN_BIT + /* DATAOUT <= high */ + sbi _SFR_IO_ADDR(TPI_DATAOUT_DDR), TPI_DATAOUT_BIT + sbi _SFR_IO_ADDR(TPI_DATAOUT_PORT), TPI_DATAOUT_BIT +#else + /* DATA <= pull-up */ + cbi _SFR_IO_ADDR(TPI_DATAOUT_DDR), TPI_DATAOUT_BIT + sbi _SFR_IO_ADDR(TPI_DATAOUT_PORT), TPI_DATAOUT_BIT +#endif + + /* 32 bits */ + ldi r21, 32 +1: + rcall tpi_bit_h + dec r21 + brne 1b + + ret + + +/** + * Update PR + * in: r25:r24 <= PR + * lost: r18-r21,r24,r30-r31 + */ +tpi_pr_update: + movw r20, r24 + ldi r24, TPI_OP_SSTPR(0) + rcall tpi_send_byte + mov r24, r20 + rcall tpi_send_byte + ldi r24, TPI_OP_SSTPR(1) + rcall tpi_send_byte + mov r24, r21 +// rjmp tpi_send_byte + + +/** + * Send one byte + * in: r24 <= byte + * lost: r18-r19,r30-r31 + */ +.global tpi_send_byte +tpi_send_byte: + /* start bit */ + rcall tpi_bit_l + /* 8 data bits */ + ldi r18, 8 + ldi r19, 0 +1: + // parity + eor r19, r24 + // get bit, shift + bst r24, 0 + lsr r24 + // send + rcall tpi_bit + dec r18 + brne 1b + /* parity bit */ + bst r19, 0 + rcall tpi_bit + /* 2 stop bits */ + rcall tpi_bit_h +// rjmp tpi_bit_h + + +/** + * Exchange of one bit + * in: T <= bit_in + * out: T => bit_out + * lost: r30-r31 + */ +tpi_bit_h: + set +tpi_bit: + /* TPIDATA = T */ +#ifdef TPI_WITH_OPTO + // DATAOUT = high (opto should allow TPIDATA to be pulled low by external device) + // if(T == 0) + // DATAOUT = low + sbi _SFR_IO_ADDR(TPI_DATAOUT_PORT), TPI_DATAOUT_BIT + brts 1f +tpi_bit_l: + cbi _SFR_IO_ADDR(TPI_DATAOUT_PORT), TPI_DATAOUT_BIT +1: +#else + // DATAOUT = pull-up + // if(T == 0) + // DATAOUT = low + cbi _SFR_IO_ADDR(TPI_DATAOUT_DDR), TPI_DATAOUT_BIT + sbi _SFR_IO_ADDR(TPI_DATAOUT_PORT), TPI_DATAOUT_BIT + brts 1f +tpi_bit_l: + cbi _SFR_IO_ADDR(TPI_DATAOUT_PORT), TPI_DATAOUT_BIT + sbi _SFR_IO_ADDR(TPI_DATAOUT_DDR), TPI_DATAOUT_BIT +1: +#endif + /* delay(); */ + lds r30, tpi_dly_cnt + lds r31, tpi_dly_cnt+1 +1: + sbiw r30, 1 + brsh 1b + /* TPICLK = 1 */ + sbi _SFR_IO_ADDR(TPI_CLK_PORT), TPI_CLK_BIT + /* T = TPIDATA */ + in r30, _SFR_IO_ADDR(TPI_DATAIN_PIN) + bst r30, TPI_DATAIN_BIT + /* delay(); */ + lds r30, tpi_dly_cnt + lds r31, tpi_dly_cnt+1 +1: + sbiw r30, 1 + brsh 1b + + /* TPICLK = 0 */ + cbi _SFR_IO_ADDR(TPI_CLK_PORT), TPI_CLK_BIT + ret + + +/** + * Receive one byte + * out: r24 => byte + * lost: r18-r19,r30-r31 + */ +.global tpi_recv_byte +tpi_recv_byte: + /* waitfor(start_bit, 192); */ + ldi r18, 192 +1: + rcall tpi_bit_h + brtc .tpi_recv_found_start + dec r18 + brne 1b + /* no start bit: set return value */ +.tpi_break_ret0: + ldi r24, 0 + /* send 2 breaks (24++ bits) */ + ldi r18, 26 +1: + rcall tpi_bit_l + dec r18 + brne 1b + /* send hi */ + rjmp tpi_bit_h + +// ---- +.tpi_recv_found_start: + /* recv 8bits(+calc.parity) */ + ldi r18, 8 + ldi r19, 0 +1: + rcall tpi_bit_h + lsr r24 + bld r24, 7 + eor r19, r24 + dec r18 + brne 1b + /* recv parity */ + rcall tpi_bit_h + bld r18, 7 + eor r19, r18 + brmi .tpi_break_ret0 + /* recv stop bits */ + rcall tpi_bit_h + rjmp tpi_bit_h + + +/** + * Read Block + */ +.global tpi_read_block +tpi_read_block: + // X <= dptr + movw XL, r22 + // r23 <= len + mov r23, r20 + /* set PR */ + rcall tpi_pr_update + /* read data */ +.tpi_read_loop: + ldi r24, TPI_OP_SLD_INC + rcall tpi_send_byte + rcall tpi_recv_byte + st X+, r24 + dec r23 + brne .tpi_read_loop + ret + + +/** + * Write block + */ +.global tpi_write_block +tpi_write_block: + // X <= sptr + movw XL, r22 + // r23 <= len + mov r23, r20 + /* set PR */ + rcall tpi_pr_update + /* write data */ +.tpi_write_loop: + ldi r24, TPI_OP_SOUT(NVMCMD) + rcall tpi_send_byte + ldi r24, NVMCMD_WORD_WRITE + rcall tpi_send_byte + ldi r24, TPI_OP_SST_INC + rcall tpi_send_byte + ld r24, X+ + rcall tpi_send_byte +.tpi_nvmbsy_wait: + ldi r24, TPI_OP_SIN(NVMCSR) + rcall tpi_send_byte + rcall tpi_recv_byte + andi r24, NVMCSR_BSY + brne .tpi_nvmbsy_wait + dec r23 + brne .tpi_write_loop + ret