audioMux/firmware/Src/message_parser.c

213 lines
4.0 KiB
C

#include <stdint.h>
#include "bd3491.h" // to manipulate the chip further than the normal system ui does
#include "i2c.h" // for the i2c handle
#include "main.h" // to enable control of the system
struct {
char buffer[1000];
volatile uint16_t begin, end;
volatile uint16_t len;
} serial_buffer = {};
void serial_buffer_push(char data) {
if (serial_buffer.len && serial_buffer.end == serial_buffer.begin)
return; // OVF
serial_buffer.buffer[serial_buffer.end] = data;
serial_buffer.end = (serial_buffer.end + 1)%(sizeof(serial_buffer.buffer));
serial_buffer.len++;
}
char serial_buffer_peek() {
if (serial_buffer.len)
return serial_buffer.buffer[serial_buffer.begin];
return 0;
}
char serial_buffer_pop() {
if (!serial_buffer.len)
return 0; // UF
char result = serial_buffer_peek();
serial_buffer.begin = (serial_buffer.begin + 1)%(sizeof(serial_buffer.buffer));
serial_buffer.len--;
return result;
}
int serial_buffer_len() {
return serial_buffer.len;
}
void CDC_Receive_callback(uint8_t * data, uint32_t len) {
while(len--) {
serial_buffer_push(*(data++));
}
}
int skip_white() {
while(serial_buffer_peek() == ' ' || serial_buffer_peek() == '\t')
serial_buffer_pop();
return !serial_buffer_len();
}
int iswhite(char in) {
return in == ' ' || in == '\t' || in == '\n';
}
int skip_non_white() {
while(serial_buffer_len() && !iswhite(serial_buffer_peek()))
serial_buffer_pop();
return !serial_buffer_len();
}
int skip_line() {
while(serial_buffer_len() && serial_buffer_peek() != '\n') serial_buffer_pop();
if (serial_buffer_peek() == '\n') serial_buffer_pop();
return !serial_buffer_len();
}
int next_arg_signed(int16_t * arg) {
*arg = 0;
if (skip_white())
return 1;
int neg = 0;
while(serial_buffer_len() && (serial_buffer_peek() == '-' || serial_buffer_peek() == '+')) {
if(serial_buffer_pop() == '-')
neg = !neg;
}
int count = 0;
while(serial_buffer_len() && serial_buffer_peek() >= '0' && serial_buffer_peek() <= '9') {
*arg *= 10;
*arg += serial_buffer_pop() - '0';
++count;
}
if (neg) {
*arg *= -1;
}
return !count;
}
int next_arg_unsigned(uint16_t * arg) {
*arg = 0;
if (skip_white())
return 1;
int count = 0;
while(serial_buffer_len() && serial_buffer_peek() >= '0' && serial_buffer_peek() <= '9') {
*arg *= 10;
*arg += serial_buffer_pop() - '0';
++count;
}
return !count;
}
#include <ctype.h>
int parse_buffer() {
if (skip_white()) {
return 1;
}
char temp;
switch((temp = toupper(serial_buffer_pop()))) {
case 'C':
// change channel
{
uint16_t channel;
if (next_arg_unsigned(&channel))
break;
set_input(channel);
}
break;
case 'G':
// set gain
{
uint16_t gain;
if (next_arg_unsigned(&gain)) break;
printf("G%d\n", (ui_state.gain = bd_set_gain(&hi2c1, gain)));
}
break;
case 'L':
case 'R':
{
uint16_t att;
uint8_t dir = 0;
uint8_t * save = &ui_state.latt;
if (next_arg_unsigned(&att)) break;
if (temp == 'R') {
dir = 1;
save = &ui_state.ratt;
}
printf("%c%d\n", temp, (*save = bd_set_attenuation(&hi2c1, dir, att&0xFF)));
}
break;
case 'M':
{
uint16_t mute;
if (next_arg_unsigned(&mute)) break;
set_mute(mute);
printf("M%d\n", is_muted());
}
break;
case 'S':
{
uint16_t shorted;
if (next_arg_unsigned(&shorted)) break;
set_short(shorted);
printf("S%d\n", is_shorted());
}
break;
case 'B':
{
uint16_t boost;
if (next_arg_unsigned(&boost)) break;
printf("B%d\n", (ui_state.bboost = bd_set_bass_boost(&hi2c1, boost)));
}
break;
case 'T':
{
uint16_t boost;
if (next_arg_unsigned(&boost)) break;
printf("T%d\n", (ui_state.tboost = bd_set_treble_boost(&hi2c1, boost)));
}
break;
case '?':
{
// return the system state
printf("M%d\n", is_muted());
printf("S%d\n", is_shorted());
printf("C%d\n", get_input());
printf("B%d\n", ui_state.bboost);
printf("T%d\n", ui_state.tboost);
printf("L%d\n", ui_state.latt);
printf("R%d\n", ui_state.ratt);
}
break;
default:
printf("E\n");
}
return skip_line();
}