; ***************************************************************************
; copyright   : (C) 2026 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_MOD_COM2WROUTER_RINGBUFFER_ASM
#define AVR_MOD_COM2WROUTER_RINGBUFFER_ASM



; ***************************************************************************
; defines

.equ COM2WR_RINGBUFFER_MAX_WORDS = 512



; ***************************************************************************
; SDRAM data

.dseg


com2wRingbufferBegin:
  com2wRingbufferReadPos:        .byte 2
  com2wRingbufferWritePos:       .byte 2
  com2wRingbufferWordsInBuffer:  .byte 2
  com2wRingbufferData:           .byte (2*COM2WR_RINGBUFFER_MAX_WORDS)
com2wRingbufferEnd:



; ***************************************************************************
; code

.cseg

; ---------------------------------------------------------------------------
; @routine COM2WR_Ringbuffer_Reset @global
;
; @clobbers r16

COM2WR_Ringbuffer_Init:
  rjmp COM2WR_Ringbuffer_Reset
; @end



; ---------------------------------------------------------------------------
; @routine COM2WR_Ringbuffer_Reset @global
;
; @clobbers r16

COM2WR_Ringbuffer_Reset:
  clr r16
  sts com2wRingbufferReadPos, r16
  sts com2wRingbufferReadPos+1, r16
  
  sts com2wRingbufferWritePos, r16
  sts com2wRingbufferWritePos+1, r16

  sts com2wRingbufferWordsInBuffer, r16
  sts com2wRingbufferWordsInBuffer+1, r16
  
  ret
; @end



; ---------------------------------------------------------------------------
; @routine COM2WR_Ringbuffer_WriteWord @global
;
; @return CFLAG set if data stored, cleared otherwise
; @param r16 low byte to add
; @param r17 high byte to add
; @clobbers xl, xh, r18, r19

COM2WR_Ringbuffer_WriteWord:
  lds xl, com2wRingbufferWordsInBuffer             ; +2
  lds xh, com2wRingbufferWordsInBuffer+1           ; +2
  ldi r18, LOW(COM2WR_RINGBUFFER_MAX_WORDS)        ; +1
  ldi r19, HIGH(COM2WR_RINGBUFFER_MAX_WORDS)       ; +1
  cp xl, r18                                       ; +1
  cpc xh, r19                                      ; +1
  brcc COM2WR_Ringbuffer_WriteWord_ret             ; +1 (+2 if jump)
  adiw xh:xl, 1                                    ; +1
  sts com2wRingbufferWordsInBuffer, xl             ; +2
  sts com2wRingbufferWordsInBuffer+1, xh           ; +2
  lds xl, com2wRingbufferWritePos                  ; +2
  lds xh, com2wRingbufferWritePos+1                ; +2
  ldi r18, LOW(com2wRingbufferData)                ; +1
  ldi r19, HIGH(com2wRingbufferData)               ; +1
  add xl, r18                                      ; +1
  adc xh, r19                                      ; +1
  st X+, r16                                       ; +2
  st X+, r17                                       ; +2
  sub xl, r18                                      ; +1
  sbc xh, r19                                      ; +1
  andi xl, LOW((2*COM2WR_RINGBUFFER_MAX_WORDS)-1)  ; +1
  andi xh, HIGH((2*COM2WR_RINGBUFFER_MAX_WORDS)-1) ; +1
  sts com2wRingbufferWritePos, xl                  ; +2
  sts com2wRingbufferWritePos+1, xh                ; +2
  sec                                              ; +1
COM2WR_Ringbuffer_WriteWord_ret:                   
  ret                                              ; +4  = +41 = <3us at 16MHz
; @end



; ---------------------------------------------------------------------------
; @routine COM2WR_Ringbuffer_ReadWord @global
;
; @return CFLAG set if data available, cleared otherwise
; @return r16 low byte from buffer
; @return r17 high byte from buffer
; @clobbers xl, xh, r18

COM2WR_Ringbuffer_ReadWord:
  lds xl, com2wRingbufferWordsInBuffer
  lds xh, com2wRingbufferWordsInBuffer+1
  mov r18, xl
  or r18, xh
  clc
  breq COM2WR_Ringbuffer_ReadWord_ret
  sbiw xh:xl, 1
  sts com2wRingbufferWordsInBuffer, xl
  sts com2wRingbufferWordsInBuffer+1, xh
  lds xl, com2wRingbufferReadPos
  lds xh, com2wRingbufferReadPos+1
  ldi r18, LOW(com2wRingbufferData)               ; +1
  ldi r19, HIGH(com2wRingbufferData)              ; +1
  add xl, r18                                     ; +1
  adc xh, r19                                     ; +1
  ld r16, X+
  ld r17, X+
  sub xl, r18
  sbc xh, r19
  andi xl, LOW((2*COM2WR_RINGBUFFER_MAX_WORDS)-1)
  andi xh, HIGH((2*COM2WR_RINGBUFFER_MAX_WORDS)-1)
  sts com2wRingbufferReadPos, xl
  sts com2wRingbufferReadPos+1, xh
  sec
COM2WR_Ringbuffer_ReadWord_ret:
  ret
; @end







#endif ; AVR_MOD_COM2WROUTER_RINGBUFFER_ASM

