; *************************************************************************** ; defines .equ COM_MAXWAIT = 200 ; maximum loop count when waiting for rising/falling clock (TODO: Make frequency-dependant) .equ COM_BUFFER_FLAGS_DONE = 0x80 .equ COM_BUFFER_FLAGS_RECEIVED = 0x40 .equ COM_BUFFER_FLAGS_TOSEND = 0x20 .equ COM_BUFFER_FLAGS_PRIO1 = 0x08 .equ COM_BUFFER_FLAGS_PRIO0 = 0x04 .equ COM_BUFFER_FLAGS_IFACE1 = 0x02 .equ COM_BUFFER_FLAGS_IFACE0 = 0x01 .equ COM_BUFFER_PRIO_INFO = 0 .equ COM_BUFFER_PRIO_NORMAL = COM_BUFFER_FLAGS_PRIO0 .equ COM_BUFFER_PRIO_IMPORTANT = COM_BUFFER_FLAGS_PRIO1 .equ COM_BUFFER_PRIO_VITAL = (COM_BUFFER_FLAGS_PRIO0 | COM_BUFFER_FLAGS_PRIO1) .equ COM_REPEAT_INFO = 3 .equ COM_REPEAT_NORMAL = 32 .equ COM_REPEAT_IMPORTANT = 64 .equ COM_REPEAT_VITAL = 255 .equ COM_CMD_PING = 1 ; *************************************************************************** ; data .dseg comDataBegin: comFlags: .byte 1 comAddress: .byte 1 comRepeatCount: .byte 1 comReserved1: .byte 1 comStatsPacketsIn: .byte 2 comStatsPacketsOut: .byte 2 comStatsRecvErrs: .byte 2 comStatsCollisions: .byte 2 comStatsMissed: .byte 2 comStatsAborted: .byte 2 comStatsIgnored: .byte 2 comStatsHandled: .byte 2 comRingBuffer: .byte RINGBUFFER_OFFS_DATA+COM_RINGBUFFER_SIZE comDataEnd: ; *************************************************************************** ; code .cseg ; --------------------------------------------------------------------------- ; Com_Init ; ; IN: ; OUT: ; - CFLAG: set if okay, clear on error ; USED: R16, R17, X, Y Com_Init: ; preset SRAM data area ldi xh, HIGH(comDataBegin) ldi xl, LOW(comDataBegin) clr r16 ldi r17, (comDataEnd-comDataBegin) rcall Utils_FillSram ; init ringbuffer ldi r16, COM_RINGBUFFER_SIZE ldi yl, LOW(comRingBuffer) ldi yh, HIGH(comRingBuffer) rcall RingBuffer_Init ; setup pins and interrupts cbi COM_PORT_DATA, COM_PINNUM_DATA ; disable internal pullup for DATA sbi COM_DDR_DATA, COM_PINNUM_DATA ; set DATA port as input cbi COM_PORT_ATTN, COM_PINNUM_ATTN ; disable internal pullup for ATTN sbi COM_DDR_ATTN, COM_PINNUM_ATTN ; set ATTN port as input sbi COM_IRQ_ADDR_ATTN, COM_IRQ_BIT_ATTN ; enable pin change irq for ATTN line in r16, GIMSK ; enable pin change irq PCIE0 or PCIE1 ori r16, (1< CARRY brcs comSendByte_setHigh ; HI: +2, LO: +1 comSendByte_setLow: sbi COM_DDR_DATA, COM_PINNUM_DATA ; +2 set DATA as output nop rjmp comSendByte_waitBit ; +2 comSendByte_setHigh: cbi COM_DDR_DATA, COM_PINNUM_DATA ; +2 set DATA as input, pullup R makes it ONE nop ; +1 (to make pin change available) sbis COM_PIN_DATA, COM_PINNUM_DATA ; +1 if okay, +2 otherwise rjmp comSendByte_error ; +2 if error comSendByte_waitBit: ; 7 cycles in this loop until now Utils_WaitNanoSecs COM_BIT_LENGTH, 10, r22 dec r21 ; +1 brne comSendByte_loop ; +2, sum per loop: 10 cycles ; send stopbit cbi COM_DDR_DATA, COM_PINNUM_DATA ; +2 set DATA as input, pullup R makes it ONE Utils_WaitNanoSecs COM_BIT_LENGTH, 4, r22 sec ret comSendByte_error: clc ret ; --------------------------------------------------------------------------- ; comReceiveByte ; ; Receive a byte. ; ; IN: ; - nothing ; OUT: ; - CFLAG: set if okay, clear otherwise ; - R16: byte read (if CFLAG set) ; MODIFIED REGS: R16, R20, R21, R22 (R17) comReceiveByte: sbi COM_DDR_DATA, COM_PINNUM_DATA ; set DATA port as input cbi COM_PORT_DATA, COM_PINNUM_DATA ; disable internal pullup for DATA ldi r21, 8 ; bits left clr r20 ; byte currently receiving ; wait for startbit rcall comWaitForDataLow brcc comReceiveByte_error Utils_WaitNanoSecs COM_BIT_LENGTH/2, 5, r22 ; goto middle of startbit to maximize sync stability comReceiveByte_loop: Utils_WaitNanoSecs COM_BIT_LENGTH, 8, r22 ; 8 cycles used in the complete loop between waits sec ; +1 sbic COM_PIN_DATA, COM_PINNUM_DATA ; LOW: +2, HIGH: +1 rjmp comReceiveByte_shiftIn ; HIGH: +2, rjmp, use set CFLAG clc ; LOW: +1 comReceiveByte_shiftIn: ror r20 ; +1 dec r21 ; +1 brne comReceiveByte_loop ; +2, sum per loop: 8 cycles rcall comWaitForDataHigh ; wait for start of stopbit ; brcc comReceiveByte_error mov r16, r20 sec ret comReceiveByte_error: clc ret ; --------------------------------------------------------------------------- ; comWaitForDataLow ; ; Waits up to COM_MAXWAIT loops for low data line ; IN: ; OUT: ; - CFLAG: set if okay, clear otherwise ; MODIFIED REGISTERS: r17, r22, X comWaitForDataLow: ldi r17, COM_MAXWAIT comWaitForDataLow_loop: sbis COM_PIN_DATA, COM_PINNUM_DATA rjmp comWaitForDataLow_done dec r17 brne comWaitForDataLow_loop clc ; timeout ret comWaitForDataLow_done: sec ; ok ret ; --------------------------------------------------------------------------- ; comWaitForDataHigh ; ; Waits up to COM_MAXWAIT loops for high data line ; IN: ; OUT: ; - CFLAG: set if okay, clear otherwise ; MODIFIED REGISTERS: r17, r22, X comWaitForDataHigh: ldi r17, COM_MAXWAIT comWaitForDataHigh_loop: sbic COM_PIN_DATA, COM_PINNUM_DATA rjmp comWaitForDataHigh_done dec r17 brne comWaitForDataHigh_loop clc ; timeout ret comWaitForDataHigh_done: sec ; ok ret