From bf3753a012bec032bad77f44f3680432f702c0ce Mon Sep 17 00:00:00 2001 From: "Sebastian H. Gabrielli" Date: Tue, 23 Apr 2024 15:31:32 +0200 Subject: [PATCH 01/15] I2C bulk fan read works --- prosjekt.X/command-handler.c | 48 +++++++++++++------------ prosjekt.X/command-handler.h | 11 ++++-- prosjekt.X/eeprom.c | 26 ++++++++++---- prosjekt.X/eeprom.h | 4 ++- prosjekt.X/main.c | 14 ++++---- prosjekt.X/nbproject/configurations.xml | 2 ++ 6 files changed, 66 insertions(+), 39 deletions(-) diff --git a/prosjekt.X/command-handler.c b/prosjekt.X/command-handler.c index e9ade45..ff9071a 100644 --- a/prosjekt.X/command-handler.c +++ b/prosjekt.X/command-handler.c @@ -38,7 +38,7 @@ void parse_command(uint8_t command[], uint8_t command_len) { context.command = WRITE_CONFIG; break; case 0x22: // Clear stored fan speed data - context.command = CLEAR_BULK_FAN_SPEED; + context.command = READ_BULK_FAN_SPEED; break; default: // Unrecognized command context.command = UNKNOWN_COMMAND; @@ -132,27 +132,29 @@ void parse_command(uint8_t command[], uint8_t command_len) { } uint8_t route_command(int pos) { - 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; + switch (context.command) { + case WRITE_CONFIG: + return WRITE_CONFIG; + case READ_CONFIG: + return READ_CONFIG; + case READ_VOLTAGE: + return READ_VOLTAGE; + case READ_TERMPERATURE: + return READ_TERMPERATURE; + case READ_FAN_SPEED: + return READ_FAN_SPEED; + case READ_BULK_FAN_SPEED: + { + if (context.fan == FAN1) { + return fan1_history[pos]; + } else if (context.fan == FAN2) { + return fan2_history[pos]; + } else { + return 0; + } + } + case UNKNOWN_COMMAND: + default: + return 0xFF; } } diff --git a/prosjekt.X/command-handler.h b/prosjekt.X/command-handler.h index e09afda..3956d07 100644 --- a/prosjekt.X/command-handler.h +++ b/prosjekt.X/command-handler.h @@ -12,10 +12,11 @@ extern "C" { #endif +#include "eeprom.h" #include #include #include - + // Enum of all valid command types typedef enum { WRITE_CONFIG, // Change the configuration @@ -45,8 +46,8 @@ typedef enum { // Enum of all valid fans // TODO: Consider moving into it's own fan page typedef enum { - FAN1, // The first fan - FAN2, // The second fan + FAN1 = 1, // The first fan + FAN2 = 2, // The second fan FAN_NONE // No fan } fans_t; @@ -59,6 +60,10 @@ typedef struct { // TODO: Add config value field for writing } command_context_t; +// Fan history variables +extern volatile uint16_t fan1_history[512]; +extern volatile uint16_t fan2_history[512]; + // Parses the input string and outputs one of the valid commands void parse_command(uint8_t *command, uint8_t command_len); diff --git a/prosjekt.X/eeprom.c b/prosjekt.X/eeprom.c index 5dd4616..2463a0b 100644 --- a/prosjekt.X/eeprom.c +++ b/prosjekt.X/eeprom.c @@ -1,15 +1,15 @@ #include "eeprom.h" // The start address for the controller data -uint8_t EEMEM start_address_controller = 0x00; +uint16_t EEMEM start_address_controller = 0x1400; // Where the writing of the fans points start -uint8_t EEMEM start_address_fan1 = 0x30; -uint8_t EEMEM start_address_fan2 = 0x60; +uint16_t EEMEM start_address_fan1 = 0x1400 + 0x30; +uint16_t EEMEM start_address_fan2 = 0x1400 + 0x60; // The placement for the next datapoint form the fans. -uint8_t EEMEM current_address_fan1 = 0x30; -uint8_t EEMEM current_address_fan2 = 0x60; +uint16_t EEMEM current_address_fan1 = 0x1400 + 0x30; +uint16_t EEMEM current_address_fan2 = 0x1400 + 0x60; // Checks if the EEPROM memory is ready to be written in. void check_eeprom_is_ready(){ @@ -58,7 +58,7 @@ int write_data_point_in_EEPROM(uint8_t byte, uint8_t fan_num){ check_eeprom_is_ready(); if (fan_num == 1){ - eeprom_update_byte(current_address_fan1, byte); + eeprom_write_byte(0x30, byte); current_address_fan1++; return 1; } else if (fan_num == 2){ @@ -97,3 +97,17 @@ uint8_t read_data_point_speed_info(uint8_t fan_num, uint8_t *array){ } return sizeof(array); } + +// Reads all the datapoints to the choosen data. +// it writes the data points in the USART stream. +uint8_t read_single_data_point_speed_info(uint8_t fan_num, uint8_t pos){ + uint8_t byte = 0; + + if (fan_num == 1){ + check_eeprom_is_ready(); + return eeprom_read_byte(0x30 + pos); + } else if (fan_num == 2){ + check_eeprom_is_ready(); + return eeprom_read_byte(start_address_fan2 + pos); + } +} diff --git a/prosjekt.X/eeprom.h b/prosjekt.X/eeprom.h index b584713..098074b 100644 --- a/prosjekt.X/eeprom.h +++ b/prosjekt.X/eeprom.h @@ -36,11 +36,13 @@ void write_struct_from_EEPROM(config_t write_struct); config_t read_struct_from_EEPROM(); // Writes a datapoint in EEPROM -int write_data_point_from_EEPROM(uint8_t byte, uint8_t fan_num); +int write_data_point_in_EEPROM(uint8_t byte, uint8_t fan_num); // Reads all the dataPoints form EEPROM uint8_t read_data_point_speed_info(uint8_t fan_num, uint8_t *array); +uint8_t read_single_data_point_speed_info(uint8_t fan_num, uint8_t pos); + #ifdef __cplusplus } diff --git a/prosjekt.X/main.c b/prosjekt.X/main.c index 428b4ff..2370b1c 100644 --- a/prosjekt.X/main.c +++ b/prosjekt.X/main.c @@ -4,24 +4,28 @@ * * Created on March 6, 2024, 12:34 PM */ +#include #include "uart.h" #include "voltage.h" #define RTC_PERIOD (511) #define DELAY_TIME 1000 #include "eeprom.h" #include -#include #include #include #include #define F_CPU 4E6 #include "command-handler.h" #include "i2c.h" +#include "themistor-temp.h" #include "uart.h" #include -#include #include -#include "themistor-temp.h" +#include + +// Fan history variables +volatile uint16_t fan1_history[512] = {1, 2, 3, 4}; +volatile uint16_t fan2_history[512] = {2, 3, 4, 5}; int main() { init_uart((uint16_t)9600); @@ -29,12 +33,10 @@ int main() { stdout = &USART_stream; PORTB.DIRSET = PIN3_bm; - + sei(); while (1) { - // uint16_t adcVal = ADC0_read(); - // printf("The values: \n%u , %u\n",VREF_REFSEL_VDD_gc , adcVal); ; } } diff --git a/prosjekt.X/nbproject/configurations.xml b/prosjekt.X/nbproject/configurations.xml index 9e4c7b2..12d6430 100644 --- a/prosjekt.X/nbproject/configurations.xml +++ b/prosjekt.X/nbproject/configurations.xml @@ -27,6 +27,8 @@ uart.c eeprom.c voltage.c + i2c.c + command-handler.c Makefile -- 2.43.0 From d964ebea372d212143b15aa72bab31cc56b14306 Mon Sep 17 00:00:00 2001 From: "Sebastian H. Gabrielli" Date: Tue, 23 Apr 2024 15:45:25 +0200 Subject: [PATCH 02/15] Handle read single fan speed --- prosjekt.X/command-handler.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/prosjekt.X/command-handler.c b/prosjekt.X/command-handler.c index ff9071a..8ca971a 100644 --- a/prosjekt.X/command-handler.c +++ b/prosjekt.X/command-handler.c @@ -142,9 +142,15 @@ uint8_t route_command(int pos) { case READ_TERMPERATURE: return READ_TERMPERATURE; case READ_FAN_SPEED: - return READ_FAN_SPEED; + if (context.fan == FAN1) { + return fan1_history[0]; + } else if (context.fan == FAN2) { + return fan2_history[0]; + } else { + return 0; + } + break; case READ_BULK_FAN_SPEED: - { if (context.fan == FAN1) { return fan1_history[pos]; } else if (context.fan == FAN2) { @@ -152,7 +158,7 @@ uint8_t route_command(int pos) { } else { return 0; } - } + break; case UNKNOWN_COMMAND: default: return 0xFF; -- 2.43.0 From 1eaeeef9a0c954056105593c8984cd34839bc066 Mon Sep 17 00:00:00 2001 From: "Sebastian H. Gabrielli" Date: Wed, 24 Apr 2024 13:24:15 +0200 Subject: [PATCH 03/15] Read temperature over I2C works Has not been tested with thermistor as I didn't have the hardware. Testing with a hardcoded positive number works. --- prosjekt.X/command-handler.c | 11 ++++++++++- prosjekt.X/command-handler.h | 2 ++ prosjekt.X/main.c | 2 ++ prosjekt.X/nbproject/configurations.xml | 1 + 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/prosjekt.X/command-handler.c b/prosjekt.X/command-handler.c index 8ca971a..8da542d 100644 --- a/prosjekt.X/command-handler.c +++ b/prosjekt.X/command-handler.c @@ -140,7 +140,16 @@ uint8_t route_command(int pos) { case READ_VOLTAGE: return READ_VOLTAGE; case READ_TERMPERATURE: - return 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[0]; diff --git a/prosjekt.X/command-handler.h b/prosjekt.X/command-handler.h index 3956d07..bcd4063 100644 --- a/prosjekt.X/command-handler.h +++ b/prosjekt.X/command-handler.h @@ -16,6 +16,8 @@ extern "C" { #include #include #include +#include "voltage.h" +#include "themistor-temp.h" // Enum of all valid command types typedef enum { diff --git a/prosjekt.X/main.c b/prosjekt.X/main.c index 2370b1c..e8b06f4 100644 --- a/prosjekt.X/main.c +++ b/prosjekt.X/main.c @@ -29,6 +29,8 @@ volatile uint16_t fan2_history[512] = {2, 3, 4, 5}; int main() { init_uart((uint16_t)9600); + ADC0_init(); + init_led(); init_i2c(); stdout = &USART_stream; diff --git a/prosjekt.X/nbproject/configurations.xml b/prosjekt.X/nbproject/configurations.xml index 12d6430..22bd261 100644 --- a/prosjekt.X/nbproject/configurations.xml +++ b/prosjekt.X/nbproject/configurations.xml @@ -29,6 +29,7 @@ voltage.c i2c.c command-handler.c + thermistor-temp.c Makefile -- 2.43.0 From 822845cc7abc45ca2187b0a42a91b8ca7761c49e Mon Sep 17 00:00:00 2001 From: "Sebastian H. Gabrielli" Date: Wed, 24 Apr 2024 13:40:45 +0200 Subject: [PATCH 04/15] Read temperature command works --- prosjekt.X/command-handler.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/prosjekt.X/command-handler.c b/prosjekt.X/command-handler.c index 8da542d..d109bdc 100644 --- a/prosjekt.X/command-handler.c +++ b/prosjekt.X/command-handler.c @@ -138,7 +138,32 @@ uint8_t route_command(int pos) { case READ_CONFIG: return READ_CONFIG; case READ_VOLTAGE: - return 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(); -- 2.43.0 From b8d19731ad2e057a084b955c5ec77f68f30b0ecf Mon Sep 17 00:00:00 2001 From: "Sebastian H. Gabrielli" Date: Wed, 24 Apr 2024 15:43:27 +0200 Subject: [PATCH 05/15] Clear fan data works --- prosjekt.X/command-handler.c | 11 +++++++++-- prosjekt.X/command-handler.h | 16 ++++++++-------- prosjekt.X/i2c.c | 16 ++++++++++++++++ 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/prosjekt.X/command-handler.c b/prosjekt.X/command-handler.c index d109bdc..e5aec24 100644 --- a/prosjekt.X/command-handler.c +++ b/prosjekt.X/command-handler.c @@ -38,7 +38,7 @@ void parse_command(uint8_t command[], uint8_t command_len) { context.command = WRITE_CONFIG; break; case 0x22: // Clear stored fan speed data - context.command = READ_BULK_FAN_SPEED; + context.command = CLEAR_BULK_FAN_SPEED; break; default: // Unrecognized command context.command = UNKNOWN_COMMAND; @@ -89,7 +89,6 @@ void parse_command(uint8_t command[], uint8_t command_len) { case 0x14: // Read current fan speed case 0x15: // Read bulk fan speed case 0x22: // Clear stored fan speed data - context.command = READ_BULK_FAN_SPEED; if (param == 0x01) { context.fan = FAN1; } else if (param == 0x02) { @@ -193,6 +192,14 @@ uint8_t route_command(int pos) { 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)); + } + break; case UNKNOWN_COMMAND: default: return 0xFF; diff --git a/prosjekt.X/command-handler.h b/prosjekt.X/command-handler.h index bcd4063..a03432d 100644 --- a/prosjekt.X/command-handler.h +++ b/prosjekt.X/command-handler.h @@ -21,14 +21,14 @@ extern "C" { // Enum of all valid command types typedef enum { - WRITE_CONFIG, // Change the configuration - READ_CONFIG, // Read, and print the current configuration - READ_VOLTAGE, // Read, and print a voltage - READ_TERMPERATURE, // Read, and print the temperature - READ_FAN_SPEED, // Read, and print the current fan speed - READ_BULK_FAN_SPEED, // Read, and print the stored back fan speed data - CLEAR_BULK_FAN_SPEED, // Clear the buffer of stored fan speed data - UNKNOWN_COMMAND // An unrecognized command has been sent + WRITE_CONFIG = 0x21, // Change the configuration + READ_CONFIG = 0x11, // Read, and print the current configuration + READ_VOLTAGE = 0x12, // Read, and print a voltage + READ_TERMPERATURE = 0x13, // Read, and print the temperature + READ_FAN_SPEED = 0x14, // Read, and print the current fan speed + READ_BULK_FAN_SPEED = 0x15, // Read, and print the stored back fan speed data + CLEAR_BULK_FAN_SPEED = 0x22, // Clear the buffer of stored fan speed data + UNKNOWN_COMMAND // An unrecognized command has been sent } command_t; // Enum of all valid voltage sources diff --git a/prosjekt.X/i2c.c b/prosjekt.X/i2c.c index c11fdcf..a29dc84 100644 --- a/prosjekt.X/i2c.c +++ b/prosjekt.X/i2c.c @@ -67,7 +67,23 @@ void i2c_stop_handler() { if (last_action_write) { // Parse the received command data parse_command(i2c_recv, i2c_recv_len); + + if (i2c_recv[0] == 0x22) { + route_command(0); + } } + + /* Write only commands need to be routed now + switch (i2c_recv[0]) { + WRITE_CONFIG: + CLEAR_BULK_FAN_SPEED: + route_command(0); + break; + default: + break; + } + */ + // Reset the buffer for future transmissions i2c_reset_recv(); } -- 2.43.0 From fb24365469eb817d05df645fef5500cf14d9e72f Mon Sep 17 00:00:00 2001 From: "Sebastian H. Gabrielli" Date: Wed, 24 Apr 2024 15:50:40 +0200 Subject: [PATCH 06/15] Prepare for write config --- prosjekt.X/eeprom.h | 2 +- prosjekt.X/i2c.c | 2 +- prosjekt.X/main.c | 14 +++++++++++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/prosjekt.X/eeprom.h b/prosjekt.X/eeprom.h index 098074b..517fad9 100644 --- a/prosjekt.X/eeprom.h +++ b/prosjekt.X/eeprom.h @@ -23,7 +23,7 @@ extern "C" { // Struct for information on the controller. typedef struct { - uint8_t fanSpeed; + uint16_t ms_fanspeed_sample_rate; } config_t; // Check if EEPROM is ready to be written in diff --git a/prosjekt.X/i2c.c b/prosjekt.X/i2c.c index a29dc84..43f65ab 100644 --- a/prosjekt.X/i2c.c +++ b/prosjekt.X/i2c.c @@ -68,7 +68,7 @@ void i2c_stop_handler() { // Parse the received command data parse_command(i2c_recv, i2c_recv_len); - if (i2c_recv[0] == 0x22) { + if (i2c_recv[0] == CLEAR_BULK_FAN_SPEED || i2c_recv[0] == WRITE_CONFIG) { route_command(0); } } diff --git a/prosjekt.X/main.c b/prosjekt.X/main.c index e8b06f4..35b71c9 100644 --- a/prosjekt.X/main.c +++ b/prosjekt.X/main.c @@ -27,18 +27,30 @@ volatile uint16_t fan1_history[512] = {1, 2, 3, 4}; volatile uint16_t fan2_history[512] = {2, 3, 4, 5}; +// Default config is 500ms sample rate +volatile config_t config = { 500 }; +volatile bool store_config = false; + int main() { + // Initialize functionality init_uart((uint16_t)9600); ADC0_init(); init_led(); init_i2c(); stdout = &USART_stream; + // Read the stored config struct + config = read_struct_from_EEPROM(); + PORTB.DIRSET = PIN3_bm; sei(); while (1) { - ; + // If we have made a config change, store it. + if (store_config) { + write_struct_from_EEPROM(config); + store_config = false; + } } } -- 2.43.0 From dd624d4d48419b714e5dbceba69b144ce363936a Mon Sep 17 00:00:00 2001 From: "Sebastian H. Gabrielli" Date: Sat, 27 Apr 2024 14:52:46 +0200 Subject: [PATCH 07/15] Reading config parameter works --- prosjekt.X/command-handler.c | 62 +++++++++++++++++++++++++++++++----- prosjekt.X/command-handler.h | 9 ++++-- prosjekt.X/main.c | 3 +- 3 files changed, 63 insertions(+), 11 deletions(-) diff --git a/prosjekt.X/command-handler.c b/prosjekt.X/command-handler.c index e5aec24..ad91602 100644 --- a/prosjekt.X/command-handler.c +++ b/prosjekt.X/command-handler.c @@ -54,7 +54,7 @@ void parse_command(uint8_t command[], uint8_t command_len) { return; } - // Validate that we have a first parameter, else requirements for command are + // 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; @@ -69,7 +69,11 @@ void parse_command(uint8_t command[], uint8_t command_len) { // Configuration parameters case 0x11: // Read config case 0x21: // Write config - // TODO: Handle parameters for config + if (param == 0x01) { + context.conf = SAMPLE_TIME; + } else { + context.conf = CNF_NONE; + } break; // Voltage parameters @@ -104,9 +108,9 @@ void parse_command(uint8_t command[], uint8_t command_len) { break; } - //////////////////////////////// - // Second parameter selection // - //////////////////////////////// + ///////////////////////////////// + // 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. @@ -114,7 +118,7 @@ void parse_command(uint8_t command[], uint8_t command_len) { return; } - // Validate that we have a first parameter, else requirements for command are + // 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; @@ -124,8 +128,32 @@ void parse_command(uint8_t command[], uint8_t command_len) { // Store the parameter param = command[2]; - // TODO: Handle the config parameters + 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 < 5) { + 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; } @@ -135,7 +163,25 @@ uint8_t route_command(int pos) { case WRITE_CONFIG: return WRITE_CONFIG; case READ_CONFIG: - return READ_CONFIG; + { + // 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.ms_fanspeed_sample_rate; + + uint8_t data = config_value.bytes[1-pos]; + + // Return the corresponding data byte + return data; + } + break; + case READ_VOLTAGE: { // Create a union to store the data diff --git a/prosjekt.X/command-handler.h b/prosjekt.X/command-handler.h index a03432d..cf0f428 100644 --- a/prosjekt.X/command-handler.h +++ b/prosjekt.X/command-handler.h @@ -42,7 +42,8 @@ typedef enum { // Enum of all valid config options // TODO: Move into config header file typedef enum { - CNF_NONE, // No config option + SAMPLE_TIME = 0x01, // Time between each fan speed sample + CNF_NONE, // No config option } config_option_t; // Enum of all valid fans @@ -59,13 +60,17 @@ typedef struct { src_voltage_t src_voltage; // The selected voltage source fans_t fan; // The selected fan config_option_t conf; // The configuration option to cange - // TODO: Add config value field for writing + uint16_t conf_val; // The value of the config option to change } command_context_t; // Fan history variables extern volatile uint16_t fan1_history[512]; extern volatile uint16_t fan2_history[512]; +// Config +extern volatile config_t config; +extern volatile bool store_config; + // Parses the input string and outputs one of the valid commands void parse_command(uint8_t *command, uint8_t command_len); diff --git a/prosjekt.X/main.c b/prosjekt.X/main.c index 35b71c9..57d6a81 100644 --- a/prosjekt.X/main.c +++ b/prosjekt.X/main.c @@ -40,7 +40,8 @@ int main() { stdout = &USART_stream; // Read the stored config struct - config = read_struct_from_EEPROM(); + //config = read_struct_from_EEPROM(); + config.ms_fanspeed_sample_rate = 500; PORTB.DIRSET = PIN3_bm; -- 2.43.0 From f654ae96f69dd592c72e04af46214b7f9a5ee72e Mon Sep 17 00:00:00 2001 From: "Sebastian H. Gabrielli" Date: Sat, 27 Apr 2024 14:55:44 +0200 Subject: [PATCH 08/15] Add case structure for better handling of future config params A case structure to send the correct config value has been added. --- prosjekt.X/command-handler.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/prosjekt.X/command-handler.c b/prosjekt.X/command-handler.c index ad91602..1de3001 100644 --- a/prosjekt.X/command-handler.c +++ b/prosjekt.X/command-handler.c @@ -164,23 +164,27 @@ uint8_t route_command(int pos) { return WRITE_CONFIG; case READ_CONFIG: { - // Validate that pos is within the valid range - if (pos >= 2) { return 0x00; } + 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.ms_fanspeed_sample_rate; - // 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.ms_fanspeed_sample_rate; - - uint8_t data = config_value.bytes[1-pos]; - - // Return the corresponding data byte - return data; + // Return the corresponding data byte + return config_value.bytes[1-pos]; + } + break; + } } - break; + break; case READ_VOLTAGE: { -- 2.43.0 From ae1c50ee09f2a64f93c0e17cbeefae3c338c1ea7 Mon Sep 17 00:00:00 2001 From: "Sebastian H. Gabrielli" Date: Sat, 27 Apr 2024 15:39:46 +0200 Subject: [PATCH 09/15] Writing config works --- prosjekt.X/command-handler.c | 13 +++++++++++-- prosjekt.X/main.c | 3 +-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/prosjekt.X/command-handler.c b/prosjekt.X/command-handler.c index 1de3001..347043c 100644 --- a/prosjekt.X/command-handler.c +++ b/prosjekt.X/command-handler.c @@ -137,7 +137,7 @@ void parse_command(uint8_t command[], uint8_t command_len) { // 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 < 5) { + if (command_len < 4) { context.command = UNKNOWN_COMMAND; return; } @@ -161,7 +161,16 @@ void parse_command(uint8_t command[], uint8_t command_len) { uint8_t route_command(int pos) { switch (context.command) { case WRITE_CONFIG: - return WRITE_CONFIG; + switch (context.conf) { + case SAMPLE_TIME: + // Overwrite the config value + config.ms_fanspeed_sample_rate = context.conf_val; + + // Set the flag to store it in the EEPROM + store_config = true; + break; + } + break; case READ_CONFIG: { switch (context.conf) { diff --git a/prosjekt.X/main.c b/prosjekt.X/main.c index 57d6a81..35b71c9 100644 --- a/prosjekt.X/main.c +++ b/prosjekt.X/main.c @@ -40,8 +40,7 @@ int main() { stdout = &USART_stream; // Read the stored config struct - //config = read_struct_from_EEPROM(); - config.ms_fanspeed_sample_rate = 500; + config = read_struct_from_EEPROM(); PORTB.DIRSET = PIN3_bm; -- 2.43.0 From 8f61e6b99830c2f93b67e8c17cf4c20f40ee0dbd Mon Sep 17 00:00:00 2001 From: "Sebastian H. Gabrielli" Date: Sun, 28 Apr 2024 20:10:01 +0200 Subject: [PATCH 10/15] Validate that we do not overflow the receive buffer Closes #20 --- prosjekt.X/i2c.c | 5 +++++ prosjekt.X/nbproject/configurations.xml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/prosjekt.X/i2c.c b/prosjekt.X/i2c.c index 43f65ab..aff2ac4 100644 --- a/prosjekt.X/i2c.c +++ b/prosjekt.X/i2c.c @@ -53,6 +53,11 @@ void i2c_reset_recv() { void i2c_write_handler(uint8_t data) { last_action_write = true; + + // Validate that we are not overflowing the buffer + if (i2c_recv_len >= I2C_RECV_BUF_SIZE) { return; } + + // Write the data to the receive buffer i2c_recv[i2c_recv_len] = data; i2c_recv_len++; } diff --git a/prosjekt.X/nbproject/configurations.xml b/prosjekt.X/nbproject/configurations.xml index 22bd261..af7016b 100644 --- a/prosjekt.X/nbproject/configurations.xml +++ b/prosjekt.X/nbproject/configurations.xml @@ -42,7 +42,7 @@ nEdbgTool XC8 - 2.45 + 2.46 2 -- 2.43.0 From ba54ff20eff042b635337543cfde730fe484b303 Mon Sep 17 00:00:00 2001 From: "Sebastian H. Gabrielli" Date: Sun, 28 Apr 2024 20:12:24 +0200 Subject: [PATCH 11/15] Fix master slave naming and remove dead code --- prosjekt.X/i2c.c | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/prosjekt.X/i2c.c b/prosjekt.X/i2c.c index aff2ac4..716618b 100644 --- a/prosjekt.X/i2c.c +++ b/prosjekt.X/i2c.c @@ -8,9 +8,7 @@ // 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[I2C_RECV_BUF_SIZE] = {0}; volatile uint8_t i2c_recv_len = 0; void init_i2c(void) { @@ -73,22 +71,12 @@ void i2c_stop_handler() { // Parse the received command data parse_command(i2c_recv, i2c_recv_len); + // If the received command is a write only command we want to route it now. if (i2c_recv[0] == CLEAR_BULK_FAN_SPEED || i2c_recv[0] == WRITE_CONFIG) { route_command(0); } } - /* Write only commands need to be routed now - switch (i2c_recv[0]) { - WRITE_CONFIG: - CLEAR_BULK_FAN_SPEED: - route_command(0); - break; - default: - break; - } - */ - // Reset the buffer for future transmissions i2c_reset_recv(); } @@ -103,16 +91,14 @@ ISR(TWI0_TWIS_vect) { uint8_t data = 0; if (((TWI0.SSTATUS & TWI_DIR_bm) >> TWI_DIR_bp) == 0) { - // Data write Master -> Slave + // Data write Controller -> Target data = TWI0.SDATA; // Send the data to the write handler i2c_write_handler(data); } else { - // Data read Master <- Slave + // Data read Controller <- Target i2c_read_handler(); - // data = TWI0.SDATA; - // TWI0.SDATA = 1; } // Acknowledge having received -- 2.43.0 From 6acdb2beb6b82449b37077a18015561ca7ff3827 Mon Sep 17 00:00:00 2001 From: "Sebastian H. Gabrielli" Date: Sun, 28 Apr 2024 20:14:27 +0200 Subject: [PATCH 12/15] Rename receive buffer for better clarity & add comment --- prosjekt.X/i2c.c | 12 +++++++----- prosjekt.X/i2c.h | 5 +++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/prosjekt.X/i2c.c b/prosjekt.X/i2c.c index 716618b..c0d6f45 100644 --- a/prosjekt.X/i2c.c +++ b/prosjekt.X/i2c.c @@ -8,7 +8,9 @@ // read request volatile bool last_action_write = false; -volatile uint8_t i2c_recv[I2C_RECV_BUF_SIZE] = {0}; +// Buffer to hold the received data +volatile uint8_t i2c_recv_buf[I2C_RECV_BUF_SIZE] = {0}; +// Counter to know which datapoint we're on volatile uint8_t i2c_recv_len = 0; void init_i2c(void) { @@ -45,7 +47,7 @@ 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_buf[i] = 0; } } @@ -56,7 +58,7 @@ void i2c_write_handler(uint8_t data) { if (i2c_recv_len >= I2C_RECV_BUF_SIZE) { return; } // Write the data to the receive buffer - i2c_recv[i2c_recv_len] = data; + i2c_recv_buf[i2c_recv_len] = data; i2c_recv_len++; } @@ -69,10 +71,10 @@ void i2c_read_handler() { void i2c_stop_handler() { if (last_action_write) { // Parse the received command data - parse_command(i2c_recv, i2c_recv_len); + parse_command(i2c_recv_buf, i2c_recv_len); // If the received command is a write only command we want to route it now. - if (i2c_recv[0] == CLEAR_BULK_FAN_SPEED || i2c_recv[0] == WRITE_CONFIG) { + if (i2c_recv_buf[0] == CLEAR_BULK_FAN_SPEED || i2c_recv_buf[0] == WRITE_CONFIG) { route_command(0); } } diff --git a/prosjekt.X/i2c.h b/prosjekt.X/i2c.h index 342f459..cd7c646 100644 --- a/prosjekt.X/i2c.h +++ b/prosjekt.X/i2c.h @@ -20,8 +20,9 @@ extern "C" { #include #include -// Received data info -#define I2C_RECV_BUF_SIZE 64 +// Received data buffer size +// The size is larger than any expected command lenght +#define I2C_RECV_BUF_SIZE 16 // Reset recv to initial state void i2c_reset_recv(); -- 2.43.0 From d31f03b6c76023518a2565d4114bb2e61ae0914e Mon Sep 17 00:00:00 2001 From: "Sebastian H. Gabrielli" Date: Sun, 28 Apr 2024 20:19:57 +0200 Subject: [PATCH 13/15] Delete unused EEPROM code & update comments We don't use a lot of the written EEPROM code. This unused code has now been deleted --- prosjekt.X/eeprom.c | 93 ++++++--------------------------------------- prosjekt.X/eeprom.h | 18 ++------- prosjekt.X/i2c.h | 2 +- 3 files changed, 16 insertions(+), 97 deletions(-) diff --git a/prosjekt.X/eeprom.c b/prosjekt.X/eeprom.c index 2463a0b..a0db672 100644 --- a/prosjekt.X/eeprom.c +++ b/prosjekt.X/eeprom.c @@ -3,15 +3,7 @@ // The start address for the controller data uint16_t EEMEM start_address_controller = 0x1400; -// Where the writing of the fans points start -uint16_t EEMEM start_address_fan1 = 0x1400 + 0x30; -uint16_t EEMEM start_address_fan2 = 0x1400 + 0x60; - -// The placement for the next datapoint form the fans. -uint16_t EEMEM current_address_fan1 = 0x1400 + 0x30; -uint16_t EEMEM current_address_fan2 = 0x1400 + 0x60; - -// Checks if the EEPROM memory is ready to be written in. +// Checks if the EEPROM memory is ready to be written in and waits until it is. void check_eeprom_is_ready(){ while(1){ if (eeprom_is_ready()){ @@ -23,91 +15,28 @@ void check_eeprom_is_ready(){ } -// Takes inn a struct by the form of config_t -// Checks if the eeprom is ready to be written in -// Checks if it has been written information at the address -// If true, the infromation is replaced with the intaken struct -// else the intaken struct is written at the address. void write_struct_from_EEPROM(config_t write_struct){ + // Calculate the required storage size uint8_t struct_size = sizeof(write_struct); + // Wait for the EEPROM to be ready check_eeprom_is_ready(); + // Update the stored config stuct eeprom_update_block((void*) &write_struct,(void*) &start_address_controller, struct_size); - } -// Reads the memory block at the address start_address_controller -// returns a struct in form of config_t config_t read_struct_from_EEPROM(){ - //is eeprom ready?? - config_t read_struct; + // Create a config struct to hold the received data + config_t read_struct = { 0 }; uint8_t struct_size = sizeof(read_struct); + // Wait for the EEPROM to be ready check_eeprom_is_ready(); + // Read the data from the EEPROM eeprom_read_block((void *) &read_struct,(void*) &start_address_controller, struct_size); + + // Return the data return read_struct; -} - -// Takes inn a dataPoint and what data set it belongs to -// checks if EEPROM is ready -// If the dataset is 1, the datapoint is written at the address. -// If the dataset is 2 its written at another point. -int write_data_point_in_EEPROM(uint8_t byte, uint8_t fan_num){ - - check_eeprom_is_ready(); - if (fan_num == 1){ - eeprom_write_byte(0x30, byte); - current_address_fan1++; - return 1; - } else if (fan_num == 2){ - eeprom_update_byte(current_address_fan2, byte); - current_address_fan2++; - return 1; - } else{ - return 0; - } -} - -// Reads all the datapoints to the choosen data. -// it writes the data points in the USART stream. -uint8_t read_data_point_speed_info(uint8_t fan_num, uint8_t *array){ - uint8_t byte = 0; - - if (fan_num == 1){ - uint8_t len = current_address_fan1 - start_address_fan1; - - check_eeprom_is_ready(); - - for (uint8_t i = 0; i #include - - // Struct for information on the controller. typedef struct { uint16_t ms_fanspeed_sample_rate; } config_t; -// Check if EEPROM is ready to be written in +// Check if EEPROM is ready to be written to void check_eeprom_is_ready(); -// Writes a struct in EEPROM +// Writes a config_t struct to the EEPROM void write_struct_from_EEPROM(config_t write_struct); -// Read data from EEPROM and return it as a controller struct +// Read data from EEPROM and return it as a config_t struct config_t read_struct_from_EEPROM(); -// Writes a datapoint in EEPROM -int write_data_point_in_EEPROM(uint8_t byte, uint8_t fan_num); - -// Reads all the dataPoints form EEPROM -uint8_t read_data_point_speed_info(uint8_t fan_num, uint8_t *array); - -uint8_t read_single_data_point_speed_info(uint8_t fan_num, uint8_t pos); - #ifdef __cplusplus } diff --git a/prosjekt.X/i2c.h b/prosjekt.X/i2c.h index cd7c646..1272b11 100644 --- a/prosjekt.X/i2c.h +++ b/prosjekt.X/i2c.h @@ -21,7 +21,7 @@ extern "C" { #include // Received data buffer size -// The size is larger than any expected command lenght +// The size is larger than any expected command length #define I2C_RECV_BUF_SIZE 16 // Reset recv to initial state -- 2.43.0 From 4666f79dd32d4581c2da4c88b17813e7076d8418 Mon Sep 17 00:00:00 2001 From: "Sebastian H. Gabrielli" Date: Sun, 28 Apr 2024 20:23:17 +0200 Subject: [PATCH 14/15] Init the fan history as 0 and add Ina to authors in main --- prosjekt.X/main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/prosjekt.X/main.c b/prosjekt.X/main.c index 35b71c9..2fe917d 100644 --- a/prosjekt.X/main.c +++ b/prosjekt.X/main.c @@ -1,6 +1,6 @@ /* * File: main.c - * Author: Sebastian H. Gabrielli, Helle Augland Grasmo + * Author: Sebastian H. Gabrielli, Helle Augland Grasmo, Ina Min Rørnes * * Created on March 6, 2024, 12:34 PM */ @@ -24,8 +24,8 @@ #include // Fan history variables -volatile uint16_t fan1_history[512] = {1, 2, 3, 4}; -volatile uint16_t fan2_history[512] = {2, 3, 4, 5}; +volatile uint16_t fan1_history[512] = { 0 }; +volatile uint16_t fan2_history[512] = { 0 }; // Default config is 500ms sample rate volatile config_t config = { 500 }; -- 2.43.0 From 91cffd78f4d47ddef676eba19c5a81b4a72f73ae Mon Sep 17 00:00:00 2001 From: "Sebastian H. Gabrielli" Date: Sun, 28 Apr 2024 20:46:50 +0200 Subject: [PATCH 15/15] Move data initialization into write, as it is only needed there --- prosjekt.X/i2c.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/prosjekt.X/i2c.c b/prosjekt.X/i2c.c index c0d6f45..ded4482 100644 --- a/prosjekt.X/i2c.c +++ b/prosjekt.X/i2c.c @@ -90,11 +90,10 @@ 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 Controller -> Target - data = TWI0.SDATA; + uint8_t data = TWI0.SDATA; // Send the data to the write handler i2c_write_handler(data); -- 2.43.0