/*** \brief Size-optimized code for TPI* \file tpi.s* \author S³awomir Fra*/#include <avr/io.h>#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_inittpi_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_BITsbi _SFR_IO_ADDR(TPI_DATAIN_PORT), TPI_DATAIN_BIT/* DATAOUT <= high */sbi _SFR_IO_ADDR(TPI_DATAOUT_DDR), TPI_DATAOUT_BITsbi _SFR_IO_ADDR(TPI_DATAOUT_PORT), TPI_DATAOUT_BIT#else/* DATA <= pull-up */cbi _SFR_IO_ADDR(TPI_DATAOUT_DDR), TPI_DATAOUT_BITsbi _SFR_IO_ADDR(TPI_DATAOUT_PORT), TPI_DATAOUT_BIT#endif/* 32 bits */ldi r21, 321:rcall tpi_bit_hdec r21brne 1bret/*** Update PR* in: r25:r24 <= PR* lost: r18-r21,r24,r30-r31*/tpi_pr_update:movw r20, r24ldi r24, TPI_OP_SSTPR(0)rcall tpi_send_bytemov r24, r20rcall tpi_send_byteldi r24, TPI_OP_SSTPR(1)rcall tpi_send_bytemov r24, r21// rjmp tpi_send_byte/*** Send one byte* in: r24 <= byte* lost: r18-r19,r30-r31*/.global tpi_send_bytetpi_send_byte:/* start bit */rcall tpi_bit_l/* 8 data bits */ldi r18, 8ldi r19, 01:// parityeor r19, r24// get bit, shiftbst r24, 0lsr r24// sendrcall tpi_bitdec r18brne 1b/* parity bit */bst r19, 0rcall 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:settpi_bit:/* TPIDATA = T */#ifdef TPI_WITH_OPTO// DATAOUT = high (opto should allow TPIDATA to be pulled low by external device)// if(T == 0)// DATAOUT = lowsbi _SFR_IO_ADDR(TPI_DATAOUT_PORT), TPI_DATAOUT_BITbrts 1ftpi_bit_l:cbi _SFR_IO_ADDR(TPI_DATAOUT_PORT), TPI_DATAOUT_BIT1:#else// DATAOUT = pull-up// if(T == 0)// DATAOUT = lowcbi _SFR_IO_ADDR(TPI_DATAOUT_DDR), TPI_DATAOUT_BITsbi _SFR_IO_ADDR(TPI_DATAOUT_PORT), TPI_DATAOUT_BITbrts 1ftpi_bit_l:cbi _SFR_IO_ADDR(TPI_DATAOUT_PORT), TPI_DATAOUT_BITsbi _SFR_IO_ADDR(TPI_DATAOUT_DDR), TPI_DATAOUT_BIT1:#endif/* delay(); */lds r30, tpi_dly_cntlds r31, tpi_dly_cnt+11:sbiw r30, 1brsh 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_cntlds r31, tpi_dly_cnt+11:sbiw r30, 1brsh 1b/* TPICLK = 0 */cbi _SFR_IO_ADDR(TPI_CLK_PORT), TPI_CLK_BITret/*** Receive one byte* out: r24 => byte* lost: r18-r19,r30-r31*/.global tpi_recv_bytetpi_recv_byte:/* waitfor(start_bit, 192); */ldi r18, 1921:rcall tpi_bit_hbrtc .tpi_recv_found_startdec r18brne 1b/* no start bit: set return value */.tpi_break_ret0:ldi r24, 0/* send 2 breaks (24++ bits) */ldi r18, 261:rcall tpi_bit_ldec r18brne 1b/* send hi */rjmp tpi_bit_h// ----.tpi_recv_found_start:/* recv 8bits(+calc.parity) */ldi r18, 8ldi r19, 01:rcall tpi_bit_hlsr r24bld r24, 7eor r19, r24dec r18brne 1b/* recv parity */rcall tpi_bit_hbld r18, 7eor r19, r18brmi .tpi_break_ret0/* recv stop bits */rcall tpi_bit_hrjmp tpi_bit_h/*** Read Block*/.global tpi_read_blocktpi_read_block:// X <= dptrmovw XL, r22// r23 <= lenmov r23, r20/* set PR */rcall tpi_pr_update/* read data */.tpi_read_loop:ldi r24, TPI_OP_SLD_INCrcall tpi_send_bytercall tpi_recv_bytest X+, r24dec r23brne .tpi_read_loopret/*** Write block*/.global tpi_write_blocktpi_write_block:// X <= sptrmovw XL, r22// r23 <= lenmov r23, r20/* set PR */rcall tpi_pr_update/* write data */.tpi_write_loop:ldi r24, TPI_OP_SOUT(NVMCMD)rcall tpi_send_byteldi r24, NVMCMD_WORD_WRITErcall tpi_send_byteldi r24, TPI_OP_SST_INCrcall tpi_send_byteld r24, X+rcall tpi_send_byte.tpi_nvmbsy_wait:ldi r24, TPI_OP_SIN(NVMCSR)rcall tpi_send_bytercall tpi_recv_byteandi r24, NVMCSR_BSYbrne .tpi_nvmbsy_waitdec r23brne .tpi_write_loopret