; 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 ; hold some general memory handling macros ; vim: sts=4 et ai fdm=marker syntax=asm ; fifo handling ; ============== ; fifo offsets {{{ ; ============ .equ FifoRPointerL = 0 .equ FifoRPointerH = 1 .equ FifoWPointerL = 2 .equ FifoWPointerH = 3 .equ FifoCounter = 4 .equ FifoData = 5 ; fifo control size: 2 byte read counter, 2 byte write counter, 1 byte fill counter .equ FifoControlSize = 5 ; }}} ; macro: FIFO_INIT {{{ ; ================================================================================== ; uses: w1 ; @0 ; call: MACRO_FIFO_INIT BaseAddress .macro MACRO_FIFO_INIT ldi w1, low(@0 + FifoData) ; load address and correct offset to point to the data storage space sts @0 + FifoRPointerL, w1 ; store address into the read pointer sts @0 + FifoWPointerL, w1 ; store address into the write pointer ldi w1, high(@0 + FifoData) sts @0 + FifoRPointerH, w1 sts @0 + FifoWPointerH, w1 ldi w1, 0 ; reset the fifo counter and store it sts @0 + FifoCounter, w1 .endmacro ; }}} ; macro: FIFO_LOAD_COUNTER {{{ ; ================================================================================== ; uses: register @1 ; returns: fifo counter in @1 ; @0 @1 ; call: MACRO_FIFO_LOAD_COUNTER BaseAddress DestinationRegister .macro MACRO_FIFO_LOAD_COUNTER lds @1, @0 + FifoCounter ; load fifo counter .endmacro ; }}} ; macro: FIFO_SAVE_COUNTER {{{ ; ================================================================================== ; @0 @1 ; call: MACRO_FIFO_SAVE_COUNTER BaseAddress CounterRegister .macro MACRO_FIFO_SAVE_COUNTER sts @0 + FifoCounter, @1 ; save counter .endmacro ; }}} ; macro: FIFO_STORE {{{ ; ================================================================================== ; uses: registers @2, Y ; @0 @1 @2 @3 ; call: MACRO_FIFO_STORE BaseAddress DataRegister TempRegister FifoSize ; remark: DataRegister and TempRegister must not point to the same register! .macro MACRO_FIFO_STORE MACRO_FIFO_LOAD_COUNTER @0 , @2 ; load counter inc @2 ; increment counter MACRO_FIFO_SAVE_COUNTER @0 , @2 ; store counter lds YL, @0 + FifoWPointerL ; load write pointer lds YH, @0 + FifoWPointerH st Y+, @1 ; store data byte in fifo and increment pointer ldi @2, low(@0 + @3 + FifoControlSize) ; load address of the first byte after the fifo data memory cp YL, @2 ; compare to the current pointer ldi @2, high(@0 + @3 + FifoControlSize) cpc YH, @2 ; ... 16 bit, of course ;) brne MACRO_FIFO_STORE_STORE_POINTER ; if not equal, fifo space end hasn't been reached, so just store the new pointer ldi YH, high(@0 + FifoData) ; else do a rollover ldi YL, low(@0 + FifoData) MACRO_FIFO_STORE_STORE_POINTER: sts @0 + FifoWPointerL, YL ; store pointer sts @0 + FifoWPointerH, YH .endmacro ; }}} ; macro: FIFO_READ {{{ ; ================================================================================== ; uses: registers @1, @2, Y ; returns: data in @1 ; @0 @1 @2 ; call: MACRO_FIFO_READ BaseAddress DataRegister FifoSize .macro MACRO_FIFO_READ lds YH, @0 + FifoRPointerH ; load read pointer into Y lds YL, @0 + FifoRPointerL MACRO_FIFO_LOAD_COUNTER @0 , @1 ; load counter dec @1 ; decrement MACRO_FIFO_SAVE_COUNTER @0 , @1 ; store counter ; will the end of fifo be reached? ldi @1, low(@0 + @2 + FifoControlSize - 1) cp @1, YL ldi @1, high(@0 + @2 + FifoControlSize - 1) ; ldi doesn't change status flags cpc @1, YH ld @1, Y+ ; load data into @1 brne MACRO_FIFO_READ_STORE_POINTER ; if not, jump away ldi YH, high(@0 + FifoData) ; else wrap the fifo around ldi YL, low(@0 + FifoData) MACRO_FIFO_READ_STORE_POINTER: sts @0 + FifoRPointerH, YH ; store new read pointer sts @0 + FifoRPointerL, YL .endmacro ; }}} ; macro: FIFO_POP {{{ ; ================================================================================== ; uses: registers @1, Y ; returns: data in @1 ; @0 @1 @2 ; call: MACRO_FIFO_POP BaseAddress DataRegister FifoSize .macro MACRO_FIFO_POP lds YH, @0 + FifoWPointerH ; load write pointer into Y lds YL, @0 + FifoWPointerL MACRO_FIFO_LOAD_COUNTER @0 , @1 ; decrement fifo counter dec @1 MACRO_FIFO_SAVE_COUNTER @0 , @1 ldi @1, low(@0 + FifoData) ; load address of the fifo data memory cp YL, @1 ; compare with Y ldi @1, high(@0 + FifoData) cpc YH, @1 brne MACRO_FIFO_POP_LOAD_DATA ; if not equal, just pre-decrement Y and load data ; else load address of the first byte after the fifo data space ldi YL, low(@0 + @2 + FifoControlSize) ldi YH, high(@0 + @2 + FifoControlSize) MACRO_FIFO_POP_LOAD_DATA: ld @1, -Y ; load data into @1 sts @0 + FifoWPointerH, YH ; store new write pointer sts @0 + FifoWPointerL, YL .endmacro ; }}}