Last active
September 10, 2019 09:00
-
-
Save lukicdarkoo/4c7db5a5bdd99f60b659616a3284ca06 to your computer and use it in GitHub Desktop.
Bit-aware circular buffer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "circbuff.h" | |
void circbuff_init(circbuff_t *circbuff) { | |
circbuff->end_bit = 0; | |
circbuff->end_byte = 0; | |
circbuff->start_bit = 0; | |
circbuff->start_byte = 0; | |
} | |
uint8_t circbuff_size(circbuff_t *circbuff) { | |
if (circbuff->end_byte >= circbuff->start_byte) { | |
return (circbuff->end_byte - circbuff->start_byte); | |
} else { | |
return CIRCBUFF_LENGTH - | |
(circbuff->start_byte - circbuff->end_byte); | |
} | |
} | |
bool circbuff_is_full(circbuff_t *circbuff) { | |
return (circbuff_size(circbuff) >= CIRCBUFF_LENGTH - 1); | |
} | |
bool circbuff_add_byte(circbuff_t *circbuff, uint8_t data) { | |
bool status = false; | |
if (circbuff_is_full(circbuff) == true) { | |
circbuff->start_byte = | |
(circbuff->start_byte + 1) % CIRCBUFF_LENGTH; | |
circbuff->start_bit = 0; | |
status = true; | |
} | |
circbuff->data[circbuff->end_byte] = data; | |
circbuff->end_byte = (circbuff->end_byte + 1) % CIRCBUFF_LENGTH; | |
circbuff->end_bit = 0; | |
return status; | |
} | |
bool circbuff_is_empty(circbuff_t *circbuff) { | |
return circbuff->start_byte == circbuff->end_byte; | |
} | |
uint8_t circbuff_pop_byte(circbuff_t *circbuff) { | |
circbuff->start_bit = 0; | |
if (circbuff_is_empty(circbuff) == false) { | |
uint8_t data = circbuff->data[circbuff->start_byte]; | |
circbuff->start_byte = | |
(circbuff->start_byte + 1) % CIRCBUFF_LENGTH; | |
return data; | |
} | |
return 0; | |
} | |
bool circbuff_add_bit(circbuff_t *circbuff, uint8_t data) { | |
bool status = false; | |
circbuff->data[circbuff->end_byte] |= data << (7 - circbuff->end_bit); | |
circbuff->end_bit++; | |
if (circbuff->end_bit > 7) { | |
if (circbuff_is_full(circbuff) == true) { | |
circbuff->start_byte = | |
(circbuff->start_byte + 1) % CIRCBUFF_LENGTH; | |
circbuff->start_bit = 0; | |
status = true; | |
} | |
circbuff->end_byte = (circbuff->end_byte + 1) % CIRCBUFF_LENGTH; | |
circbuff->end_bit = 0; | |
circbuff->data[circbuff->end_byte] = 0; | |
} | |
return status; | |
} | |
uint8_t circbuff_pop_bit(circbuff_t *circbuff) { | |
uint8_t data; | |
uint8_t bit; | |
data = circbuff->data[circbuff->start_byte]; | |
bit = (data & (1 << (7 - circbuff->start_bit))) >> | |
(7 - circbuff->start_bit); | |
circbuff->start_bit++; | |
if (circbuff->start_bit > 7) { | |
circbuff_pop_byte(circbuff); | |
} | |
return bit; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef _CIRCBUFF_H_ | |
#define _CIRCBUFF_H_ | |
#include <stdbool.h> | |
#include <stdint.h> | |
#ifndef CIRCBUFF_LENGTH | |
#define CIRCBUFF_LENGTH 64U | |
#endif | |
typedef struct _circbuff_t { | |
uint8_t data[CIRCBUFF_LENGTH]; | |
uint8_t start_byte; | |
uint8_t start_bit; | |
uint8_t end_byte; | |
uint8_t end_bit; | |
} circbuff_t; | |
void circbuff_init(circbuff_t *circbuff); | |
bool circbuff_is_full(circbuff_t *circbuff); | |
bool circbuff_is_empty(circbuff_t *circbuff); | |
uint8_t circbuff_size(circbuff_t *circbuff); | |
bool circbuff_add_byte(circbuff_t *circbuff, uint8_t data); | |
uint8_t circbuff_pop_byte(circbuff_t *circbuff); | |
bool circbuff_add_bit(circbuff_t *circbuff, uint8_t data); | |
uint8_t circbuff_pop_bit(circbuff_t *circbuff); | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "circbuff.h" | |
#include <assert.h> | |
#include <stdio.h> | |
static circbuff_t buff; | |
int main() { | |
circbuff_init(&buff); | |
// Byte pop test | |
circbuff_add_byte(&buff, 1); | |
assert(circbuff_pop_byte(&buff) == 1); | |
assert(circbuff_is_empty(&buff) == true); | |
// Bit add test | |
circbuff_add_bit(&buff, 1); | |
circbuff_add_bit(&buff, 0); | |
circbuff_add_bit(&buff, 1); | |
circbuff_add_bit(&buff, 0); | |
circbuff_add_bit(&buff, 1); | |
circbuff_add_bit(&buff, 1); | |
circbuff_add_bit(&buff, 1); | |
circbuff_add_bit(&buff, 1); | |
assert(circbuff_pop_byte(&buff) == 0xAF); | |
// Bit add/pop test | |
circbuff_add_bit(&buff, 1); | |
assert(circbuff_pop_bit(&buff) == 1); // Not sure if it is the correct behaviour | |
circbuff_add_bit(&buff, 1); | |
circbuff_add_bit(&buff, 0); | |
circbuff_add_bit(&buff, 1); | |
assert(circbuff_pop_bit(&buff) == 1); | |
assert(circbuff_pop_bit(&buff) == 0); | |
assert(circbuff_pop_bit(&buff) == 1); | |
circbuff_pop_byte(&buff); | |
// Bit pop test | |
circbuff_add_byte(&buff, 0x80); | |
assert(circbuff_pop_bit(&buff) == 1); | |
assert(circbuff_pop_bit(&buff) == 0); | |
assert(circbuff_pop_byte(&buff) == 0x80); | |
// Stress test | |
for (int i = 0; i < 65; i++) { | |
circbuff_add_bit(&buff, 1); | |
circbuff_add_bit(&buff, 0); | |
circbuff_add_bit(&buff, 1); | |
circbuff_add_bit(&buff, 0); | |
circbuff_add_bit(&buff, 1); | |
circbuff_add_bit(&buff, 1); | |
circbuff_add_bit(&buff, 1); | |
circbuff_add_bit(&buff, 1); | |
} | |
assert(circbuff_is_full(&buff)); | |
for (int i = 0; i < 63; i++) { | |
assert(circbuff_pop_byte(&buff) == 0xAF); | |
} | |
assert(circbuff_is_empty(&buff)); | |
assert(circbuff_pop_byte(&buff) == 0); | |
// Real world | |
circbuff_add_byte(&buff, 0xAA); | |
circbuff_add_byte(&buff, 0x02); | |
circbuff_add_byte(&buff, 0x03); | |
circbuff_add_byte(&buff, 0x04); | |
assert(circbuff_pop_bit(&buff) == 1); | |
assert(circbuff_pop_bit(&buff) == 0); | |
assert(circbuff_pop_bit(&buff) == 1); | |
assert(circbuff_pop_bit(&buff) == 0); | |
assert(circbuff_pop_bit(&buff) == 1); | |
assert(circbuff_pop_bit(&buff) == 0); | |
assert(circbuff_pop_bit(&buff) == 1); | |
assert(circbuff_pop_bit(&buff) == 0); | |
assert(circbuff_pop_bit(&buff) == 0); | |
assert(circbuff_pop_bit(&buff) == 0); | |
assert(circbuff_pop_bit(&buff) == 0); | |
assert(circbuff_pop_bit(&buff) == 0); | |
assert(circbuff_pop_bit(&buff) == 0); | |
assert(circbuff_pop_bit(&buff) == 0); | |
assert(circbuff_pop_bit(&buff) == 1); | |
assert(circbuff_pop_bit(&buff) == 0); | |
assert(circbuff_pop_bit(&buff) == 0); | |
assert(circbuff_pop_bit(&buff) == 0); | |
assert(circbuff_pop_bit(&buff) == 0); | |
assert(circbuff_pop_bit(&buff) == 0); | |
assert(circbuff_pop_bit(&buff) == 0); | |
assert(circbuff_pop_bit(&buff) == 0); | |
assert(circbuff_pop_bit(&buff) == 1); | |
assert(circbuff_pop_bit(&buff) == 1); | |
assert(circbuff_pop_bit(&buff) == 0); | |
assert(circbuff_pop_bit(&buff) == 0); | |
assert(circbuff_pop_bit(&buff) == 0); | |
assert(circbuff_pop_bit(&buff) == 0); | |
assert(circbuff_pop_bit(&buff) == 0); | |
assert(circbuff_pop_bit(&buff) == 1); | |
assert(circbuff_pop_bit(&buff) == 0); | |
assert(circbuff_pop_bit(&buff) == 0); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment