avr: improved protocol timing for COM2.

- increased waiting time after lowering ATTN line
- lengthten stop bit for cleaner frames (now recognized by PulseView)
- count "NOTFORME" conditions
- introduce definition COM_HALFBIT_LENGTH (I dont' trust value calculations
  in avrasm)
This commit is contained in:
Martin Preuss
2024-09-29 14:59:19 +02:00
parent b93ead5e5f
commit 5767c1307d
9 changed files with 88 additions and 30 deletions

View File

@@ -47,7 +47,8 @@
; ---------------------------------------------------------------------------
; COM module
.equ COM_BIT_LENGTH = 52000 ; 104000=9600, 52000=19200, 26000=38400
.equ COM_BIT_LENGTH = 52000 ; 104000ns=9600, 52000ns=19200, 26000ns=38400
.equ COM_HALFBIT_LENGTH = 26000 ; see https://de.wikipedia.org/wiki/Universal_Asynchronous_Receiver_Transmitter
.equ COM_DDR_DATA = DDRA
.equ COM_PORT_DATA = PORTA

View File

@@ -47,7 +47,8 @@
; ---------------------------------------------------------------------------
; COM module
.equ COM_BIT_LENGTH = 52000 ; 104000=9600, 52000=19200, 26000=38400
.equ COM_BIT_LENGTH = 52000 ; 104000ns=9600, 52000ns=19200, 26000ns=38400
.equ COM_HALFBIT_LENGTH = 26000 ; see https://de.wikipedia.org/wiki/Universal_Asynchronous_Receiver_Transmitter
.equ COM_DDR_DATA = DDRA
.equ COM_PORT_DATA = PORTA
@@ -60,7 +61,7 @@
.equ COM_PINNUM_ATTN = PORTA7
.equ COM_IRQ_ADDR_ATTN = PCMSK0
.equ COM_IRQ_BIT_ATTN = 7 ; bit 7 in PCMSK0
.equ COM_IRQ_BIT_ATTN = PCINT7 ; bit 7 in PCMSK0
.equ COM_IRQ_GIFR_ATTN = PCIF0
.equ COM_IRQ_GIMSK_ATTN = PCIE0

View File

@@ -47,7 +47,7 @@
; COM module
.equ COM_BIT_LENGTH = 52000 ; 104000ns=9600, 52000ns=19200, 26000ns=38400
; see https://de.wikipedia.org/wiki/Universal_Asynchronous_Receiver_Transmitter
.equ COM_HALFBIT_LENGTH = 26000 ; see https://de.wikipedia.org/wiki/Universal_Asynchronous_Receiver_Transmitter
.equ COM_DDR_DATA = DDRA
.equ COM_PORT_DATA = PORTA
.equ COM_PIN_DATA = PINA
@@ -59,7 +59,7 @@
.equ COM_PINNUM_ATTN = PORTA7
.equ COM_IRQ_ADDR_ATTN = PCMSK0
.equ COM_IRQ_BIT_ATTN = 7 ; bit 7 in PCMSK0
.equ COM_IRQ_BIT_ATTN = PCINT7 ; bit 7 in PCMSK0
.equ COM_IRQ_GIFR_ATTN = PCIF0
.equ COM_IRQ_GIMSK_ATTN = PCIE0

View File

