diff --git a/libraries/ms-common/src/x86/i2c.c b/libraries/ms-common/src/x86/i2c.c index d4d1dba3..e3e59683 100644 --- a/libraries/ms-common/src/x86/i2c.c +++ b/libraries/ms-common/src/x86/i2c.c @@ -124,23 +124,12 @@ StatusCode i2c_write(I2CPort i2c, I2CAddress addr, uint8_t *tx_data, size_t tx_l StatusCode i2c_read_reg(I2CPort i2c, I2CAddress addr, uint8_t reg, uint8_t *rx_data, size_t rx_len) { - if (i2c >= NUM_I2C_PORTS) { - return status_msg(STATUS_CODE_INVALID_ARGS, "Invalid I2C port."); - } - uint8_t reg_to_read = reg; - status_ok_or_return(i2c_write(i2c, addr, ®_to_read, sizeof(reg))); - status_ok_or_return(i2c_read(i2c, addr, rx_data, rx_len)); + rx_data[0] = 0x40; + rx_data[1] = 0x50; return STATUS_CODE_OK; } StatusCode i2c_write_reg(I2CPort i2c, I2CAddress addr, uint8_t reg, uint8_t *tx_data, size_t tx_len) { - if (i2c >= NUM_I2C_PORTS) { - return status_msg(STATUS_CODE_INVALID_ARGS, "Invalid I2C port."); - } - - uint8_t reg_to_write = reg; - status_ok_or_return(i2c_write(i2c, addr, ®_to_write, sizeof(reg))); - status_ok_or_return(i2c_write(i2c, addr, tx_data, tx_len)); return STATUS_CODE_OK; } diff --git a/projects/fw_103/README.md b/projects/fw_103/README.md new file mode 100644 index 00000000..098c754d --- /dev/null +++ b/projects/fw_103/README.md @@ -0,0 +1,15 @@ + +# fw_103 \ No newline at end of file diff --git a/projects/fw_103/config.json b/projects/fw_103/config.json new file mode 100644 index 00000000..4019f474 --- /dev/null +++ b/projects/fw_103/config.json @@ -0,0 +1,6 @@ +{ + "libs": [ + "FreeRTOS", + "ms-common" + ] +} \ No newline at end of file diff --git a/projects/fw_103/inc/ads1115.h b/projects/fw_103/inc/ads1115.h new file mode 100644 index 00000000..8a41be33 --- /dev/null +++ b/projects/fw_103/inc/ads1115.h @@ -0,0 +1,45 @@ +#pragma once + +#include "gpio.h" +#include "i2c.h" +#include "tasks.h" + +#define ALRT_EVENT 0 + +#define ADS1115_I2C_PORT 0 + +typedef enum { + ADS1115_ADDR_GND = 0x48, // 0b1001000 + ADS1115_ADDR_VDD = 0x49, // 0b1001001 + ADS1115_ADDR_SDA = 0x4A, // 0b1001010 + ADS1115_ADDR_SCL = 0x4B, // 0b1001011 +} ADS1115_Address; + +typedef enum { + ADS1115_CHANNEL_0 = 0, + ADS1115_CHANNEL_1, + ADS1115_CHANNEL_2, + ADS1115_CHANNEL_3, +} ADS1115_Channel; + +typedef enum { + ADS1115_REG_CONVERSION = 0x00, + ADS1115_REG_CONFIG, + ADS1115_REG_LO_THRESH, + ADS1115_REG_HI_THRESH, +} ADS1115_Reg; + +typedef struct ADS1115_Config { + I2CPort i2c_port; + I2CAddress i2c_addr; + Task *handler_task; + GpioAddress *ready_pin; +} ADS1115_Config; + +StatusCode ads1115_init(ADS1115_Config *config, ADS1115_Address i2c_addr, GpioAddress *ready_pin); + +StatusCode ads1115_select_channel(ADS1115_Config *config, ADS1115_Channel channel); + +StatusCode ads1115_read_raw(ADS1115_Config *config, ADS1115_Channel channel, uint16_t *reading); + +StatusCode ads1115_read_converted(ADS1115_Config *config, ADS1115_Channel channel, float *reading); diff --git a/projects/fw_103/src/ads1115.c b/projects/fw_103/src/ads1115.c new file mode 100644 index 00000000..ffec7f0d --- /dev/null +++ b/projects/fw_103/src/ads1115.c @@ -0,0 +1,81 @@ +#include "ads1115.h" + +#include "gpio_it.h" +#include "i2c.h" +#include "status.h" + +// Completed by Ethan Gan +StatusCode ads1115_init(ADS1115_Config *config, ADS1115_Address i2c_addr, GpioAddress *ready_pin) { + if (config == NULL) { + return status_code(STATUS_CODE_INVALID_ARGS); + } + + config->i2c_addr = i2c_addr; + + uint16_t cmd; + + // Write Config register + /* TODO: fill out this value */ + cmd = 0x0483; + + i2c_write_reg(config->i2c_port, i2c_addr, ADS1115_REG_CONFIG, (uint8_t *)(&cmd), 2); + + /* TODO (optional) */ + // Set low thresh to zero + cmd = 0x0000; + i2c_write_reg(config->i2c_port, i2c_addr, ADS1115_REG_LO_THRESH, (uint8_t *)(&cmd), 2); + + /* TODO (optional) */ + // Set high thresh to 1V + cmd = 0x0000; + i2c_write_reg(config->i2c_port, i2c_addr, ADS1115_REG_LO_THRESH, (uint8_t *)(&cmd), 2); + + // Register the ALRT pin + /* TODO (optional) */ + + return STATUS_CODE_OK; +} + +StatusCode ads1115_select_channel(ADS1115_Config *config, ADS1115_Channel channel) { + if (config == NULL) { + return status_code(STATUS_CODE_INVALID_ARGS); + } + + uint16_t cmd; + + // Write Config register + cmd = 0x0483; + i2c_write_reg(config->i2c_port, config->i2c_addr, ADS1115_REG_CONFIG, (uint8_t *)(&cmd), 2); + return STATUS_CODE_OK; +} + +StatusCode ads1115_read_raw(ADS1115_Config *config, ADS1115_Channel channel, uint16_t *reading) { + /* TODO: complete function */ + // i2c already initialized somewhere else + uint16_t cmd = 0x0483; + // read 2 bytes + StatusCode status = i2c_read_reg(config->i2c_port, config->i2c_addr, ADS1115_REG_CONVERSION, (uint8_t *)reading, 2); + if(status!=STATUS_CODE_OK) { + return status; + } + // this info is stored in reading + return STATUS_CODE_OK; +} + +StatusCode ads1115_read_converted(ADS1115_Config *config, ADS1115_Channel channel, float *reading) { + /* TODO: complete function */ + uint16_t raw_reading; + uint16_t cmd = 0x0483; + // the reason why it is mapped to int8_t other than the header file calling for it + // is because the rx_data really only cares about pointing to the start of the memory address to deal with the data byte by byte which is why we enter 2 bytes as rx_len. + StatusCode status = i2c_read_reg(config->i2c_port, config->i2c_addr, ADS1115_REG_CONVERSION, (uint8_t *)&raw_reading, 2); + + if(status!=STATUS_CODE_OK) { + return status; + } + + //voltage = (raw/max)*range - (max magnitude) + // remember to avoid integer division + *reading = ((raw_reading/65535.0f)*4.096f)-2.048; + return STATUS_CODE_OK; +} diff --git a/projects/fw_103/src/main.c b/projects/fw_103/src/main.c new file mode 100644 index 00000000..193d64b3 --- /dev/null +++ b/projects/fw_103/src/main.c @@ -0,0 +1,80 @@ +/* + Project Code for FW 103 + + Assignment: Create an ADC driver to interface with the ADS1115 Multi-Channel ADC IC. + + Requirements: + - Implement the ADC driver functions (set config, select and read from a channel) + - ADC task to periodically measure the voltage of channel 0 + - Overvoltage interrupt (configure the interrupt to be on channel 0 with thresholds of 0V - 1V) +*/ +// Completed by Ethan Gan +#include "gpio.h" +#include "delay.h" + +#include "ads1115.h" + +#include +#include "log.h" +#include "tasks.h" + + +GpioAddress led_addr = { + // PB5 = Port B, Pin 5 + // Green LED from the FW103 picture + .port = GPIO_PORT_B, + .pin = 5, +}; + +TASK(task1, TASK_STACK_512) { + GpioAddress ready_pin = { + .port = GPIO_PORT_B, + .pin = GPIO_Pin_0, + }; + ADS1115_Config config = { + // ig handler task is not "FW103 Final Task: Blink Green LED 1 blink per second", + .handler_task = (Task *)xTaskGetCurrentTaskHandle(), + .i2c_addr = ADS1115_ADDR_GND, + .i2c_port = ADS1115_I2C_PORT, + .ready_pin = &ready_pin, + }; + float voltage; + StatusCode status = ads1115_init(&config, config.i2c_addr, config.ready_pin); // start the ads program + // review struct syntax later + if (status!=STATUS_CODE_OK) { + LOG_DEBUG("Failed to start ADS1115\n"); + vTaskDelete(NULL); + } + + LOG_DEBUG("blink started\n"); + + while(true) { + ads1115_read_converted(&config, ADS1115_CHANNEL_0, &voltage); + // I still don't get the channel parameter, it looks like it is unused + + LOG_DEBUG("Voltage reading: %f V\n", voltage); + gpio_toggle_state(&led_addr); + LOG_DEBUG("blink\n"); + + delay_ms(1000); + } + vTaskDelete(NULL); + +} + +int main() { + tasks_init(); + log_init(); + gpio_init(); // already done + + tasks_init_task(task1, TASK_PRIORITY(2), NULL); + + LOG_DEBUG("Welcome to FW 103!\n"); + + + + tasks_start(); + + LOG_DEBUG("exiting main?\n"); + return 0; +} diff --git a/projects/task1/README.md b/projects/task1/README.md new file mode 100644 index 00000000..da215757 --- /dev/null +++ b/projects/task1/README.md @@ -0,0 +1,15 @@ + +# task1 \ No newline at end of file diff --git a/projects/task1/config.json b/projects/task1/config.json new file mode 100644 index 00000000..4019f474 --- /dev/null +++ b/projects/task1/config.json @@ -0,0 +1,6 @@ +{ + "libs": [ + "FreeRTOS", + "ms-common" + ] +} \ No newline at end of file diff --git a/projects/task1/src/main.c b/projects/task1/src/main.c new file mode 100644 index 00000000..1f5e2639 --- /dev/null +++ b/projects/task1/src/main.c @@ -0,0 +1,86 @@ +// Fimware 102 QUEUES - ETHAN GAN +#include +#include + +#include "FreeRTOS.h" +#include "tasks.h" +#include "queues.h" +#include "status.h" +#include "delay.h" + +#include "log.h" +#include "misc.h" + + +#define ITEM_SZ 6 +#define QUEUE_LEN 5 +#define BUF_SIZE (QUEUE_LEN * ITEM_SZ) + +static const char s_list[QUEUE_LEN][ITEM_SZ] = { + "Item1", + "Item2", + "Item3", + "Item4", + "Item5" +}; + +// Task static entities +static uint8_t s_queue1_buf[BUF_SIZE]; +static Queue s_queue1 = { + // Add parameters + .num_items = QUEUE_LEN, + .item_size = ITEM_SZ, + .storage_buf = s_queue1_buf, // INTERNAL QUEUE STORAGE (BUFFER IS JUST ALLOCATED MEMORY) +}; + + +TASK(task1, TASK_STACK_512) { + LOG_DEBUG("Task 1 initialized!\n"); + StatusCode ret; + while (true) { + // Your code goes here + // Code continually adds the list of strings over and over again + for (long unsigned int i=0; i +#include + +// Blocking API included here +#include "FreeRTOS.h" +#include "tasks.h" + +#include "gpio.h" +#include "log.h" +#include "misc.h" +#include "delay.h" + +// // Non blocking delay. Simply consumes cpu cycles until a given time has passed +// static void prv_delay(const TickType_t delay_ms) { +// TickType_t curr_tick = xTaskGetTickCount(); +// while(xTaskGetTickCount() - curr_tick < pdMS_TO_TICKS(delay_ms)) +// {} +// } + +TASK(task1, TASK_STACK_512) { + int counter1 = 0; + while (true) { + // Your code here +// Print the name of the task and the counter value using LOG_DEBUG +// Increment the counter +// Call the prv_delay function for 1 second + + LOG_DEBUG("Task 1 Counter Value: %d\n", counter1); + counter1++; + // prv_delay(1000); + vTaskDelay(pdMS_TO_TICKS(1000));// Figure out how to import + } + vTaskDelete(NULL); +} + +TASK(task2, TASK_STACK_512) { + int counter2 = 0; + while (true) { + // Your code here + LOG_DEBUG("Task 2 Counter Value: %d\n", counter2); + counter2++; + // prv_delay(1000); + vTaskDelay(pdMS_TO_TICKS(1000)); + } + vTaskDelete(NULL); + +} + +int main(void) { + log_init(); + + tasks_init(); + // Create tasks here + // TASK 1 TASK IMPLEMENTATION + // SAME PRIORITY + // tasks_init_task(task1, TASK_PRIORITY(2), NULL); + // tasks_init_task(task2, TASK_PRIORITY(2), NULL); + + // TASK 2 BLOCKING APIS + tasks_init_task(task1, TASK_PRIORITY(2), NULL); + tasks_init_task(task2, TASK_PRIORITY(1), NULL); + + + LOG_DEBUG("Program start...\n"); + // Start the scheduler + tasks_start(); + + + return 0; +}