bpsk-demod/src/bpsk/mac.c

185 lines
5.7 KiB
C

#include <stdint.h>
#include <stdio.h>
#include <assert.h>
#include "mac.h"
#ifdef PLAYGROUND
#include "../printf.h"
#else
#include <stdio.h>
#endif
extern uint32_t debug_print_sync;
extern uint32_t debug_print_status;
// uint8_t byte_log[65536];
// uint8_t bit_offset = 8;
// uint32_t byte_log_offset;
// put_bit with a MAC layer on it
int mac_put_bit(struct mac_state *state, int bit, void *buffer,
unsigned int buffer_size) {
demod_pkt_t *pkt = (demod_pkt_t *)buffer;
int packet_done = 0;
assert(buffer_size >= sizeof(demod_pkt_t));
// byte_log[byte_log_offset] |= (bit << --bit_offset);
// if (!bit_offset) {
// byte_log_offset++;
// if (byte_log_offset > sizeof(byte_log)) {
// byte_log_offset = 0;
// }
// byte_log[byte_log_offset] = 0;
// bit_offset = 8;
// }
switch (state->mstate) {
case MAC_IDLE:
// Search until at least /n/ zeros are found.
// The next transition /might/ be sync.
if (state->idle_zeros > 32) {
if (bit != 0) {
state->mstate = MAC_SYNC;
// printf("Got bit, transitioning to MAC_SYNC\n");
state->bitpos = 6;
state->curbyte = 0x80;
state->sync_count = 0;
} else {
if (state->idle_zeros < 255) {
state->idle_zeros++;
}
}
} else {
if (bit != 0)
state->idle_zeros = 0;
else
state->idle_zeros++;
}
break;
case MAC_SYNC:
// acculumate two bytes worth of temp data, then check to see if valid
// sync
state->curbyte >>= 1;
state->bitpos--;
if (bit) {
state->curbyte |= 0x80;
}
/* We haven't yet read 8 bits */
if (state->bitpos) {
break;
}
// printf("Got MAC byte: %02x\n", state->curbyte);
/* 8 bits have been read. Process the resulting byte. */
/* Optimization: check to see if we just read an idle value. */
if (state->curbyte == 0x00) {
/* False noise trigger, go back to idle. */
state->mstate = MAC_IDLE;
state->idle_zeros = 8; /* We just saw 8 zeros, so count those */
if (debug_print_sync) printf("False sync\n");
break;
}
/* Tally up the sync characters, make sure the sync matches. */
state->mac_sync[state->sync_count++] = state->curbyte;
if (state->sync_count >= 3) {
/* Test for sync sequence. It's one byte less than the # of
* leading zeros, to allow for the idle escape trick above to work
* in case of zero-biased noise.
*/
if ((state->mac_sync[0] == 0xAA) && (state->mac_sync[1] == 0x55) &&
(state->mac_sync[2] == 0x42)) {
// found the sync sequence, proceed to packet state
// osalDbgAssert(pktReady == 0,
// "Packet buffer full flag still set "
// "while new packet incoming\r\n");
if (debug_print_sync) printf("Found sync\n");
state->mstate = MAC_PACKET;
state->pkt_len = 0;
state->pkt_read = 0;
} else {
if (debug_print_sync)
printf("%02x %02x %02x not sync\n", state->mac_sync[0],
state->mac_sync[1], state->mac_sync[2]);
state->mstate = MAC_IDLE;
state->idle_zeros = 0;
}
}
/* Move on to the next bit */
state->bitpos = 8;
state->curbyte = 0;
break;
case MAC_PACKET:
/* If we haven't figured out the length, but we've read the entire
* header, figure out the length. Or exit the loop if it's not a
* valid packet.
*/
if (!state->pkt_len && state->pkt_read > sizeof(demod_pkt_header_t)) {
/* If the version number doesn't match, abandon ship. */
if ((pkt->header.version != PKT_VER_1) &&
(pkt->header.version != PKT_VER_2) &&
(pkt->header.version != PKT_VER_3)) {
if (debug_print_status) {
printf("Unrecognized packet version: %d\n", pkt->header.version);
}
goto make_idle;
}
if (pkt->header.type == PKTTYPE_CTRL)
state->pkt_len = CTRL_LEN;
else if (pkt->header.type == PKTTYPE_DATA)
state->pkt_len = DATA_LEN;
else {
/* Unrecognized packet type */
if (debug_print_status)
printf("Unrecognized packet header type %d\n",
pkt->header.type);
goto make_idle;
}
}
/* Load on the next bit. */
state->curbyte >>= 1;
state->bitpos--;
if (bit) {
state->curbyte |= 0x80;
}
/* If we've finished this bit, add it to the packet. */
if (state->bitpos == 0) {
((uint8_t *)buffer)[state->pkt_read++] = state->curbyte;
state->bitpos = 8;
state->curbyte = 0;
}
/* If we've finished reading the packet, indicate it's ready */
if (state->pkt_len && state->pkt_read >= state->pkt_len) {
packet_done = 1; // flag that the packet is ready
goto make_idle;
break;
}
break;
default:
break;
}
return 0;
make_idle:
state->mstate = MAC_IDLE;
state->idle_zeros = 0;
return packet_done;
}