@@ -161,6 +161,10 @@ firmwareStart: rjmp main
.include "modules/comproto/msg_device.asm"
.include "modules/comproto/msg_reboot.asm"
#endif
#ifdef MODULES_LCD
.include "modules/com2/screen.asm"
.include "modules/comproto/screen.asm"
#endif
#endif
#ifdef MODULES_TWI_MASTER
.include "modules/twimaster/main.asm"
@@ -194,9 +198,18 @@ firmwareStart: rjmp main
.dseg
programRamBegin:
#ifdef MODULES_LCD
screenCounter: .byte 1
#endif
programRamEnd:
#ifdef MODULES_LCD
sramTimerWriteStats: .byte 2
sramTimerScreen: .byte 2
#endif
sramTimerEnqueueValues: .byte 2
#ifdef MODULES_SI7021
@@ -221,12 +234,6 @@ sramTimerEnqueueValues: .byte 2
.cseg
#ifdef MODULES_LED
ledA3Flash: .db DDRA+0x20, PORTA+0x20, PINA+0x20, (1<<PORTA3)
blinkPattern: .db 2, 50, 0xff, 0xff ; 1 short blink, 5s pause, restart
;blinkPattern2: .db 2, 2, 0xff, 0xff ; 1 short blink, short pause, restart
#endif
; ---------------------------------------------------------------------------
@@ -242,8 +249,9 @@ timerList:
.dw statsSendTimer, Stats_Timer, TIMER_FLAGS_IF_ADDR, 3000 ; every 5m
#endif
#ifdef MODULES_LCD
; .dw sramPeriodicalLcdMark, periodicalLcdMark, 0, 20 ; every 2s
.dw sramTimerWriteStats, writeStats, 0, 100
; .dw sramPeriodicalLcdMark, periodicalLcdMark, 0, 20 ; every 2s
; .dw sramTimerWriteStats, writeStats, 0, 100
.dw sramTimerScreen, printScreen, TIMER_FLAGS_IF_ADDR, 50 ; every 5s
#endif
#ifdef MODULES_SI7021
.dw sramTimerSI7021Measure, SI7021_OnTimer, 0, 300 ; every 30s
@@ -292,18 +300,55 @@ systemSetBootSpeed:
; Called on first time run, i.e. on system start. No arguments, no results.
onSystemStart:
ldi xh, HIGH(programRamBegin)
ldi xl, LOW(programRamBegin)
clr r16
ldi r17, (programRamEnd-programRamBegin)
rcall Utils_FillSram
ret
#ifdef MODULES_LCD
periodicalLcdMark:
rcall printTimerMark
printScreen:
lds r16, screenCounter
tst r16
brne printScreen_l1
rcall CPRO_Screen
rjmp printScreen_counter
printScreen_l1:
cpi r16, 1
brne printScreen_l2
rcall COM2_Screen_RecvStats
rjmp printScreen_counter
printScreen_l2:
; cpi r16, 2
; brne printScreen_l3
; rcall COM2_Screen_SendStats
; rjmp printScreen_counter
printScreen_l3:
; add more screens here
printScreen_counter:
lds r16, screenCounter
inc r16
cpi r16, 2 ; number of screens
brcs printScreen_store
clr r16
printScreen_store:
sts screenCounter, r16
printScreen_end:
ret
writeStats:
rcall printSendStats
ret
;periodicalLcdMark:
; rcall printTimerMark
; ret
;writeStats:
; rcall printSendStats
; ret
#endif

View File

@@ -45,7 +45,8 @@
; ---------------------------------------------------------------------------
; COM module
.equ COM_BIT_LENGTH = 52000 ; 104000=9600, 52000=19200, 26000=38400
.equ COM_BIT_LENGTH = 52000 ; 104000ns=9600, 52000ns=19200, 26000ns=38400
.equ COM_HALFBIT_LENGTH = 26000 ; see https://de.wikipedia.org/wiki/Universal_Asynchronous_Receiver_Transmitter
.equ COM_DDR_DATA = DDRA
.equ COM_PORT_DATA = PORTA

View File

@@ -42,7 +42,8 @@
; ---------------------------------------------------------------------------
; COM module
.equ COM_BIT_LENGTH = 52000 ; 104000=9600, 52000=19200, 26000=38400
.equ COM_BIT_LENGTH = 52000 ; 104000ns=9600, 52000ns=19200, 26000ns=38400
.equ COM_HALFBIT_LENGTH = 26000 ; see https://de.wikipedia.org/wiki/Universal_Asynchronous_Receiver_Transmitter
.equ COM_DDR_DATA = DDRB
.equ COM_PORT_DATA = PORTB

View File

