287 lines
7.7 KiB
C
287 lines
7.7 KiB
C
#include "command-handler.h"
|
|
#include "fan-speed.h"
|
|
|
|
// Initialize empty, global command context
|
|
volatile command_context_t context = {UNKNOWN_COMMAND, SRC_NONE, FAN_NONE,
|
|
CNF_NONE};
|
|
|
|
void parse_command(uint8_t command[], uint8_t command_len) {
|
|
///////////////////////
|
|
// Command selection //
|
|
///////////////////////
|
|
|
|
// Validate that we have a command
|
|
if (command_len < 1) {
|
|
context.command = UNKNOWN_COMMAND;
|
|
}
|
|
|
|
// Extract the first byte, which contains the command
|
|
uint8_t command_byte = command[0];
|
|
|
|
// Figure out which command to run
|
|
switch (command_byte) {
|
|
case 0x11: // Read config
|
|
context.command = READ_CONFIG;
|
|
break;
|
|
case 0x12: // Read voltage
|
|
context.command = READ_VOLTAGE;
|
|
break;
|
|
case 0x13: // Read temperature
|
|
context.command = READ_TERMPERATURE;
|
|
break;
|
|
case 0x14: // Read current fan speed
|
|
context.command = READ_FAN_SPEED;
|
|
break;
|
|
case 0x15: // Read bulk fan speed
|
|
context.command = READ_BULK_FAN_SPEED;
|
|
break;
|
|
case 0x21: // Write config
|
|
context.command = WRITE_CONFIG;
|
|
break;
|
|
case 0x22: // Clear stored fan speed data
|
|
context.command = CLEAR_BULK_FAN_SPEED;
|
|
break;
|
|
default: // Unrecognized command
|
|
context.command = UNKNOWN_COMMAND;
|
|
break;
|
|
}
|
|
|
|
///////////////////////////////
|
|
// First parameter selection //
|
|
///////////////////////////////
|
|
|
|
// Check if the command does not require a parameter. If it does not, return.
|
|
if (context.command == READ_TERMPERATURE) {
|
|
return;
|
|
}
|
|
|
|
// Validate that we have a second parameter, else requirements for command are
|
|
// not fulfilled. return unknown command.
|
|
if (command_len < 2) {
|
|
context.command = UNKNOWN_COMMAND;
|
|
return;
|
|
}
|
|
|
|
// Store the parameter
|
|
uint8_t param = command[1];
|
|
|
|
// Extract the parameter. Parameter is dependent on command
|
|
switch (command[0]) {
|
|
// Configuration parameters
|
|
case 0x11: // Read config
|
|
case 0x21: // Write config
|
|
if (param == 0x01) {
|
|
context.conf = SAMPLE_TIME;
|
|
} else {
|
|
context.conf = CNF_NONE;
|
|
}
|
|
break;
|
|
|
|
// Voltage parameters
|
|
case 0x12: // Read voltage
|
|
if (param == 0x01) {
|
|
context.src_voltage = SRC_INTERNAL;
|
|
} else if (param == 0x02) {
|
|
context.src_voltage = SRC_EXTRNAL;
|
|
} else if (param == 0x03) {
|
|
context.src_voltage = SRC_THERMISTOR;
|
|
} else {
|
|
context.src_voltage = SRC_NONE;
|
|
}
|
|
break;
|
|
|
|
// Fan parameters
|
|
case 0x14: // Read current fan speed
|
|
case 0x15: // Read bulk fan speed
|
|
case 0x22: // Clear stored fan speed data
|
|
if (param == 0x01) {
|
|
context.fan = FAN1;
|
|
} else if (param == 0x02) {
|
|
context.fan = FAN2;
|
|
} else {
|
|
context.fan = FAN_NONE;
|
|
}
|
|
break;
|
|
|
|
// This should never be reached
|
|
default: // Unrecognized command
|
|
context.command = UNKNOWN_COMMAND;
|
|
break;
|
|
}
|
|
|
|
/////////////////////////////////
|
|
// Third parameter selection //
|
|
/////////////////////////////////
|
|
|
|
// Check if the command does not require a second parameter. If it does not,
|
|
// return. Only config write requires a second parameter.
|
|
if (context.command != WRITE_CONFIG) {
|
|
return;
|
|
}
|
|
|
|
// Validate that we have a third parameter, else requirements for command are
|
|
// not fulfilled. return unknown command.
|
|
if (command_len < 3) {
|
|
context.command = UNKNOWN_COMMAND;
|
|
return;
|
|
}
|
|
|
|
// Store the parameter
|
|
param = command[2];
|
|
|
|
context.conf = param;
|
|
|
|
|
|
////////////////////////////////
|
|
// Fourth parameter selection //
|
|
////////////////////////////////
|
|
|
|
// Validate that we have a fourth parameter, else requirements for command are
|
|
// not fulfilled. return unknown command. Second parameter is u16, thus two bytes.
|
|
if (command_len < 4) {
|
|
context.command = UNKNOWN_COMMAND;
|
|
return;
|
|
}
|
|
|
|
// Extract the value
|
|
union {
|
|
uint16_t value;
|
|
uint8_t bytes[2];
|
|
} config_value;
|
|
|
|
config_value.bytes[0] = command[3];
|
|
config_value.bytes[1] = command[4];
|
|
|
|
// Store the value
|
|
context.conf_val = config_value.value;
|
|
|
|
// exit
|
|
return;
|
|
}
|
|
|
|
uint8_t route_command(int pos) {
|
|
switch (context.command) {
|
|
case WRITE_CONFIG:
|
|
switch (context.conf) {
|
|
case SAMPLE_TIME:
|
|
// Overwrite the config value
|
|
config.fanspeed_sample_rate = context.conf_val;
|
|
|
|
// Set the flag to store it in the EEPROM
|
|
store_config = true;
|
|
return 0;
|
|
break;
|
|
case CNF_NONE:
|
|
return 0;
|
|
break;
|
|
}
|
|
break;
|
|
case READ_CONFIG:
|
|
{
|
|
switch (context.conf) {
|
|
case SAMPLE_TIME:
|
|
{
|
|
// Validate that pos is within the valid range
|
|
if (pos >= 2) { return 0x00; }
|
|
|
|
// Config only has one parameter so we sent that parameter
|
|
// Create a union to store the data
|
|
union {
|
|
uint16_t value;
|
|
uint8_t bytes[2];
|
|
} config_value;
|
|
config_value.value = config.fanspeed_sample_rate;
|
|
|
|
// Return the corresponding data byte
|
|
return config_value.bytes[1-pos];
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case READ_VOLTAGE:
|
|
{
|
|
// Create a union to store the data
|
|
union {
|
|
int16_t v;
|
|
uint8_t bytes[2];
|
|
} voltage;
|
|
|
|
// Figure out which voltage source to read
|
|
switch (context.src_voltage) {
|
|
case SRC_INTERNAL:
|
|
voltage.v = internal_voltage_read();
|
|
break;
|
|
case SRC_EXTRNAL:
|
|
voltage.v = external_voltage_read();
|
|
break;
|
|
case SRC_THERMISTOR:
|
|
voltage.v = thermistor_voltage_read();
|
|
break;
|
|
default:
|
|
return 0xFF;
|
|
break;
|
|
}
|
|
|
|
// Send the data
|
|
return voltage.bytes[pos];
|
|
}
|
|
case READ_TERMPERATURE:
|
|
{
|
|
uint16_t v_therm = thermistor_voltage_read();
|
|
union {
|
|
int16_t temp;
|
|
uint8_t bytes[2];
|
|
} temperature;
|
|
temperature.temp = (int16_t) ( calculate_thermistor_temp(v_therm) * 1000 );
|
|
return temperature.bytes[pos];
|
|
}
|
|
break;
|
|
case READ_FAN_SPEED:
|
|
if (context.fan == FAN1) {
|
|
return fan1_history[fan1_history_index];
|
|
} else if (context.fan == FAN2) {
|
|
return fan2_history[fan2_history_index];
|
|
} else {
|
|
return 0;
|
|
}
|
|
break;
|
|
case READ_BULK_FAN_SPEED:
|
|
if (context.fan == FAN1) {
|
|
// Validate that pos is valid, if not return 0
|
|
if (pos >= 512) { return 0; }
|
|
|
|
// Calculate the index position
|
|
int16_t index = fan1_history_index - pos;
|
|
if (index < 0) { index = 511-pos; }
|
|
|
|
return fan1_history[index];
|
|
} else if (context.fan == FAN2) {
|
|
// Validate that pos is valid, if not return 0
|
|
if (pos >= 512) { return 0; }
|
|
|
|
// Calculate the index position
|
|
int16_t index = fan2_history_index - pos;
|
|
if (index < 0) { index = 511-pos; }
|
|
|
|
return fan2_history[index];
|
|
} else {
|
|
return 0;
|
|
}
|
|
break;
|
|
case CLEAR_BULK_FAN_SPEED:
|
|
// Overwrite the content of the desired fan array with zeroes
|
|
if (context.fan == FAN1) {
|
|
memset(fan1_history, 0, sizeof(fan1_history));
|
|
} else if (context.fan == FAN2) {
|
|
memset(fan2_history, 0, sizeof(fan2_history));
|
|
}
|
|
return 0;
|
|
break;
|
|
case UNKNOWN_COMMAND:
|
|
default:
|
|
return 0xFF;
|
|
}
|
|
}
|