--- /dev/null
+/* circularbytebuffer-asm.S */
+/*
+ This file is part of the AVR-circularbytebuffer.
+ Copyright (C) 2009 Daniel Otte (daniel.otte@rub.de)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file circularbytebuffer-asm.S
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2009-07-25
+ * \license GPLv3 or later
+ * \ingroup circularbytebuffer
+ * \brief declaration for circular byte buffer
+ */
+/*
+ typedef struct {
+ uint8_t buffer_size;
+ uint8_t fillcount;
+ uint8_t* buffer;
+ uint8_t* head;
+ uint8_t* tail;
+ uint8_t* top;
+} circularbytebuffer_t;
+*/
+
+#include "config.h"
+
+#define BUFFER_SIZE_OFFSET 0
+#define FILLCOUNT_OFFSET 1
+#define BUFFER_OFFSET 2
+#define HEAD_OFFSET 4
+#define TAIL_OFFSET 6
+#define TOP_OFFSET 8
+
+#ifndef CIRCULARBYTEBUFFER_NO_MALLOC
+# define CIRCULARBYTEBUFFER_NO_MALLOC 0
+#endif
+
+#ifndef CIRCULARBYTEBUFFER_NO_INIT2
+# define CIRCULARBYTEBUFFER_NO_INIT2 0
+#endif
+
+#if CIRCULARBYTEBUFFER_NO_MALLOC==0
+
+/******************************************************************************/
+/*
+ * uint8_t circularbytebuffer_init(uint8_t buffersize, circularbytebuffer_t* cb){
+ * cb->buffer_size = buffersize;
+ * cb->buffer = malloc(buffersize);
+ * cb->head = cb->tail = cb->buffer;
+ * cb->top = cb->buffer + cb->buffer_size;
+ * cb->fillcount = 0;
+ * if(cb->buffer)
+ * return 1; / * success * /
+ * return 0; / * malloc failed * /
+ * }
+ *
+ * param buffersize: r24
+ * param cb: r22:r23
+ */
+.global circularbytebuffer_init
+circularbytebuffer_init:
+ push r28
+ push r29
+ movw r28, r22
+ std Y+0, r24 /* set buffer_size */
+ std Y+1, r1 /* set fillcount to 0 */
+ clr r25
+ call malloc
+ adiw r24, 0
+ brne 10f
+ clr r24
+ rjmp 99f
+10:
+ std Y+2, r24
+ std Y+3, r25
+ std Y+4, r24
+ std Y+5, r25
+ std Y+6, r24
+ std Y+7, r25
+ ld r22, Y
+ add r24, r22
+ adc r25, r1
+ std Y+8, r24
+ std Y+9, r25
+ ldi r24, 1
+99:
+ clr r25
+ pop r29
+ pop r28
+ ret
+
+/******************************************************************************/
+/*
+ * void circularbytebuffer_free(circularbytebuffer_t* cb){
+ * free(cb->buffer);
+ * }
+ *
+ * param cb: r24:r25
+ */
+.global circularbytebuffer_free
+circularbytebuffer_free:
+ movw r30, r24
+ ldd r24, Z+BUFFER_OFFSET
+ ldd r25, Z+BUFFER_OFFSET+1
+ jmp free
+
+#endif /* CIRCULARBYTEBUFFER_NO_MALLOC==0 */
+
+#if CIRCULARBYTEBUFFER_NO_INIT2==0
+
+/******************************************************************************/
+/*
+ * void circularbytebuffer_init2(uint8_t buffersize, circularbytebuffer_t* cb, void* buffer){
+ * cb->buffer_size = buffersize;
+ * cb->buffer = buffer
+ * cb->head = cb->tail = cb->buffer;
+ * cb->top = cb->buffer + cb->buffer_size;
+ * cb->fillcount = 0;
+ * }
+ *
+ * param buffersize: r24
+ * param cb: r22:r23
+ * param buffer: r20:r21
+ */
+.global circularbytebuffer_init2
+circularbytebuffer_init2:
+ movw r30, r22
+ std Z+0, r24 /* set buffer_size */
+ std Z+1, r1 /* set fillcount to 0 */
+ std Z+2, r20
+ std Z+3, r21
+ std Z+4, r20
+ std Z+5, r21
+ std Z+6, r20
+ std Z+7, r21
+ add r20, r24
+ adc r21, r1
+ std Z+8, r20
+ std Z+9, r21
+ ret
+
+#endif /* CIRCULARBYTEBUFFER_NO_INIT2==0 */
+
+/******************************************************************************/
+/*
+ * uint8_t circularbytebuffer_cnt(circularbytebuffer_t* cb){
+ * return (cb->fillcount);
+ * }
+ *
+ * param cb: r24:r25
+ */
+.global circularbytebuffer_cnt
+circularbytebuffer_cnt:
+ movw r30, r24
+ ldd r24, Z+FILLCOUNT_OFFSET
+ clr r25
+ ret
+
+/******************************************************************************/
+/*
+ * uint16_t circularbytebuffer_get_lifo(circularbytebuffer_t* cb){
+ * uint8_t ret;
+ * if(cb->fillcount==0)
+ * return 0xffff;
+ * --cb->fillcount;
+ * ret=*(cb->tail);
+ * cb->tail = (uint8_t*)(cb->tail) + 1;
+ * if(cb->tail>=cb->top)
+ * cb->tail = (uint8_t*)(cb->tail) - cb->buffer_size;
+ * return ret;
+ * }
+ * param cb: r24:r25
+ */
+.global circularbytebuffer_get_lifo
+circularbytebuffer_get_lifo:
+ movw r30, r24
+ ldd r23, Z+FILLCOUNT_OFFSET
+ tst r23
+ brne 10f
+ ser r24
+ ser r25
+ ret
+10:
+ dec r23
+ std Z+FILLCOUNT_OFFSET, r23
+ ldd r26, Z+TAIL_OFFSET
+ ldd r27, Z+TAIL_OFFSET+1
+ ld r24, X+
+ clr r25
+ ldd r22, Z+TOP_OFFSET
+ ldd r23, Z+TOP_OFFSET+1
+ cp r26, r22
+ cpc r27, r23
+ brlo 20f
+ ldd r22, Z+BUFFER_SIZE_OFFSET
+ sub r26, r22
+ sbc r27, r1
+20:
+ std Z+TAIL_OFFSET, r26
+ std Z+TAIL_OFFSET+1, r27
+ ret
+
+/******************************************************************************/
+/*
+ * uint16_t circularbytebuffer_get_fifo(circularbytebuffer_t* cb){
+ * uint8_t ret;
+ * if(cb->fillcount==0)
+ * return 0xffff;
+ * --cb->fillcount;
+ * ret=*(cb->head);
+ * cb->head = (uint8_t*)(cb->head) - 1;
+ * if(cb->head<cb->buffer)
+ * cb->head = (uint8_t*)(cb->head) + cb->buffer_size;
+ * return ret;
+ * }
+ *
+ * param cb: r24:r25
+ */
+.global circularbytebuffer_get_fifo
+circularbytebuffer_get_fifo:
+ movw r30, r24
+ ldd r23, Z+FILLCOUNT_OFFSET
+ tst r23
+ brne 10f
+ ser r24
+ ser r25
+ ret
+10:
+ dec r23
+ std Z+FILLCOUNT_OFFSET, r23
+ ldd r26, Z+HEAD_OFFSET
+ ldd r27, Z+HEAD_OFFSET+1
+ ld r24, X
+ clr 25
+ sbiw r26, 1
+ ldd r22, Z+BUFFER_OFFSET
+ ldd r23, Z+BUFFER_OFFSET+1
+ cp r26, r22
+ cpc r27, r23
+ brge 20f
+ ldd r22, Z+BUFFER_SIZE_OFFSET
+ add r26, r22
+ adc r27, r1
+20:
+ std Z+HEAD_OFFSET, r26
+ std Z+HEAD_OFFSET+1, r27
+ ret
+
+/******************************************************************************/
+/*
+ * uint8_t circularbytebuffer_append(uint8_t elem, circularbytebuffer_t* cb){
+ * if(cb->fillcount==cb->buffer_size)
+ * return 1;
+ * cb->fillcount++;
+ * cb->tail = cb->tail - 1;
+ * if(cb->tail<cb->buffer)
+ * cb->tail = (uint8_t*)(cb->tail) + cb->buffer_size;
+ * if(cb->fillcount==1)
+ * cb->head = cb->tail;
+ * *(cb->tail) = elem;
+ * return 0;
+ * }
+ *
+ * param elem: r24
+ * param cb: r22:r23
+ */
+.global circularbytebuffer_append
+circularbytebuffer_append:
+ movw r30, r22
+ ldd r22, Z+FILLCOUNT_OFFSET
+ ldd r23, Z+BUFFER_SIZE_OFFSET
+ cp r22, r23
+ brne 10f
+ ldi r24, 1
+ ret
+10:
+ clt
+ tst r22
+ brne 11f
+ set
+11:
+ inc r22
+ std Z+FILLCOUNT_OFFSET, r22
+ ldd r26, Z+TAIL_OFFSET
+ ldd r27, Z+TAIL_OFFSET+1
+ sbiw r26, 1
+ ldd r22, Z+BUFFER_OFFSET
+ ldd r23, Z+BUFFER_OFFSET+1
+ cp r26, r22
+ cpc r27, r23
+ brge 20f
+ ldd r22, Z+BUFFER_SIZE_OFFSET
+ add r26, r22
+ adc r27, r1
+20:
+ std Z+TAIL_OFFSET, r26
+ std Z+TAIL_OFFSET+1, r27
+ brtc 30f
+ std Z+HEAD_OFFSET, r26
+ std Z+HEAD_OFFSET+1, r27
+30:
+ st X, r24
+ clr r24
+ ret
+
+/******************************************************************************/
+/*
+ * uint8_t circularbytebuffer_push(uint8_t elem, circularbytebuffer_t* cb){
+ * if(cb->fillcount==cb->buffer_size)
+ * return 1;
+ * cb->fillcount++;
+ * cb->head = cb->head + 1;
+ * if(cb->head>=cb->top)
+ * cb->head = (uint8_t*)(cb->head) - cb->buffer_size;
+ * if(cb->fillcount==1)
+ * cb->tail = cb->head;
+ * *(cb->head) = elem;
+ * return 0;
+ * }
+ *
+ * param elem: r24
+ * param cb: r22:r23
+ */
+.global circularbytebuffer_push
+circularbytebuffer_push:
+ movw r30, r22
+ ldd r22, Z+FILLCOUNT_OFFSET
+ ldd r23, Z+BUFFER_SIZE_OFFSET
+ cp r22, r23
+ brne 10f
+ ldi r24, 1
+ ret
+10:
+ clt
+ tst r22
+ brne 11f
+ set
+11:
+ inc r22
+ std Z+FILLCOUNT_OFFSET, r22
+ ldd r26, Z+HEAD_OFFSET
+ ldd r27, Z+HEAD_OFFSET+1
+ adiw r26, 1
+ ldd r22, Z+TOP_OFFSET
+ ldd r23, Z+TOP_OFFSET+1
+ cp r26, r22
+ cpc r27, r23
+ brlo 20f
+ ldd r22, Z+BUFFER_SIZE_OFFSET
+ sub r26, r22
+ sbc r27, r1
+20:
+ std Z+HEAD_OFFSET, r26
+ std Z+HEAD_OFFSET+1, r27
+ brtc 30b
+ std Z+TAIL_OFFSET, r26
+ std Z+TAIL_OFFSET+1, r27
+ rjmp 30b