; *************************************************************************** ; 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. * ; *************************************************************************** #ifndef AVR_MODULES_COM2W_COM2WN_RUN_H #define AVR_MODULES_COM2W_COM2WN_RUN_H ; WORK IN PROGRESS .cseg ; --------------------------------------------------------------------------- ; @routine com2wnLowLevelRun ; com2wnLowLevelRunOnePort: ldi yl, LOW(com2wnIoRingBuffer) ldi yh, HIGH(com2wnIoRingBuffer) rcall RingBufferY_ReadByteGuarded ; (R17, R18, X) brcc com2wnLowLevelRunOnePort_ret lds r18, com2wnIoCurrentClockStates eor r18, r16 ; r18: changed bits in clk states sts com2wnIoCurrentClockStates, r16 ; store new state ; r16=clock byte, r17=data byte, r18=clock change byte ldi r19, COM_PORTS ldi yl, LOW(com2w0_iface) ; first interface ldi yh, HIGH(com2w0_iface) com2wnLowLevelRunOnePort_loop: ; loop through all interfaces ldd r20, Y+COM2W_IFACE_OFFS_PINMASK_CLK mov r21, r20 and r21, r18 ; CLK for interface changed? breq com2wnLowLevelRunOnePort_nextIface push r16 push r18 push r19 mov r17, r16 ; same byte on onePort system rcall com2wnActOnClock ; (r16, r17, r18, X) pop r19 pop r18 pop r16 com2wnLowLevelRunOnePort_nextIface: adiw yh:yl, COM2W_IFACE_SIZE dec r19 brne com2wnLowLevelRunOnePort_loop sec com2wnLowLevelRunOnePort_ret: ret ; @end ; --------------------------------------------------------------------------- ; @routine com2wPeriodically @global ; ; @clobbers R16, Y com2wPeriodically: push r15 in r15, SREG cli rcall NET_Interface_Periodically ldd r16, Y+COM2W_IFACE_OFFS_MODECOUNTER inc r16 breq com2wPeriodically_end std Y+COM2W_IFACE_OFFS_MODECOUNTER, r16 com2wPeriodically_end: out SREG, r15 pop r15 ret ; @end ; --------------------------------------------------------------------------- ; @routine com2wSetMode ; ; Doesn't change processor status flags! ; ; @param R16 mode ; @clobbers R17 com2wSetMode: push r15 in r15, SREG cli ldd r17, Y+COM2W_IFACE_OFFS_MODE cp r16, r17 breq com2wSetMode_end std Y+COM2W_IFACE_OFFS_MODE, r16 clr r17 std Y+COM2W_IFACE_OFFS_MODECOUNTER, r17 com2wSetMode_end: out SREG, r15 pop r15 ret ; @end ; --------------------------------------------------------------------------- ; @routine com2wnStartReading ; ; @param Y pointer to interface data in SRAM ; @clobbers R16, R17, X com2wnStartReading: mov xl, yl mov xh, yh adiw xh:xl, COM2W_IFACE_OFFS_BUFFER std Y+COM2W_IFACE_OFFS_BUFPOS_LOW, xl std Y+COM2W_IFACE_OFFS_BUFPOS_HIGH, xh ldi r16, COM2W_BUFFER_SIZE std Y+COM2W_IFACE_OFFS_BUFLEFT, r16 clr r16 std Y+COM2W_IFACE_OFFS_BUFUSED, r16 ldi r16, COM2W_MODE_READING rcall com2wSetMode ; (R17) ret ; @end ; --------------------------------------------------------------------------- ; @routine com2wnRunMode ; ; @param Y pointer to interface data in SRAM ; @clobbers all com2wnRunMode: cpi r16, COM2W_MODE_NUM brcs com2wnRunMode_jump ldi r16, COM2W_MODE_IDLE ; unknown mode, set to idle rcall com2wSetMode ; (R17) sec ret com2wnRunMode_jump: ldi zl, LOW(com2wnModeJumpTable) ldi zh, HIGH(com2wnModeJumpTable) add zl, r16 adc zh, r16 sub zh, r16 ijmp com2wnModeJumpTable: rjmp com2wnRunIdle rjmp com2wnRunReading rjmp com2wnRunSkipping rjmp com2wnRunWriting ; @end ; --------------------------------------------------------------------------- ; @routine com2wnRunIdle ; ; @param Y pointer to interface data in SRAM ; @clobbers R16, R17, R22, R24, R25, X com2wnRunIdle: ;rjmp com2wnRunIdle_end ; DEBUG push r15 in r15, SREG cli ; look for outbound message rcall NET_Interface_PeekNextOutgoingMsgNum ; r16=msgNum brcs com2wnRunIdle_haveMsg out SREG, r15 pop r15 clc rjmp com2wnRunIdle_end com2wnRunIdle_haveMsg: mov r24, r16 ldi r16, COM2W_MODE_WRITING rcall com2wSetMode ; (R17) mov r16, r24 out SREG, r15 pop r15 push r16 rcall NET_Buffer_Locate ; (R17) adiw xh:xl, 1 rcall com2w0SendMsg ; (R16, R17, R22, R24, R25, X) push r15 in r15, SREG ; save SREG (no CLI, we want to save CFLAG only) ldi r16, COM2W_MODE_IDLE rcall com2wSetMode ; (R17) out SREG, r15 ; restore SREG pop r15 pop r16 brcc com2wnRunIdle_end push r15 in r15, SREG cli rcall NET_Interface_GetNextOutgoingMsgNum ; take current msg off the queue rcall NET_Buffer_ReleaseByNum ; (R16, X) out SREG, r15 pop r15 sec com2wnRunIdle_end: ret ; @end ; --------------------------------------------------------------------------- ; @routine com2wnRunReading ; ; @param Y pointer to interface data in SRAM ; @clobbers none com2wnRunReading: ; check for timeout (Y+NET_IFACE_OFFS_READTIMER) ldd r16, Y+NET_IFACE_OFFS_READTIMER cpi r16, COM2W_READING_MAXREADCOUNTER brcc com2wnRunReading_goIdle ldd r16, Y+COM2W_IFACE_OFFS_MODECOUNTER cpi r16, COM2W_READING_MAXMODECOUNTER brcc com2wnRunReading_goIdle clc rjmp com2wnRunReading_end com2wnRunReading_goIdle: ldi r16, NET_IFACE_OFFS_ERR_IO_LOW rcall NET_Interface_IncCounter16 ; (R24, R25) ldi r16, COM2W_MODE_IDLE rcall com2wSetMode ; (r17) sec com2wnRunReading_end: ret ; @end ; --------------------------------------------------------------------------- ; @routine com2wnRunSkipping ; ; @param Y pointer to interface data in SRAM ; @clobbers r16 (r17) com2wnRunSkipping: ; check for timeout (Y+NET_IFACE_OFFS_READTIMER) ldd r16, Y+NET_IFACE_OFFS_READTIMER cpi r16, COM2W_SKIPPING_MAXREADCOUNTER brcc com2wnRunSkipping_goIdle ldd r16, Y+COM2W_IFACE_OFFS_MODECOUNTER cpi r16, COM2W_SKIPPING_MAXMODECOUNTER brcc com2wnRunSkipping_goIdle clc rjmp com2wnRunSkipping_end com2wnRunSkipping_goIdle: ldi r16, COM2W_MODE_IDLE rcall com2wSetMode ; (r17) sec com2wnRunSkipping_end: ret ; @end ; --------------------------------------------------------------------------- ; @routine com2wnRunWriting ; ; @param Y pointer to interface data in SRAM ; @clobbers none com2wnRunWriting: ; TODO: check for timeout clc ret ; @end #endif ; AVR_MODULES_COM2W_COM2WN_RUN_H