; vim: sts=4 sw=8 et ai fdm=marker ft=asm .nolist .include "m8def.inc" .list .include "fifo_handling.inc" ; compile settings ; ============================================================================= ; SERIALDEBUG ; define SERIALDEBUG for extra debugging output ; flags and aliases ; ============================================================================= ; serial port .equ CLOCK = 4000000 .equ BAUD = 19200 .equ UBRRVAL = CLOCK/(BAUD*16)-1 ; timer1 loop, half a second with prescaler 256 .equ HALFSECOND = CLOCK/(256*2) ; leds .equ STATUSLED = 0 .equ UARTLED = 1 .equ TWILED = 2 ; fifo sizes .equ URSize = 255 ; uart receive fifo size .equ UTSize = 128 ; uart transmit fifo size .equ IRSize = 64 ; i2c receive fifo size .equ ITSize = 255 ; i2c transmit fifo size ; twi .equ TWICommandByteSize = 5 ; one twi command is 1 byte address and 4 byte data .equ ADDR = 0b1000000 ; own twi address .equ GCE = 1 ; general call enabled ; global flags .equ TWITransmission = 0 ; if bit0 is set, a twi transmission is active ; fifos {{{ ; ============================================================================= .dseg ; fifo: UReceiveFifo ; ========================== UReceiveFifo: .byte FifoControlSize + URSize ; fifo: UTransmitFifo ; ========================== UTransmitFifo: .byte FifoControlSize + UTSize ; fifo: IReceiveFifo ; ========================== IReceiveFifo: .byte FifoControlSize + IRSize ; fifo: ITransmitFifo ; ========================== ITransmitFifo: .byte FifoControlSize + ITSize .cseg ; }}} ; register definitions ; ============================================================================= .def l1 = r8 ; low working registers .def l2 = r9 .def TD1 = r10 .def w1 = r16 ; working registers .def w2 = r17 .def w3 = r18 .def w4 = r19 .def Flags = r20 ; globa flags .def TWIDC = r21 ; twi data counter register ; interrupt table {{{ ; ============================================================================= .ORG 0x0 ; reset vector rjmp reset .ORG OC1Aaddr ; timer1 CompareA interrupt handler rjmp OC1AHandler .ORG URXCaddr ; USART receive complete interrupt handler rjmp URXCHandler .ORG UDREaddr ; USART data register empty handler rjmp UDREHandler .ORG TWIaddr ; TWI data handler rjmp TWIHandler .ORG INT_VECTORS_SIZE ; program start ; }}} ; SERIALDEBUG output routines {{{ ; ============================================================================= ; DEBUG_write_uart_transmit_fifo {{{ ; ============================================================================= ; saves registers and calls write_uart_transmit_fifo DEBUG_write_uart_transmit_fifo: push w2 push l1 push l2 rcall write_uart_transmit_fifo pop l2 pop l1 pop w2 ret ; }}} ; writes an immediate value .macro DEBUG_WRITE_I .ifdef SERIALDEBUG push w1 ldi w1, @0 rcall DEBUG_write_utf pop w1 .endif .endmacro ; writes an register value .macro DEBUG_WRITE_R .ifdef SERIALDEBUG push w1 mov w1, @0 rcall DEBUG_write_utf pop w1 .endif .endmacro ; }}} ; function: reset interrupt handler {{{ ; ============================================================================= reset: ; init stack ; ======================================== ldi w1, low(RAMEND) out SPL, w1 ldi w1, high(RAMEND) out SPH, w1 ; init uart ; ======================================== ldi w1, high(UBRRVAL) out UBRRH, w1 ldi w1, low(UBRRVAL) out UBRRL, w1 ldi w1, (1< . . . . \ ldi w1, 'N' rcall write_uart_transmit_fifo .ifdef SERIALDEBUG ldi w1, 0 rcall write_uart_transmit_fifo .endif rjmp TWI_cleanup TWI_data_transmit_ack: cpi TWIDC, 0 breq TWI_send_data_finished ; if there is no data left, finish transfer DEBUG_WRITE_I 'D' DEBUG_WRITE_R TWIDC rcall read_i2c_transmit_fifo ; else read data byte and output to data register out TWDR, w1 dec TWIDC ; decrement data counter rjmp TWI_next_command TWI_data_transmit_nack: TWI_data_transmit_nack_loop: rcall read_i2c_transmit_fifo dec TWIDC brne TWI_data_transmit_nack_loop rjmp TWI_send_data_finished TWI_abitration_lost: TWI_abitration_lost_loop: rcall read_i2c_transmit_fifo dec TWIDC brne TWI_abitration_lost_loop rjmp TWI_abort TWI_send_data_finished: ; FIXME?> . . . . \ ldi w1, 'F' rcall write_uart_transmit_fifo .ifdef SERIALDEBUG mov w1, TWIDC rcall write_uart_transmit_fifo .endif in w1, TWCR ; generate stop signal ori w1, (1<