Command handing works!
The command handler can now receive a command, then it can run a function / return some data based on it.
This commit is contained in:
parent
8e3607cbda
commit
9fd877aab5
@ -1,9 +1,10 @@
|
|||||||
#include "command-handler.h"
|
#include "command-handler.h"
|
||||||
|
|
||||||
command_context_t parse_command(uint8_t *command, uint8_t command_len) {
|
// Initialize empty, global command context
|
||||||
// Create the context
|
volatile command_context_t context = {UNKNOWN_COMMAND, SRC_NONE, FAN_NONE,
|
||||||
command_context_t context;
|
CNF_NONE};
|
||||||
|
|
||||||
|
void parse_command(uint8_t command[], uint8_t command_len) {
|
||||||
///////////////////////
|
///////////////////////
|
||||||
// Command selection //
|
// Command selection //
|
||||||
///////////////////////
|
///////////////////////
|
||||||
@ -11,11 +12,12 @@ command_context_t parse_command(uint8_t *command, uint8_t command_len) {
|
|||||||
// Validate that we have a command
|
// Validate that we have a command
|
||||||
if (command_len < 1) {
|
if (command_len < 1) {
|
||||||
context.command = UNKNOWN_COMMAND;
|
context.command = UNKNOWN_COMMAND;
|
||||||
return context;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t foo = command[0];
|
||||||
|
|
||||||
// Figure out which command to run
|
// Figure out which command to run
|
||||||
switch (command[0]) {
|
switch (foo) {
|
||||||
case 0x11: // Read config
|
case 0x11: // Read config
|
||||||
context.command = READ_CONFIG;
|
context.command = READ_CONFIG;
|
||||||
break;
|
break;
|
||||||
@ -48,14 +50,14 @@ command_context_t parse_command(uint8_t *command, uint8_t command_len) {
|
|||||||
|
|
||||||
// Check if the command does not require a parameter. If it does not, return.
|
// Check if the command does not require a parameter. If it does not, return.
|
||||||
if (context.command == READ_TERMPERATURE) {
|
if (context.command == READ_TERMPERATURE) {
|
||||||
return context;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate that we have a first parameter, else requirements for command are
|
// Validate that we have a first parameter, else requirements for command are
|
||||||
// not fulfilled. return unknown command.
|
// not fulfilled. return unknown command.
|
||||||
if (command_len < 2) {
|
if (command_len < 2) {
|
||||||
context.command = UNKNOWN_COMMAND;
|
context.command = UNKNOWN_COMMAND;
|
||||||
return context;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the parameter
|
// Store the parameter
|
||||||
@ -109,14 +111,14 @@ command_context_t parse_command(uint8_t *command, uint8_t command_len) {
|
|||||||
// Check if the command does not require a second parameter. If it does not,
|
// Check if the command does not require a second parameter. If it does not,
|
||||||
// return. Only config write requires a second parameter.
|
// return. Only config write requires a second parameter.
|
||||||
if (context.command != WRITE_CONFIG) {
|
if (context.command != WRITE_CONFIG) {
|
||||||
return context;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate that we have a first parameter, else requirements for command are
|
// Validate that we have a first parameter, else requirements for command are
|
||||||
// not fulfilled. return unknown command.
|
// not fulfilled. return unknown command.
|
||||||
if (command_len < 3) {
|
if (command_len < 3) {
|
||||||
context.command = UNKNOWN_COMMAND;
|
context.command = UNKNOWN_COMMAND;
|
||||||
return context;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the parameter
|
// Store the parameter
|
||||||
@ -124,8 +126,32 @@ command_context_t parse_command(uint8_t *command, uint8_t command_len) {
|
|||||||
|
|
||||||
// TODO: Handle the config parameters
|
// TODO: Handle the config parameters
|
||||||
|
|
||||||
// Return the context
|
// exit
|
||||||
return context;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void route_command(command_context_t command);
|
uint8_t route_command() {
|
||||||
|
switch (context.command) {
|
||||||
|
WRITE_CONFIG:
|
||||||
|
return WRITE_CONFIG;
|
||||||
|
break;
|
||||||
|
READ_CONFIG:
|
||||||
|
return READ_CONFIG;
|
||||||
|
break;
|
||||||
|
READ_VOLTAGE:
|
||||||
|
return READ_VOLTAGE;
|
||||||
|
break;
|
||||||
|
READ_TERMPERATURE:
|
||||||
|
return READ_TERMPERATURE;
|
||||||
|
break;
|
||||||
|
READ_FAN_SPEED:
|
||||||
|
return READ_FAN_SPEED;
|
||||||
|
break;
|
||||||
|
CLEAR_BULK_FAN_SPEED:
|
||||||
|
return CLEAR_BULK_FAN_SPEED;
|
||||||
|
break;
|
||||||
|
UNKNOWN_COMMAND:
|
||||||
|
return 0xFF;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -12,6 +12,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@ -59,10 +60,10 @@ typedef struct {
|
|||||||
} command_context_t;
|
} command_context_t;
|
||||||
|
|
||||||
// Parses the input string and outputs one of the valid commands
|
// Parses the input string and outputs one of the valid commands
|
||||||
command_context_t parse_command(uint8_t *command, uint8_t command_len);
|
void parse_command(uint8_t *command, uint8_t command_len);
|
||||||
|
|
||||||
// Routes the provided command to the appropriate function to handle it
|
// Routes the provided command to the appropriate function to handle it
|
||||||
void route_command(command_context_t command);
|
uint8_t route_command();
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,17 @@
|
|||||||
#include "i2c.h"
|
#include "i2c.h"
|
||||||
|
#include "command-handler.h"
|
||||||
|
|
||||||
// Basic I2C handling structure is heavily inspired by: https://github.com/microchip-pic-avr-examples/avr128db48-bare-metal-twi-mplab/blob/master/twi-client.X/peripherals/TWI/TWI_client.c
|
// Basic I2C handling structure is heavily inspired by:
|
||||||
|
// https://github.com/microchip-pic-avr-examples/avr128db48-bare-metal-twi-mplab/blob/master/twi-client.X/peripherals/TWI/TWI_client.c
|
||||||
|
|
||||||
volatile uint8_t i2c_recv[I2C_RECV_BUF_SIZE]; // Arbitrary length array to hold the received data, longer than max expected command
|
// We need to keep track of if the stop confition is in regards to a write or
|
||||||
volatile uint8_t i2c_recv_len;
|
// read request
|
||||||
|
volatile bool last_action_write = false;
|
||||||
|
|
||||||
|
volatile uint8_t i2c_recv[I2C_RECV_BUF_SIZE] = {
|
||||||
|
0}; // Arbitrary length array to hold the received
|
||||||
|
// data, longer than max expected command
|
||||||
|
volatile uint8_t i2c_recv_len = 0;
|
||||||
|
|
||||||
void init_i2c(void) {
|
void init_i2c(void) {
|
||||||
// Pin setup
|
// Pin setup
|
||||||
@ -44,28 +52,38 @@ void i2c_reset_recv() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void i2c_write_handler(uint8_t data) {
|
void i2c_write_handler(uint8_t data) {
|
||||||
|
last_action_write = true;
|
||||||
i2c_recv[i2c_recv_len] = data;
|
i2c_recv[i2c_recv_len] = data;
|
||||||
i2c_recv_len++;
|
i2c_recv_len++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void i2c_read_handler() {
|
void i2c_read_handler() {
|
||||||
printf("Master wanted to read.\n");
|
last_action_write = false;
|
||||||
|
TWI0.SDATA = route_command();
|
||||||
}
|
}
|
||||||
|
|
||||||
void i2c_stop_handler() {
|
void i2c_stop_handler() {
|
||||||
// Reset counter and clear receive buffer
|
if (last_action_write) {
|
||||||
i2c_recv[i2c_recv_len] = '\0';
|
// Parse the received command data
|
||||||
printf("%s\n", i2c_recv);
|
parse_command(i2c_recv, i2c_recv_len);
|
||||||
|
} else {
|
||||||
|
// route_command();
|
||||||
|
;
|
||||||
|
}
|
||||||
|
// Reset the buffer for future transmissions
|
||||||
i2c_reset_recv();
|
i2c_reset_recv();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Address received
|
// Address received
|
||||||
ISR(TWI0_TWIS_vect) {
|
ISR(TWI0_TWIS_vect) {
|
||||||
|
// Disable interrupts while handling I2C
|
||||||
|
cli();
|
||||||
|
|
||||||
// Check for the data interrupt flag
|
// Check for the data interrupt flag
|
||||||
if (TWI0.SSTATUS & TWI_DIF_bm) {
|
if (TWI0.SSTATUS & TWI_DIF_bm) {
|
||||||
uint8_t data = 0;
|
uint8_t data = 0;
|
||||||
|
|
||||||
if ( ((TWI0.SSTATUS & TWI_DIR_bm) >> TWI_DIR_bp) == 0 ) {
|
if (((TWI0.SSTATUS & TWI_DIR_bm) >> TWI_DIR_bp) == 0) {
|
||||||
// Data write Master -> Slave
|
// Data write Master -> Slave
|
||||||
data = TWI0.SDATA;
|
data = TWI0.SDATA;
|
||||||
|
|
||||||
@ -74,7 +92,8 @@ ISR(TWI0_TWIS_vect) {
|
|||||||
} else {
|
} else {
|
||||||
// Data read Master <- Slave
|
// Data read Master <- Slave
|
||||||
i2c_read_handler();
|
i2c_read_handler();
|
||||||
data = TWI0.SDATA;
|
// data = TWI0.SDATA;
|
||||||
|
// TWI0.SDATA = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Acknowledge having received
|
// Acknowledge having received
|
||||||
@ -94,4 +113,7 @@ ISR(TWI0_TWIS_vect) {
|
|||||||
TWI0.SCTRLB = TWI_ACKACT_ACK_gc | TWI_SCMD_RESPONSE_gc;
|
TWI0.SCTRLB = TWI_ACKACT_ACK_gc | TWI_SCMD_RESPONSE_gc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Re-enable interrupts
|
||||||
|
sei();
|
||||||
}
|
}
|
||||||
@ -13,9 +13,11 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Include the IO for I2C
|
// Include the IO for I2C
|
||||||
#include <avr/io.h>
|
#include "command-handler.h"
|
||||||
#include <avr/interrupt.h>
|
|
||||||
#include "uart.h"
|
#include "uart.h"
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <util/twi.h>
|
#include <util/twi.h>
|
||||||
|
|
||||||
// Received data info
|
// Received data info
|
||||||
|
|||||||
@ -11,17 +11,20 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "uart.h"
|
#include "uart.h"
|
||||||
#include "i2c.h"
|
#include "i2c.h"
|
||||||
|
#include "command-handler.h"
|
||||||
#include <util/delay.h>
|
#include <util/delay.h>
|
||||||
|
#include <avr/io.h>
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
init_uart((uint16_t)9600);
|
init_uart((uint16_t)9600);
|
||||||
init_i2c();
|
init_i2c();
|
||||||
stdout = &USART_stream;
|
stdout = &USART_stream;
|
||||||
|
|
||||||
|
PORTB.DIRSET = PIN3_bm;
|
||||||
|
|
||||||
sei();
|
sei();
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
printf("\n");
|
;
|
||||||
_delay_ms(500);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -149,6 +149,9 @@
|
|||||||
<property key="program-the-device-with-default-config-words" value="false"/>
|
<property key="program-the-device-with-default-config-words" value="false"/>
|
||||||
<property key="remove-unused-sections" value="true"/>
|
<property key="remove-unused-sections" value="true"/>
|
||||||
</HI-TECH-LINK>
|
</HI-TECH-LINK>
|
||||||
|
<Tool>
|
||||||
|
<property key="debugoptions.useswbreakpoints" value="true"/>
|
||||||
|
</Tool>
|
||||||
<XC8-CO>
|
<XC8-CO>
|
||||||
<property key="coverage-enable" value=""/>
|
<property key="coverage-enable" value=""/>
|
||||||
<property key="stack-guidance" value="false"/>
|
<property key="stack-guidance" value="false"/>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user