; vim: sts=4 sw=8 et ai fdm=marker ft=asm ; ; fnordlicht firmware ; ; for additional information please ; see http://koeln.ccc.de/prozesse/running/fnordlicht ; ; (c) by Alexander Neumann ; and Lars Noschinski ; ; This program is free software; you can redistribute it and/or modify ; it under the terms of the GNU General Public License version 2 as ; published by the Free Software Foundation. ; ; This program is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with this program; if not, write to the Free Software ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ; ; For more information on the GPL, please go to: ; http://www.gnu.org/copyleft/gpl.html ; remote command execution ; ============================================================================= ; table: RemoteCommandOperatorJumpTable {{{ ; ================================================================================== RemoteCommandOperatorJumpTable: rjmp do_rc_nop ; 0x00 rjmp do_rc_toggle_scripts ; 0x10 rjmp do_rc_set_channels ; 0x20 ; }}} ; function: execute_remote_commands {{{ ; ============================================================================= execute_remote_commands: MACRO_FIFO_LOAD_COUNTER IReceiveFifo, w1 ; load IReceiveFifo counter cpi w1, 0 ; if no commands left, return breq execute_remote_commands_end ;DEBUG_WRITE_I 'C' ;DEBUG_WRITE_R w3 rcall execute_remote_command rjmp execute_remote_commands execute_remote_commands_end: ret ; }}} ; function: execute_remote_command {{{ ; ============================================================================= execute_remote_command: lds w4, IReceiveFifo + FifoRPointerL ; save read pointer lds w5, IReceiveFifo + FifoRPointerH MACRO_FIFO_READ IReceiveFifo, w1, IRSize ; load counter byte into w1 cpi w1, 0 ; check if command completed brne execute_remote_command_do_execute ; if nonzero, command is complete ;DEBUG_WRITE_I 'x' sts IReceiveFifo + FifoRPointerL, w4 ; restore read pointer sts IReceiveFifo + FifoRPointerH, w5 lds w1, IReceiveFifo + FifoCounter ; increment pointer inc w1 sts IReceiveFifo + FifoCounter, w1 ret ; return execute_remote_command_do_execute: DEBUG_WRITE_I 'o' DEBUG_WRITE_R w1 cpi w1, 4 ; check if command is 4 bytes brne execute_remote_command_abort ; if not, abort lds w1, IReceiveFifo + FifoCounter ; load counter subi w1, 4 ; decrement counter sts IReceiveFifo + FifoCounter, w1 ; save counter ldi w1, low(IReceiveFifo + IRSize + FifoControlSize) ; load address of the byte after the last databyte ldi w2, high(IReceiveFifo + IRSize + FifoControlSize) movw l2:l1, w2:w1 ; save for later comparing lds YH, IReceiveFifo + FifoRPointerH ; load read pointer lds YL, IReceiveFifo + FifoRPointerL ld w1, Y+ ; load opcode and parameters rcall execute_remote_command_check_wraparound ld w2, Y+ rcall execute_remote_command_check_wraparound ld w3, Y+ rcall execute_remote_command_check_wraparound ld w4, Y+ rcall execute_remote_command_check_wraparound sts IReceiveFifo + FifoRPointerL, YL ; save read pointer sts IReceiveFifo + FifoRPointerH, YH mov l1, w1 ; save opcode andi w1, 0xf0 ; extract opcode swap w1 DEBUG_WRITE_I 'O' DEBUG_WRITE_R w1 cpi w1, 0x03 ; check for valid opcode brsh execute_remote_command_end ; if invalid, return. ldi ZL, low(RemoteCommandOperatorJumpTable) ; load jump table address ldi ZH, high(RemoteCommandOperatorJumpTable) add ZL, w1 ; add opcode offset clr w1 adc ZH, w1 mov w1, l1 ; restore original opcode andi w1, 0x0f ; extract flags icall ; execute opcode ret execute_remote_command_abort: MACRO_FIFO_READ IReceiveFifo, w2, IRSize ; read received byte into w2 dec w1 brne execute_remote_command_abort ; do while w1 nonzero execute_remote_command_end: ret ; =================== ; Helper functions ; =================== execute_remote_command_check_wraparound: ;{{{ cp YL, l1 ; compare Y with saved byte address cpc YH, l2 brne execute_remote_command_check_wraparound_end ; if not at end, ret ; else do wraparound ldi YL, low(IReceiveFifo + FifoData) ; load address of first data byte ldi YH, high(IReceiveFifo + FifoData) execute_remote_command_check_wraparound_end: ret ; }}} ; }}} ; RC OPCODES {{{ ; ============================================================================= ; Flags are passed in on w1, parameters on w2-w4. ; ; RC Opcodes can pass flags back on w1, so w1 should be cleared before "ret". ; ----------------------------------------------------------------------------- do_rc_nop: ret do_rc_toggle_scripts: ldi w1, (1<