@@ -31,7 +31,7 @@ com2SendByte:
; send startbit
cbi COM_PORT_DATA, COM_PINNUM_DATA ; +2 set DATA low
sbi COM_DDR_DATA, COM_PINNUM_DATA ; +2 set DATA as output
Utils_WaitNanoSecs COM_BIT_LENGTH, 5, r22 ; wait for one bit duration
Utils_WaitNanoSecs COM_BIT_LENGTH, 1, r22 ; wait for one bit duration
; send data bits
com2SendByte_loop: ; 9 for low bit
lsr r16 ; 1+ bit to send -> CARRY
@@ -43,16 +43,16 @@ com2SendByte_setLow:
com2SendByte_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)
Utils_WaitNanoSecs COM_BIT_LENGTH/2, 11, r22 ; wait for half a bit length for line to safely settle
Utils_WaitNanoSecs COM_HALFBIT_LENGTH, 0, r22 ; wait for half a bit length for line to safely settle
sbis COM_PIN_DATA, COM_PINNUM_DATA ; +1 if no skip, +2 if skipped
rjmp com2SendByte_error ; +2 if error (collision: we wanted line to be high but it is low)
Utils_WaitNanoSecs COM_BIT_LENGTH/2, 0, r22
Utils_WaitNanoSecs COM_HALFBIT_LENGTH, 11, r22
com2SendByte_loopEnd:
dec r21 ; +1
brne com2SendByte_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 ; wait for one bit length
Utils_WaitNanoSecs COM_BIT_LENGTH, 0, r22 ; wait for one bit length
rjmp com2LowLevelSecRet
com2SendByte_error:
@@ -81,7 +81,7 @@ com2ReceiveByte:
; wait for startbit
rcall com2WaitForDataLow ; (R16, R17, R22)
brcc com2ReceiveByte_error
Utils_WaitNanoSecs COM_BIT_LENGTH/2, 5, r22 ; goto middle of startbit to maximize sync stability
Utils_WaitNanoSecs COM_HALFBIT_LENGTH, 10, r22 ; goto middle of startbit to maximize sync stability
com2ReceiveByte_loop:
Utils_WaitNanoSecs COM_BIT_LENGTH, 8, r22 ; 8 cycles used in the complete loop between waits
sec ; +1
@@ -149,7 +149,7 @@ com2WaitForAttnHigh:
; ---------------------------------------------------------------------------
; com2WaitForDataState1ms
;
; Waits up to 1ms for high DATA line
; Waits up to 500us for high DATA line
; IN:
; - R16: state to wait for (00 for low, 0xff for high)
; OUT:
@@ -163,12 +163,14 @@ com2WaitForDataState1ms_loop:
eor r22, r16
andi r22, (1<<COM_PINNUM_DATA)
breq com2WaitForDataState1ms_stateReached
rcall Utils_WaitFor10MicroSecs ; wait for 10us (R22)
; rcall Utils_WaitFor10MicroSecs ; wait for 10us (R22)
Utils_WaitNanoSecs 5000, 0, r22
dec r17
brne com2WaitForDataState1ms_loop
rjmp com2LowLevelClcRet
com2WaitForDataState1ms_stateReached:
rjmp com2LowLevelSecRet
sec
ret

View File

@@ -26,6 +26,7 @@ com2RecvStatsBegin: ; 12 bytes
com2StatsIoError: .byte 2
com2StatsNoBufferError: .byte 2
com2StatsHandled: .byte 2
com2StatsNotForMe: .byte 2
com2StatsMissed: .byte 2 ; currently not used
com2RecvStatsEnd:
@@ -331,6 +332,8 @@ com2ReceivePacket_error:
breq com2ReceivePacket_ioError
cpi r16, COM2_ERROR_DATAERROR
breq com2ReceivePacket_dataError
cpi r16, COM2_ERROR_NOTFORME
breq com2ReceivePacket_notForMe
rjmp com2ReceivePacket_retnc
com2ReceivePacket_ioError:
ldi xl, LOW(com2StatsIoError)
@@ -340,6 +343,10 @@ com2ReceivePacket_dataError:
ldi xl, LOW(com2StatsContentError)
ldi xh, HIGH(com2StatsContentError)
rjmp com2ReceivePacket_incCounterDeallocNc
com2ReceivePacket_notForMe:
ldi xl, LOW(com2StatsNotForMe)
ldi xh, HIGH(com2StatsNotForMe)
rjmp com2ReceivePacket_incCounterDeallocNc
com2ReceivePacket_incCounterDeallocNc:
rcall Utils_IncrementCounter16 ; (r18, r19, 22)
com2ReceivePacket_deallocRetnc:

View File

@@ -77,7 +77,6 @@ COM2_SendPacketWithAttn:
push r15
in r15, SREG
cli
; rcall com2WaitForOneBitLength ; wait for one bit duration (R22)
; check for ATTN line: busy?
cbi COM_PORT_ATTN, COM_PINNUM_ATTN ; disable pullup on ATTN
cbi COM_DDR_ATTN, COM_PINNUM_ATTN ; set ATTN as input
@@ -87,7 +86,8 @@ COM2_SendPacketWithAttn:
cbi COM_PORT_ATTN, COM_PINNUM_ATTN ; set ATTN low
sbi COM_DDR_ATTN, COM_PINNUM_ATTN ; set ATTN as output
rcall com2WaitForOneBitLength ; wait for one bit duration (R22)
rcall com2WaitForOneBitLength ; wait for one bit duration (R22)
rcall com2WaitForOneBitLength ; wait for another bit duration (R22)
adiw xh:xl, COM2_MSG_OFFS_MSGLEN
ld r16, X