User Tools

Site Tools


FIFO buffer with readline

I wrote this code for Atmel microprocessor line parser.

hello.c
//#include <avr/io.h>
//#include <util/delay.h>
 
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
 
struct fifo_t {
    volatile unsigned head;
    volatile unsigned tail;
    volatile uint8_t *buffer;
    unsigned buffer_len;
};
 
typedef struct fifo_t FIFO;
 
uint8_t fifo_count(const FIFO *b) {
    if (b) {
        return (b->head - b->tail);
    }
    return 0;
}
 
static bool fifo_full(const FIFO *b) {
    if (b) {
        return (fifo_count(b) == b->buffer_len);
    }
    return true;
}
 
bool fifo_empty(const FIFO *b) {
    if (b) {
        return (fifo_count(b) == 0);
    }
    return true;
}
 
uint8_t fifo_peek(const FIFO *b) {
    if (b) {
        return (b->buffer[b->tail % b->buffer_len]);
    }
    return 0;
}
 
uint8_t fifo_getc(FIFO *b) {
    uint8_t data = 0;
    if (!fifo_empty(b)) {
        data = b->buffer[b->tail % b->buffer_len];
        b->tail++;
    }
    return data;
}
 
bool fifo_putc(FIFO *b, uint8_t data) {
    bool status = false;
    if (b) {
        if (!fifo_full(b)) {
            b->buffer[b->head % b->buffer_len] = data;
            b->head++;
            status = true;
        }
    }
    return status;
}
 
void fifo_init(FIFO *b, volatile uint8_t *buffer, unsigned buffer_len) {
    if (b) {
        b->buffer_len = buffer_len;
        b->buffer = buffer;
        b->head = 0;
        b->tail = 0;
    }
    return;
}
 
uint8_t fifo_puts(FIFO *b, char *string) {
    if (b) {
        for (uint8_t i = 0; i < strlen(string); i++) {
            if (!fifo_putc(b, string[i])) return i;
        }
    }
}
 
bool fifo_scanc(FIFO *b, uint8_t c) {
    if (b) {
        if (!fifo_empty(b)) {
            uint8_t tail = b->tail;
            for (uint8_t i = 0; i < fifo_count(b); i++) {
                uint8_t data = b->buffer[tail % b->buffer_len];
                if (data == c) { return true; }
                tail++;
            }
        }
        return false;
    }
}
 
#define LINE_TERM '\n'
 
uint8_t fifo_readline(FIFO *b, uint8_t *str, uint8_t len) {
    if (b) {
        memset((void *)str, 0, len);
        // str[0] = 0;
        if (fifo_scanc(b, LINE_TERM) && str) {
            uint8_t i = 0, c = 0;
            while ((c = fifo_getc(b)) != 0) {
                if (c == LINE_TERM) break;
                str[i] = c;
                i++;
            }
            return i;
        }
        return 0;
    }
}
 
#define FIFO_BUFFER_SIZE 256
#define MAX_LINE_LEN 64
 
 
void main(void) {
 
    FIFO fifo;
 
    volatile uint8_t store[FIFO_BUFFER_SIZE + 1];
    memset((void *)store, 0, FIFO_BUFFER_SIZE + 1);
 
    fifo_init(&fifo, store, sizeof(store));
 
    fifo_puts(&fifo, "CMD123\nCMD456\nCMD90\n");
 
    // if (fifo_scanc(&fifo, '\n')) puts("fifo have newine");
    // printf("count=%d\n", fifo_count(&fifo));
 
    uint8_t line[MAX_LINE_LEN+1];
    memset((void *)line, 0, MAX_LINE_LEN+1);
 
    uint8_t count;
 
    while((count = fifo_readline(&fifo, line, MAX_LINE_LEN)) > 0) {
 
        // if (fifo_scanc(&fifo, '\n')) puts("fifo have newine");
        // printf("fifo count=%d\n", fifo_count(&fifo));
        printf("readline: count=%d out=%s\n", count, line);
    }
 
}
 
//EOF

Out

readline: count=6 out=CMD123
readline: count=6 out=CMD456
readline: count=5 out=CMD90