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"
|
||||
|
||||
command_context_t parse_command(uint8_t *command, uint8_t command_len) {
|
||||
// Create the context
|
||||
command_context_t context;
|
||||
// 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 //
|
||||
///////////////////////
|
||||
@ -11,11 +12,12 @@ command_context_t parse_command(uint8_t *command, uint8_t command_len) {
|
||||
// Validate that we have a command
|
||||
if (command_len < 1) {
|
||||
context.command = UNKNOWN_COMMAND;
|
||||
return context;
|
||||
}
|
||||
|
||||
uint8_t foo = command[0];
|
||||
|
||||
// Figure out which command to run
|
||||
switch (command[0]) {
|
||||
switch (foo) {
|
||||
case 0x11: // Read config
|
||||
context.command = READ_CONFIG;
|
||||
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.
|
||||
if (context.command == READ_TERMPERATURE) {
|
||||
return context;
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate that we have a first parameter, else requirements for command are
|
||||
// not fulfilled. return unknown command.
|
||||
if (command_len < 2) {
|
||||
context.command = UNKNOWN_COMMAND;
|
||||
return context;
|
||||
return;
|
||||
}
|
||||
|
||||
// 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,
|
||||
// return. Only config write requires a second parameter.
|
||||
if (context.command != WRITE_CONFIG) {
|
||||
return context;
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate that we have a first parameter, else requirements for command are
|
||||
// not fulfilled. return unknown command.
|
||||
if (command_len < 3) {
|
||||
context.command = UNKNOWN_COMMAND;
|
||||
return context;
|
||||
return;
|
||||
}
|
||||
|
||||
// Store the parameter
|
||||
@ -124,8 +126,32 @@ command_context_t parse_command(uint8_t *command, uint8_t command_len) {
|
||||
|
||||
// TODO: Handle the config parameters
|
||||
|
||||
// Return the context
|
||||
return context;
|
||||
// exit
|
||||
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" {
|
||||
#endif
|
||||
|
||||
#include <avr/io.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
@ -59,10 +60,10 @@ typedef struct {
|
||||
} command_context_t;
|
||||
|
||||
// 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
|
||||
void route_command(command_context_t command);
|
||||
uint8_t route_command();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
114
prosjekt.X/i2c.c
114
prosjekt.X/i2c.c
@ -1,18 +1,26 @@
|
||||
#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
|
||||
volatile uint8_t i2c_recv_len;
|
||||
// We need to keep track of if the stop confition is in regards to a write or
|
||||
// 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) {
|
||||
// Pin setup
|
||||
PORTA.DIRSET = PIN2_bm | PIN3_bm;
|
||||
PORTA.PINCTRLUPD = PIN2_bm | PIN3_bm;
|
||||
|
||||
|
||||
// Enable operating in debug
|
||||
TWI0.DBGCTRL = TWI_DBGRUN_bm;
|
||||
|
||||
|
||||
// Initialize the control A register
|
||||
TWI0.CTRLA = TWI_INPUTLVL_I2C_gc // I2C voltage transition level
|
||||
| TWI_SDASETUP_4CYC_gc // Four clock cycles setup time
|
||||
@ -30,7 +38,7 @@ void init_i2c(void) {
|
||||
| PIN2_bm // Respond to all TWI addresses
|
||||
| TWI_ENABLE_bm // Enable acting as a slave
|
||||
;
|
||||
|
||||
|
||||
// Reset the received stuff
|
||||
i2c_reset_recv();
|
||||
}
|
||||
@ -39,59 +47,73 @@ void init_i2c(void) {
|
||||
void i2c_reset_recv() {
|
||||
i2c_recv_len = 0;
|
||||
for (int i = 0; i < I2C_RECV_BUF_SIZE; i++) {
|
||||
i2c_recv[i] = 0;
|
||||
i2c_recv[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void i2c_write_handler(uint8_t data) {
|
||||
i2c_recv[i2c_recv_len] = data;
|
||||
i2c_recv_len++;
|
||||
last_action_write = true;
|
||||
i2c_recv[i2c_recv_len] = data;
|
||||
i2c_recv_len++;
|
||||
}
|
||||
|
||||
void i2c_read_handler() {
|
||||
printf("Master wanted to read.\n");
|
||||
last_action_write = false;
|
||||
TWI0.SDATA = route_command();
|
||||
}
|
||||
|
||||
void i2c_stop_handler() {
|
||||
// Reset counter and clear receive buffer
|
||||
i2c_recv[i2c_recv_len] = '\0';
|
||||
printf("%s\n", i2c_recv);
|
||||
i2c_reset_recv();
|
||||
if (last_action_write) {
|
||||
// Parse the received command data
|
||||
parse_command(i2c_recv, i2c_recv_len);
|
||||
} else {
|
||||
// route_command();
|
||||
;
|
||||
}
|
||||
// Reset the buffer for future transmissions
|
||||
i2c_reset_recv();
|
||||
}
|
||||
|
||||
// Address received
|
||||
ISR(TWI0_TWIS_vect) {
|
||||
// Check for the data interrupt flag
|
||||
if (TWI0.SSTATUS & TWI_DIF_bm) {
|
||||
uint8_t data = 0;
|
||||
|
||||
if ( ((TWI0.SSTATUS & TWI_DIR_bm) >> TWI_DIR_bp) == 0 ) {
|
||||
// Data write Master -> Slave
|
||||
data = TWI0.SDATA;
|
||||
|
||||
// Send the data to the write handler
|
||||
i2c_write_handler(data);
|
||||
} else {
|
||||
// Data read Master <- Slave
|
||||
i2c_read_handler();
|
||||
data = TWI0.SDATA;
|
||||
}
|
||||
|
||||
// Acknowledge having received
|
||||
TWI0.SCTRLB = TWI_ACKACT_ACK_gc | TWI_SCMD_RESPONSE_gc;
|
||||
// Disable interrupts while handling I2C
|
||||
cli();
|
||||
|
||||
// Check for the data interrupt flag
|
||||
if (TWI0.SSTATUS & TWI_DIF_bm) {
|
||||
uint8_t data = 0;
|
||||
|
||||
if (((TWI0.SSTATUS & TWI_DIR_bm) >> TWI_DIR_bp) == 0) {
|
||||
// Data write Master -> Slave
|
||||
data = TWI0.SDATA;
|
||||
|
||||
// Send the data to the write handler
|
||||
i2c_write_handler(data);
|
||||
} else {
|
||||
// Data read Master <- Slave
|
||||
i2c_read_handler();
|
||||
// data = TWI0.SDATA;
|
||||
// TWI0.SDATA = 1;
|
||||
}
|
||||
|
||||
// Check for address match or STOP
|
||||
if (TWI0.SSTATUS & TWI_APIF_bm) {
|
||||
|
||||
if (TWI0.SSTATUS & TWI_AP_ADR_gc) {
|
||||
// Address match, just send ack
|
||||
TWI0.SCTRLB = TWI_ACKACT_ACK_gc | TWI_SCMD_RESPONSE_gc;
|
||||
} else {
|
||||
// STOP condition received
|
||||
i2c_stop_handler();
|
||||
// Send ACK
|
||||
TWI0.SCTRLB = TWI_ACKACT_ACK_gc | TWI_SCMD_RESPONSE_gc;
|
||||
}
|
||||
|
||||
// Acknowledge having received
|
||||
TWI0.SCTRLB = TWI_ACKACT_ACK_gc | TWI_SCMD_RESPONSE_gc;
|
||||
}
|
||||
|
||||
// Check for address match or STOP
|
||||
if (TWI0.SSTATUS & TWI_APIF_bm) {
|
||||
|
||||
if (TWI0.SSTATUS & TWI_AP_ADR_gc) {
|
||||
// Address match, just send ack
|
||||
TWI0.SCTRLB = TWI_ACKACT_ACK_gc | TWI_SCMD_RESPONSE_gc;
|
||||
} else {
|
||||
// STOP condition received
|
||||
i2c_stop_handler();
|
||||
// Send ACK
|
||||
TWI0.SCTRLB = TWI_ACKACT_ACK_gc | TWI_SCMD_RESPONSE_gc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Re-enable interrupts
|
||||
sei();
|
||||
}
|
||||
|
||||
@ -13,13 +13,15 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
// Include the IO for I2C
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include "command-handler.h"
|
||||
#include "uart.h"
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/io.h>
|
||||
#include <stdbool.h>
|
||||
#include <util/twi.h>
|
||||
|
||||
// Received data info
|
||||
#define I2C_RECV_BUF_SIZE 64
|
||||
#define I2C_RECV_BUF_SIZE 64
|
||||
|
||||
// Reset recv to initial state
|
||||
void i2c_reset_recv();
|
||||
|
||||
@ -11,17 +11,20 @@
|
||||
#include <stdlib.h>
|
||||
#include "uart.h"
|
||||
#include "i2c.h"
|
||||
#include "command-handler.h"
|
||||
#include <util/delay.h>
|
||||
#include <avr/io.h>
|
||||
|
||||
int main() {
|
||||
init_uart((uint16_t)9600);
|
||||
init_i2c();
|
||||
stdout = &USART_stream;
|
||||
|
||||
PORTB.DIRSET = PIN3_bm;
|
||||
|
||||
sei();
|
||||
|
||||
while (1) {
|
||||
printf("\n");
|
||||
_delay_ms(500);
|
||||
;
|
||||
}
|
||||
}
|
||||
@ -149,6 +149,9 @@
|
||||
<property key="program-the-device-with-default-config-words" value="false"/>
|
||||
<property key="remove-unused-sections" value="true"/>
|
||||
</HI-TECH-LINK>
|
||||
<Tool>
|
||||
<property key="debugoptions.useswbreakpoints" value="true"/>
|
||||
</Tool>
|
||||
<XC8-CO>
|
||||
<property key="coverage-enable" value=""/>
|
||||
<property key="stack-guidance" value="false"/>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user