Files
hexdec/servo_controller/src/command_handler.c
T

185 lines
3.5 KiB
C

#include "command_handler.h"
#include "command_message.h"
#include "led.h"
#include "servo.h"
#include "adc.h"
#include "usb.h"
#include "digital_out.h"
#include "power_monitor.h"
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(command_handler, LOG_LEVEL_INF);
// BUFFER (add ack and nack at the and as static)
#define CMD_MSG_BUFFER_SIZE 10
struct command_message_t cmd_msg_buffer[CMD_MSG_BUFFER_SIZE + 2];
struct command_message_t *cmd_msg_buffer_ptr;
int command_handler_init() {
// BUFFER
memset(cmd_msg_buffer, 0, sizeof(cmd_msg_buffer));
cmd_msg_buffer_ptr = cmd_msg_buffer;
// CREATE ACK/NACK
command_create_ack(&cmd_msg_buffer[CMD_MSG_BUFFER_SIZE]);
command_create_nack(&cmd_msg_buffer[CMD_MSG_BUFFER_SIZE + 1]);
return 0;
}
int command_handler_rx(struct command_message_t *msg) {
if (msg == NULL) {
LOG_ERR("Received NULL message pointer");
return -EINVAL;
}
LOG_DBG("Processing command: %d, length: %d", msg->command, msg->length);
switch (msg->command) {
case LED_TOGGLE: {
// Toggle LED
int led = msg->data[0];
if (!led) {
led0_toggle();
}
else {
led1_toggle();
}
break;
}
case LED_SET: {
// Set LED
int led = msg->data[0];
int state = msg->data[1];
led_set(led, state);
break;
}
case SERVO_SET: {
// Set SERVO
int servo = msg->data[0];
float angle;
memcpy(&angle, &msg->data[1], sizeof(float));
servo_set_angle(servo, angle);
break;
}
case SERVO_SET_ALL: {
// Set ALL SERVO
float angles[NUM_SERVO_CHANNELS];
for (int i = 0; i < NUM_SERVO_CHANNELS; i++) {
int start = i*4;
memcpy(&angles[i], &msg->data[start], sizeof(float));
}
servo_set_all_angles(angles);
break;
}
case ADC_READ_RAW: {
int channel = msg->data[0];
int value = adc_read_id(channel);
struct command_message_t *reply = cmd_get_next_tx_buf();
command_create_message(reply, sizeof(value), msg->command, (uint8_t *)&value);
command_handler_tx(reply);
break;
}
case ADC_READ_RAW_ALL: {
int values[NUM_ADC_CHANNELS];
for (int i = 0; i < NUM_ADC_CHANNELS; i++) {
values[i] = adc_read_id(i);
}
struct command_message_t *reply = cmd_get_next_tx_buf();
command_create_message(reply, sizeof(values), msg->command, (uint8_t *)values);
command_handler_tx(reply);
break;
}
case ADC_READ: {
uint32_t mask;
memcpy(&mask, &msg->data[0], sizeof(uint32_t));
adc_add_mask(mask);
break;
}
case ADC_READ_ALL: {
uint32_t mask = 0b111111111111111111;
adc_add_mask(mask);
break;
}
case ADC_SET_READ: {
int interval_ms;
memcpy(&interval_ms, &msg->data[0], sizeof(int));
adc_timer_set(interval_ms);
break;
}
case DIGITAL_LEG_OUT: {
uint8_t mask = msg->data[0];
digital_out_set_leg(mask);
break;
}
case POWER_MONITOR_SET_READ: {
int interval_ms;
memcpy(&interval_ms, &msg->data[0], sizeof(int));
power_monitor_timer_set(interval_ms);
break;
}
default: {
LOG_WRN("Unknown command received: %d", msg->command);
return -EINVAL;
}
}
return 0;
}
struct command_message_t* cmd_get_next_tx_buf() {
struct command_message_t *buf = cmd_msg_buffer_ptr;
// Increment the buffer pointer
cmd_msg_buffer_ptr++;
if (cmd_msg_buffer_ptr > &cmd_msg_buffer[CMD_MSG_BUFFER_SIZE-1]) {
cmd_msg_buffer_ptr = cmd_msg_buffer;
}
return buf;
}
int command_handler_tx(struct command_message_t *msg) {
// Send over USB if enabled and ready
if (usb_is_tx_enabled()) {
usb_send_command(msg);
}
return 0;
}