3 Commits

Author SHA1 Message Date
Martin Preuss
deddf42379 First try to unify ATTN handling. 2025-05-29 14:32:48 +02:00
Martin Preuss
e584245965 c01: added defs when using uart_bitbang2. 2025-05-29 14:32:29 +02:00
Martin Preuss
46720d791c avr: some ideas for autosync. 2025-05-29 12:47:41 +02:00
4 changed files with 457 additions and 1 deletions

278
avr/devices/all/attn.asm Normal file
View File

@@ -0,0 +1,278 @@
; ***************************************************************************
; copyright : (C) 2025 by Martin Preuss
; email : martin@libchipcard.de
;
; ***************************************************************************
; * This file is part of the project "AqHome". *
; * Please see toplevel file COPYING of that project for license details. *
; ***************************************************************************
; not used for now
; ***************************************************************************
; macros
.macro mAttnInitInt0
; select falling edge of ATTN
inr r16, MCUCR
cbr r16, (1<<ISC01) | (1<<ISC00)
sbr r16, (1<<ISC01) | (0<<ISC00)
outr MCUCR, r16
.endmacro
.macro mAttnInitPCI
in r16, GIMSK ; enable pin change irq PCIE0 or PCIE1
ori r16, (1<<COM_IRQ_GIMSK_ATTN)
out GIMSK, R16
ldi r16, (1<<COM_IRQ_GIFR_ATTN) ; clear pending irq by writing 1 to ATTN bit
out GIFR, r16
.endmacro
.macro mAttnEnableIrqInt0
inr r16, COM_IRQ_ADDR_ATTN
sbr r16, (1<<ATTN_IRQ_BIT)
outr COM_IRQ_ADDR_ATTN, r16
.endmacro
.macro mAttnEnableIrqPCI
sbi COM_IRQ_ADDR_ATTN, ATTN_IRQ_BIT ; enable pin change irq for ATTN line
.endmacro
.macro mAttnDisableIrqInt0
inr r16, COM_IRQ_ADDR_ATTN ; disable irq for ATTN line
cbr r16, (1<<ATTN_IRQ_BIT)
outr COM_IRQ_ADDR_ATTN, r16
.endmacro
.macro mAttnDisableIrqPCI
cbi COM_IRQ_ADDR_ATTN, ATTN_IRQ_BIT ; disable pin change irq for ATTN line
.endmacro
; ***************************************************************************
; code
.cseg
; ---------------------------------------------------------------------------
; @routine ATTN_Init @global
;
; @clobbers R16
ATTN_Init:
.ifdef INT0
.if ATTN_IRQ_BIT == INT0
mAttnInitInt0
.else
mAttnInitPCI
.endif
.else
mAttnInitPCI
.endif
rcall ATTN_SetHighEnableIrq
sec
ret
; @end
; ---------------------------------------------------------------------------
; @routine ATTN_SetLowDisableIrq @global
;
; @clobbers R16
ATTN_SetLowDisableIrq:
.ifdef INT0
.if ATTN_IRQ_BIT == INT0
mAttnDisableIrqInt0
.else
mAttnDisableIrqPCI
.endif
.else
mAttnDisableIrqPCI
.endif
sbi ATTN_DDR, ATTN_PIN ; set ATTN as output
cbi ATTN_OUTPUT, ATTN_PIN ; set ATTN low
ret
; @end
; ---------------------------------------------------------------------------
; @routine ATTN_SetHighEnableIrq @global
;
; @clobbers R16
ATTN_SetHighEnableIrq:
cbi ATTN_DDR, ATTN_PIN ; set ATTN as input
.ifdef ATTN_PUE
cbi ATTN_PUE, ATTN_PIN ; disable pullup on ATTN
.else
cbi ATTN_OUTPUT, ATTN_PIN ; disable pullup on ATTN
.endif
.ifdef INT0
.if ATTN_IRQ_BIT == INT0
mAttnEnableIrqInt0
.else
mAttnEnableIrqPCI
.endif
.else
mAttnEnableIrqPCI
.endif
ret
; @end
; ---------------------------------------------------------------------------
; @routine ATTN_IsHigh @global
;
; @return CFLAG set if ATTN is high
; @clobbers none
ATTN_IsHigh:
clc
sbic ATTN_INPUT, ATTN_PIN ; ATTN low?
sec ; yes, set CF
ret
; @end
; ---------------------------------------------------------------------------
; @routine ATTN_WaitForStateSeconds
;
; Wait for ATTN state max given seconds
;
; @return CFLAG set if okay (data available), cleared on error
; @param R16 expected state (0xff for high, 0 for low)
; @param r20 maximum number of seconds to wait
; @clobbers: r20, r22
ATTN_WaitForStateSeconds:
ATTN_WaitForStateSeconds_loop:
push r20
rcall ATTN_WaitForState1s ; (r20, r22)
pop r20
brcs ATTN_WaitForStateSeconds_gotit
sbi LED_PIN, LED_PINNUM ; toggle (doen't work on AtMega8515)
dec r20
brne ATTN_WaitForStateSeconds_loop
clc
ATTN_WaitForStateSeconds_gotit:
ret
; @end
; ---------------------------------------------------------------------------
; @routine ATTN_WaitForState1s
;
; Wait for ATTN state for max 1s
;
; @param R16 expected state (0xff for high, 0 for low)
; @return CFLAG set if okay (ATTN state reached), cleared on error
; @clobbers: r20, r22
ATTN_WaitForState1s:
ldi r20, 100
ATTN_WaitForState1s_loop:
push r20
rcall ATTN_WaitForState10ms ; (R20, R22)
pop r20
brcs ATTN_WaitForState1s_gotit
dec r20
brne ATTN_WaitForState1s_loop
clc
ATTN_WaitForState1s_gotit:
ret
; @end
; ---------------------------------------------------------------------------
; @routine ATTN_WaitForState10ms
;
; Wait for ATTN state for max 10 milliseconds.
;
; @param R16 expected state (0xff for high, 0 for low)
; @return CFLAG set if okay (ATTN state reached), cleared on error
; @clobbers: r20, r22
ATTN_WaitForState10ms:
.if clock == 8000000
ldi r20, 80
.endif
.if clock == 1000000
ldi r20, 10
.endif
ATTN_WaitForState10ms_loop:
push r20
rcall ATTN_WaitForState1000Cycles ; (r20, r22)
pop r20
brcs ATTN_WaitForState10ms_gotit
dec r20
brne ATTN_WaitForState10ms_loop
clc
ATTN_WaitForState10ms_gotit:
ret
; @end
; ---------------------------------------------------------------------------
; @routine ATTN_WaitForStateState1000Cycles
;
; Wait for ATTN state for max 1000 clock cycles
; (about 1ms at 1MHz, 0.125ms at 8MHz)
;
; @param R16 expected state (0xff for high, 0 for low)
; @return CFLAG set if okay (packet received), cleared on error
; @clobbers: r20, r22
ATTN_WaitForState1000Cycles:
ldi r20, 90 ; 1
ATTN_WaitForState1000Cycles_loop:
push r17 ; +2
in r17, COM_ATTN_INPUT ; +1
eor r17, r16 ; +1
andi r17, (1<<COM_ATTN_PIN) ; +1
pop r17 ; +2
breq ATTN_WaitForState1000Cycles_stateReached ; +1
dec r20 ; +1
brne ATTN_WaitForState1000Cycles_loop ; +2
clc
ret
ATTN_WaitForState1000Cycles_stateReached:
sec
ret
; @end

View File

@@ -67,6 +67,12 @@
.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_DATA_DDR = DDRD ; use RX pin
.equ COM_DATA_INPUT = PIND
.equ COM_DATA_OUTPUT = PORTD
.equ COM_DATA_PIN = PORTD0
.equ COM_ATTN_DDR = DDRD
.equ COM_ATTN_INPUT = PIND
.equ COM_ATTN_OUTPUT = PORTD

View File

@@ -61,6 +61,8 @@
#define MODULES_NETWORK
;#define MODULES_COMONUART0
#define MODULES_UART_HW
;#define MODULES_UART_BITBANG
#define MODULES_SPI_HW
#define MODULES_ILI9341
;#define MODULES_FONT_8X8
@@ -221,6 +223,6 @@ onEveryLoop:
; defines for network interface
.equ netInterfaceData = netUartIface
;.equ netInterfaceData = uart_bitbang_iface

View File

@@ -0,0 +1,170 @@
; ***************************************************************************
; copyright : (C) 2025 by Martin Preuss
; email : martin@libchipcard.de
;
; ***************************************************************************
; * This file is part of the project "AqHome". *
; * Please see toplevel file COPYING of that project for license details. *
; ***************************************************************************
.equ UARTSOFT_WAITFORSYNCSTART = 200
; ***************************************************************************
; code
.cseg
uartSoftWaitAndReadSyncByte:
; wait for begin of startbit
ldi r24, LOW(UARTSOFT_WAITFORSYNCSTART)
ldi r25, HIGH(UARTSOFT_WAITFORSYNCSTART)
uartSoftWaitAndReadSyncByte_loop0:
sbis COM_DATA_INPUT, COM_DATA_PIN
rjmp uartSoftWaitAndReadSyncByte_gotStartBit
sbiw r25:r24, 1
brne uartSoftWaitAndReadSyncByte_loop0
uartSoftWaitAndReadSyncByte_error: ; timeout
clc
ret
uartSoftWaitAndReadSyncByte_gotStartBit:
clr r25
clr r24
; count cycles while DATA low (count length of startBit)
uartSoftWaitAndReadSyncByte_loopLow: ; 5 cycles per loop +3 cycles to leave loop
sbic COM_DATA_INPUT, COM_DATA_PIN ; +2 (skip)/+1 (no skip)
rjmp uartSoftWaitAndReadSyncByte_startDataBit1 ; +0 (skip) / +2 (no skip)
adiw r25:r24, 1 ; +1
brne uartSoftWaitAndReadSyncByte_loopLow ; +2
rjmp uartSoftWaitAndReadSyncByte_error
uartSoftWaitAndReadSyncByte_startDataBit1:
clr r25
clr r24
ldi r17, 4
uartSoftWaitAndReadSyncByte_loopData:
; count cycles while DATA high (count length of dataBit)
uartSoftWaitAndReadSyncByte_loopDataHigh: ; 5 cycles per loop +3 cycles to leave loop
sbis COM_DATA_INPUT, COM_DATA_PIN ; +2 (skip)/+1 (no skip)
rjmp uartSoftWaitAndReadSyncByte_startLowDataBit ; +0 (skip) / +2 (no skip)
adiw r25:r24, 1 ; +1
brne uartSoftWaitAndReadSyncByte_loopDataHigh ; +2
; too long LOW
rjmp uartSoftWaitAndReadSyncByte_error
uartSoftWaitAndReadSyncByte_startLowDataBit:
; count cycles while DATA low (count length of dataBit)
uartSoftWaitAndReadSyncByte_loopDataLow: ; 5 cycles per loop +3 cycles to leave loop
sbic COM_DATA_INPUT, COM_DATA_PIN ; +2 (skip)/+1 (no skip)
rjmp uartSoftWaitAndReadSyncByte_startHighDataBit ; +0 (skip) / +2 (no skip)
adiw r25:r24, 1 ; +1
brne uartSoftWaitAndReadSyncByte_loop4 ; +2
; too long LOW
rjmp uartSoftWaitAndReadSyncByte_error
uartSoftWaitAndReadSyncByte_startHighDataBit:
dec r17
brne uartSoftWaitAndReadSyncByte_loopData
; calc average (8 values)
lsr r25 ; /2
ror r24
lsr r25 ; /4
ror r24
lsr r25 ; /8
ror r24
sec
ret
; @end
uartSoftReceiveByte:
; wait for begin of startbit
ldi r24, LOW(UARTSOFT_WAITFORSYNCSTART)
ldi r25, HIGH(UARTSOFT_WAITFORSYNCSTART)
uartSoftReceiveByte_waitForBeginOfStartBit:
sbis COM_DATA_INPUT, COM_DATA_PIN
rjmp uartSoftReceiveByte_gotBeginOfStartBit
sbiw r25:r24, 1
brne uartSoftReceiveByte_waitForBeginOfStartBit
uartSoftReceiveByte_error: ; timeout
clc
ret
uartSoftReceiveByte_gotBeginOfStartBit:
clr r25
clr r24
; count cycles while DATA low (count length of startBit)
uartSoftReceiveByte_waitForEndOfStartBit: ; 5 cycles per loop
sbic COM_DATA_INPUT, COM_DATA_PIN ; +2 (skip)/+1 (no skip)
rjmp uartSoftReceiveByte_gotEndOfStartBit ; +0 (skip) / +2 (no skip)
adiw r25:r24, 1 ; +1
brne uartSoftWaitAndReadSyncByte_loopLow ; +2
rjmp uartSoftReceiveByte_error
uartSoftReceiveByte_gotEndOfStartBit:
; r25:r24=counter equivalent for length of startbit
clr r16
ldi r17, 8
uartSoftReceiveByte_bitLoop:
; TODO: receive 8bits, wait for start of endbit
ret
uartSoftCountDataLow: ; 5 cycles per loop +5 cycles outside (+3 cycles RCALL)
sbic COM_DATA_INPUT, COM_DATA_PIN ; +2 (skip)/+1 (no skip)
rjmp uartSoftCountDataLow_ok ; +0 (skip) / +2 (no skip)
adiw r25:r24, 1 ; +1
brne uartSoftCountDataLow ; +2
clc
ret
uartSoftCountDataLow_ok:
sec
ret
; @end
uartSoftCountDataHigh: ; 5 cycles per loop +5 cycles outside (+3 cycles RCALL)
sbis COM_DATA_INPUT, COM_DATA_PIN ; +2 (skip)/+1 (no skip)
rjmp uartSoftCountDataHigh_ok ; +0 (skip) / +2 (no skip)
adiw r25:r24, 1 ; +1
brne uartSoftCountDataHigh ; +2
clc
ret
uartSoftCountDataHigh_ok:
sec ; +1
ret ; +4
; @end
uartSoftWaitBitTime: ; 5 cycles per loop +5 cycles outside (+3 cycles RCALL)
uartSoftWaitBitTime_loop:
nop ; +1
nop ; +1
sbiw r25:r24, 1 ; +1
brne uartSoftWaitBitTime_loop ; +2
nop ; +1
ret ; +4
; @end