diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..d11f98b --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,17 @@ +{ + "configurations": [ + { + "name": "Linux", + "includePath": [ + "${workspaceFolder}/**", + "/usr/include/libgpio_ftdi" + ], + "defines": [], + "compilerPath": "/usr/bin/clang", + "cStandard": "c11", + "cppStandard": "c++17", + "intelliSenseMode": "clang-x64" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..9325639 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,47 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "(gdb) Launch distance", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/bin/distance", + "args": [], + "stopAtEntry": true, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + }, + { + "name": "(gdb) Launch unit test", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/bin/test/unit/distance", + "args": [], + "stopAtEntry": true, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + } + + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..80f23f0 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "files.associations": { + "ftdi_dev.h": "c", + "gpio_sys.h": "c", + "stdbool.h": "c", + "ads1115.h": "c" + } +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..554ee63 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,115 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "all", + "type":"shell", + "command": "make all -j8", + "problemMatcher": { + "base": "$gcc", + "owner": "gcc", + "fileLocation": [ + "relative", + "${workspaceFolder}" + ] + }, + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "label": "check", + "type":"shell", + "command": "make check -j8", + "problemMatcher": { + "base": "$gcc", + "owner": "gcc", + "fileLocation": [ + "relative", + "${workspaceFolder}" + ] + }, + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "label": "clean", + "type":"shell", + "command": "make clean -j8", + "problemMatcher": { + "base": "$gcc", + "owner": "gcc", + "fileLocation": [ + "relative", + "${workspaceFolder}" + ] + }, + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "label": "build_unit_test", + "type":"shell", + "command": "make build_unit_test -j8", + "problemMatcher": { + "base": "$gcc", + "owner": "gcc", + "fileLocation": [ + "relative", + "${workspaceFolder}" + ] + }, + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "label": "exec_unit_test", + "type":"shell", + "command": "make exec_unit_test -j1", + "problemMatcher": { + "base": "$gcc", + "owner": "gcc", + "fileLocation": [ + "relative", + "${workspaceFolder}" + ] + }, + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "label": "coverage", + "type":"shell", + "command": "make coverage -j1", + "problemMatcher": { + "base": "$gcc", + "owner": "gcc", + "fileLocation": [ + "relative", + "${workspaceFolder}" + ] + }, + "group": { + "kind": "build", + "isDefault": true + } + } + ], + "presentation": { + "focus": true, + "reveal": "always", + "panel": "shared", + "clear": true, + } +} diff --git a/inc/ads1115.h b/inc/ads1115.h new file mode 100644 index 0000000..1c89d60 --- /dev/null +++ b/inc/ads1115.h @@ -0,0 +1,23 @@ +#ifndef __ADS1115__ +#define __ADS1115__ + +#include +#include + +struct ads1115_dev { + struct i2c_bb *i2c_dev; + uint8_t i2c_slave_address; +}; + +struct ads1115_conversation_result { + uint16_t raw; + float voltage; +}; + +int ads1115_open(const struct ads1115_dev *ads1115); +int ads1115_close(const struct ads1115_dev *ads1115); +int ads1115_start_conversation(const struct ads1115_dev *ads1115); +int ads1115_read_conversation_result(const struct ads1115_dev *ads1115, + struct ads1115_conversation_result *result); + +#endif diff --git a/inc/i2c_bb.h b/inc/i2c_bb.h deleted file mode 100644 index 2f9753d..0000000 --- a/inc/i2c_bb.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef __I2C_BB_H__ -#define __I2C_BB_H__ - -#include - -struct i2c_bb { - struct gpio *sda; - struct gpio *scl; -}; - -int i2c_open(const struct i2c_bb *i2c); -int i2c_close(const struct i2c_bb *i2c); - -void start_condition(const struct i2c_bb *i2c); -void stop_condition(const struct i2c_bb *i2c); -bool write_byte(const struct i2c_bb *i2c, unsigned char byte); -unsigned char read_byte(const struct i2c_bb *i2c, bool ack); - -#endif diff --git a/src/ads1115.c b/src/ads1115.c new file mode 100644 index 0000000..762be90 --- /dev/null +++ b/src/ads1115.c @@ -0,0 +1,100 @@ +#include +#include +#include +#include +#include +#include +#include + +#include + +#define BUF_SIZE 3 +#define VPS 6.144 / 32768.0 + +int ads1115_open(const struct ads1115_dev *ads1115) +{ + int res; + + assert(NULL != ads1115); + + syslog(LOG_DEBUG, "Trying to open i2c_bb.\n"); + res = i2c_open(ads1115->i2c_dev); + if(res != 0) { + syslog(LOG_ERR, "Unable to open i2c_bb.\n"); + return res; + } + syslog(LOG_DEBUG, "i2c dev successfully opened.\n"); + + return 0; +} + +int ads1115_close(const struct ads1115_dev *ads1115) +{ + assert(NULL != ads1115); + + return i2c_close(ads1115->i2c_dev); +} + +int ads1115_start_conversation(const struct ads1115_dev *ads1115) +{ + int res; + char buffer[BUF_SIZE]; + + assert(NULL != ads1115); + + syslog(LOG_DEBUG, "ads1115 start conversation.\n"); + + /* FIXME: prevent hard coded config. */ + buffer[0] = 0b00000001; // config register @ address 1 + buffer[1] = 0b11000001; // config value high byte + buffer[2] = 0b10000111; // config value low byte + + // begin conversation + res = i2c_write(ads1115->i2c_dev, ads1115->i2c_slave_address, buffer, BUF_SIZE); + if(res != BUF_SIZE) { + syslog(LOG_ERR, "Unable to write to ADS1115.\n"); + i2c_close(ads1115->i2c_dev); + return res; + } + syslog(LOG_DEBUG, "ads1115 conversation done.\n"); + + return 0; +} + +int ads1115_read_conversation_result(const struct ads1115_dev *ads1115, + struct ads1115_conversation_result *result) +{ + int res; + char buffer[BUF_SIZE]; + + assert(NULL != ads1115); + assert(NULL != result); + + // wait for conversation complete + do { + res = i2c_read(ads1115->i2c_dev, ads1115->i2c_slave_address, buffer, 2); + if(res != 2) { + syslog(LOG_ERR, "Unable to read from ADS1115.\n"); + return res; + } + } while((buffer[0] & 0x80) == 0); + + // read conversation result + buffer[0] = 0b00000000; /* conversation register at address 0b00000000 */ + res = i2c_write(ads1115->i2c_dev, ads1115->i2c_slave_address, buffer, 1); + if(res != 1) { + syslog(LOG_ERR, "Unable to write to ADS1115.\n"); + return res; + } + + // read 2 bytes + res = i2c_read(ads1115->i2c_dev, ads1115->i2c_slave_address, buffer, 2); + if(res != 2) { + syslog(LOG_ERR, "Unable to read from ADS1115.\n"); + return res; + } + result->raw = buffer[0] << 8 | buffer[1]; + result->voltage = result->raw * VPS; + + return 0; +} diff --git a/src/main.c b/src/main.c index 35ad78d..c0b0570 100644 --- a/src/main.c +++ b/src/main.c @@ -7,10 +7,7 @@ #include #include -#include - -#define ADS1115_ADDR 0x48 -#define VPS 6.144 / 32768.0 +#include static struct gpio_sys gpio_sda = { .pin = 4, @@ -22,79 +19,42 @@ static struct gpio_sys gpio_scl = { .direction = OUT, }; -static struct i2c_bb i2c_obj = { +static struct i2c_bb i2c_dev = { .sda = &gpio_sda, .scl = &gpio_scl, }; +static struct ads1115_dev ads = { + .i2c_dev = &i2c_dev, + .i2c_slave_address = 0x48, +}; + + int main(void) { int res; - uint16_t value; - float f_value; - char w_buffer[3], r_buffer[2]; + struct ads1115_conversation_result result; - openlog("distance_app", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); - printf("Trying to open I2C device.\n"); - - syslog(LOG_DEBUG, "Trying to open i2c_bb.\n"); - res = i2c_open(&i2c_obj); - if(res != EXIT_SUCCESS) { - syslog(LOG_ERR, "Unable to open i2c_bb.\n"); - return EXIT_FAILURE; - } - syslog(LOG_DEBUG, "i2c_bb successfully opened.\n"); - - w_buffer[0] = 0b00000001; // config register @ address 1 - w_buffer[1] = 0b11000001; // config value high byte - w_buffer[2] = 0b10000111; // config value low byte - - // begin conversation - res = i2c_write(&i2c_obj, ADS1115_ADDR, w_buffer, 3); - if(res != 3) { - syslog(LOG_ERR, "Unable to write to ADS1115.\n"); - i2c_close(&i2c_obj); - return EXIT_FAILURE; + res = ads1115_open(&ads); + if(res != 0) { + return res; } - // wait for conversation complete - do { - res = i2c_read(&i2c_obj, ADS1115_ADDR, w_buffer, 2); - if(res != 2) { - syslog(LOG_ERR, "Unable to read from ADS1115.\n"); - i2c_close(&i2c_obj); - return EXIT_FAILURE; - } - } while((w_buffer[0] & 0x80) == 0); - - // read conversation result - r_buffer[0] = 0b00000000; /* conversation register at address 0b00000000 */ - res = i2c_write(&i2c_obj, ADS1115_ADDR, r_buffer, 1); - if(res != 1) { - syslog(LOG_ERR, "Unable to write to ADS1115.\n"); - i2c_close(&i2c_obj); - return EXIT_FAILURE; + res = ads1115_start_conversation(&ads); + if(res != 0) { + ads1115_close(&ads); + return res; } - // read 2 bytes - res = i2c_read(&i2c_obj, ADS1115_ADDR, r_buffer, 2); - if(res != 2) { - syslog(LOG_ERR, "Unable to read from ADS1115.\n"); - i2c_close(&i2c_obj); - return EXIT_FAILURE; + res = ads1115_read_conversation_result(&ads, &result); + if(res != 0) { + ads1115_close(&ads); + return res; } - printf("Conversation done [0x%02x:%02x].\n", r_buffer[0], r_buffer[1]); - i2c_close(&i2c_obj); + ads1115_close(&ads); - value = r_buffer[0] << 8 | r_buffer[1]; - if(value & 0x8000) { - value = 0; - } - f_value = value * VPS; - - printf("Conversation result: %4.3fV (0x%04x).\n", f_value, value); + printf("Conversation: %4.3fV (0x%04x).\n", result.voltage, result.raw); return res; } -