diff --git a/.clang-format b/.clang-format index 1e81119..072b4e4 100644 --- a/.clang-format +++ b/.clang-format @@ -3,6 +3,7 @@ IndentWidth: 4 AlignConsecutiveMacros: Consecutive AlignConsecutiveDeclarations: true AlignConsecutiveAssignments: true +AllowShortFunctionsOnASingleLine: false BreakBeforeBraces: Custom BraceWrapping: AfterEnum: false diff --git a/demos/dht_sensor/CMakeLists.txt b/demos/dht_sensor/CMakeLists.txt index 84bc631..9cb75c3 100644 --- a/demos/dht_sensor/CMakeLists.txt +++ b/demos/dht_sensor/CMakeLists.txt @@ -3,8 +3,14 @@ cmake_minimum_required(VERSION 3.10) project(usbsio_dhtsensor) set(USBSIO_DHT_SRCS + "src/aht10.c" "src/main.c" ) +set(USBSIO_DHT_INCLUDES + "include" +) + add_executable(${PROJECT_NAME} ${USBSIO_DHT_SRCS}) +target_include_directories(${PROJECT_NAME} PRIVATE ${USBSIO_DHT_INCLUDES}) target_link_libraries(${PROJECT_NAME} PRIVATE "usbsio") \ No newline at end of file diff --git a/demos/dht_sensor/include/aht10.h b/demos/dht_sensor/include/aht10.h new file mode 100644 index 0000000..f83ddef --- /dev/null +++ b/demos/dht_sensor/include/aht10.h @@ -0,0 +1,42 @@ +#ifndef AHT10_H +#define AHT10_H + +#include + +#define AHT10_SKIP_BUSY_CHECK + +typedef enum { + AHT10_OK, + AHT10_FAIL, +} aht10_ret_t; + +typedef struct { + uint8_t *tx_data; + uint8_t *rx_data; + uint16_t tx_size; + uint16_t rx_size; +} aht10_xfer_desc_t; + +typedef aht10_ret_t (*aht10_i2c_xfer_t)(void *pdev, aht10_xfer_desc_t *xfer); +typedef aht10_ret_t (*aht10_delay_t)(void *pdev, uint32_t delay_msec); + +typedef struct { + double temperature; + double humidity; +} aht10_result_t; + +typedef struct { + aht10_i2c_xfer_t xfer; + aht10_delay_t delay; +} aht10_cb_t; + +typedef struct { + aht10_cb_t cb; + void *user_data; +} aht10_t; + +aht10_ret_t aht10_init(aht10_t *aht); +aht10_ret_t aht10_measure(aht10_t *aht, aht10_result_t *result); + + +#endif \ No newline at end of file diff --git a/demos/dht_sensor/src/aht10.c b/demos/dht_sensor/src/aht10.c new file mode 100644 index 0000000..828f963 --- /dev/null +++ b/demos/dht_sensor/src/aht10.c @@ -0,0 +1,132 @@ +#include + +/* Private header */ +#include "aht10.h" + +#define AHT10_STATUS_CALIBRATED_MASK (1U << 3U) +#define AHT10_STATUS_BUSY_MASK (1U << 7U) + +#define AHT10_ERROR_CHECK(x) \ + if (x != AHT10_OK) return AHT10_FAIL + +typedef struct { + uint8_t status; + uint32_t temperature; + uint32_t humidity; +} aht10_raw_t; + +static aht10_ret_t aht10_software_reset(aht10_t *aht) { + /* Reset and initialize device */ + + uint8_t tx_data[3] = {0xBA}; + + aht10_xfer_desc_t xfer = { + .tx_data = tx_data, + .tx_size = 1U, + .rx_data = NULL, + .rx_size = 0U, + }; + + AHT10_ERROR_CHECK(aht->cb.xfer(aht->user_data, &xfer)); + + AHT10_ERROR_CHECK(aht->cb.delay(aht->user_data, 20)); + + tx_data[0] = 0xE1; + tx_data[1] = 0x08; + tx_data[2] = 0x00; + + xfer.tx_size = 3U; + + AHT10_ERROR_CHECK(aht->cb.xfer(aht->user_data, &xfer)); +} + +static aht10_ret_t aht10_start_measurement(aht10_t *aht) { + /* Start measurement */ + + uint8_t tx_data[3] = {0xAC, 0x33, 0x00}; + + aht10_xfer_desc_t xfer = { + .tx_data = tx_data, + .tx_size = 3U, + .rx_data = NULL, + .rx_size = 0U, + }; + + AHT10_ERROR_CHECK(aht->cb.xfer(aht->user_data, &xfer)); + + return AHT10_OK; +} + +static aht10_ret_t aht10_read_result(aht10_t *aht, aht10_raw_t *raw) { + /* Read conversion result */ + + uint8_t tx_data[] = {0x71}; + uint8_t rx_data[6]; + + aht10_xfer_desc_t xfer = { + .tx_data = tx_data, + .tx_size = 1U, + .rx_data = rx_data, + .rx_size = 6U, + }; + + AHT10_ERROR_CHECK(aht->cb.xfer(aht->user_data, &xfer)); + + raw->humidity = rx_data[1] << 12U; + raw->humidity |= rx_data[2] << 4U; + raw->humidity |= rx_data[3] >> 4U; + + raw->temperature = (rx_data[3] & 0x0FU) << 16U; + raw->temperature |= rx_data[4] << 8U; + raw->temperature |= rx_data[5]; + + raw->status = rx_data[0]; + + return AHT10_OK; +} + +aht10_ret_t aht10_init(aht10_t *aht) { + /* Check if we need initialization */ + + /* Delay 40ms after POR */ + AHT10_ERROR_CHECK(aht->cb.delay(aht->user_data, 40)); + + aht10_raw_t raw; + + /* Check 0x71 status byte, if uncalibrated then reset and calibrate it. */ + AHT10_ERROR_CHECK(aht10_read_result(aht, &raw)); + if ((raw.status & AHT10_STATUS_CALIBRATED_MASK) == 0) { + AHT10_ERROR_CHECK(aht10_software_reset(aht)); + } + + return AHT10_OK; +} + +aht10_ret_t aht10_measure(aht10_t *aht, aht10_result_t *result) { + /* Start a measurement and read back result... */ + + AHT10_ERROR_CHECK(aht10_start_measurement(aht)); + + AHT10_ERROR_CHECK(aht->cb.delay(aht->user_data, 80)); + + aht10_raw_t raw; + + uint8_t max_retries = 5U; + + do { + AHT10_ERROR_CHECK(aht10_read_result(aht, &raw)); + max_retries--; + if (max_retries == 0) { + return AHT10_FAIL; + } +#ifndef AHT10_SKIP_BUSY_CHECK + } while (raw.status & AHT10_STATUS_BUSY_MASK); +#else + } while (0); +#endif + + result->temperature = ((double)raw.temperature * 200.0 / 1048576.0) - 50.0; + result->humidity = (double)raw.humidity * 100.0 / 1048576.0; + + return AHT10_OK; +} \ No newline at end of file diff --git a/demos/dht_sensor/src/main.c b/demos/dht_sensor/src/main.c index 5393884..4adc4f0 100644 --- a/demos/dht_sensor/src/main.c +++ b/demos/dht_sensor/src/main.c @@ -7,14 +7,17 @@ /* USBSIO header */ #include +/* AHT10 */ +#include "aht10.h" + #define NXP_VID 0x1FC9 #define MCULINK_PID 0x0143 static bool s_running = true; -static int aht10_measure(LPC_HANDLE handle, uint8_t slave_addr, double *temp, double *hum); - -static void signal_handler(int sig); +static aht10_ret_t aht_impl_xfer(void *pdev, aht10_xfer_desc_t *xfer); +static aht10_ret_t aht_impl_delay(void *pdev, uint32_t msec); +static void signal_handler(int sig); int main(int argc, const char *argv) { int ret; @@ -49,98 +52,55 @@ int main(int argc, const char *argv) { i2c_handle = I2C_Open(dev_handle, &i2c_cfg, 0); - double temperature = 0.00; - double humidity = 0.00; + aht10_t aht = { + .user_data = i2c_handle, + .cb = + { + .delay = aht_impl_delay, + .xfer = aht_impl_xfer, + }, + }; + aht10_init(&aht); + + aht10_result_t result; while (s_running) { - int ret = aht10_measure(i2c_handle, 0x38, &temperature, &humidity); - if(ret < 0) { + if (aht10_measure(&aht, &result) != AHT10_OK) { fprintf(stderr, "Sensor communication error.\n"); - } - else { - fprintf(stdout, "Temperature: %.2fC, humidity: %.2f%%\n", temperature, humidity); + } else { + fprintf(stdout, "Temperature: %.3fC, humidity: %.3f%%\n", result.temperature, result.humidity); } usleep(100 * 1000); } } -static int aht10_measure(LPC_HANDLE handle, uint8_t slave_addr, double *temp, double *hum) { - uint8_t tx_buffer[3] = {0x71, 0x00, 0x00}; - uint8_t rx_buffer[6]; +static aht10_ret_t aht_impl_xfer(void *pdev, aht10_xfer_desc_t *xfer) { + LPC_HANDLE i2c_handle = pdev; - I2C_FAST_XFER_T xfer = { - .slaveAddr = slave_addr, - .txSz = 1U, - .txBuff = tx_buffer, - .rxSz = 1U, - .rxBuff = rx_buffer, + I2C_FAST_XFER_T i2c_xfer = { .options = 0U, + .slaveAddr = 0x38, + .rxBuff = xfer->rx_data, + .rxSz = xfer->rx_size, + .txBuff = xfer->tx_data, + .txSz = xfer->tx_size, }; - usleep(40 * 1000); - - int ret = I2C_FastXfer(handle, &xfer); + int ret = I2C_FastXfer(i2c_handle, &i2c_xfer); if (ret < 0) { - I2C_Reset(handle); - return ret; + return AHT10_FAIL; } - if ((rx_buffer[0] & 0x08) == 0U) { - /* BIT3 indicates AHT10 not calibrated, send initialization command */ - tx_buffer[0] = 0xE1; - tx_buffer[1] = 0x08; - tx_buffer[2] = 0x00; - - xfer.txSz = 0x03; - xfer.rxSz = 0x00; - - ret = I2C_FastXfer(handle, &xfer); - if (ret < 0) { - I2C_Reset(handle); - return ret; - } - - usleep(40 * 1000); - } - - tx_buffer[0] = 0xAC; - tx_buffer[1] = 0x33; - tx_buffer[2] = 0x00; - - xfer.txSz = 0x03; - xfer.rxSz = 0x00; - - ret = I2C_FastXfer(handle, &xfer); - if (ret < 0) { - I2C_Reset(handle); - return ret; - } - - usleep(80 * 1000); - - tx_buffer[0] = 0x71; - xfer.txSz = 0x01; - xfer.rxSz = 0x06; - - ret = I2C_FastXfer(handle, &xfer); - if (ret < 0) { - I2C_Reset(handle); - return ret; - } - - uint32_t humid_raw = rx_buffer[1] << 12U; - humid_raw |= rx_buffer[2] << 4U; - humid_raw |= rx_buffer[3] >> 4U; - - uint32_t temp_raw = (rx_buffer[3] & 0x0FU) << 16U; - temp_raw |= rx_buffer[4] << 8U; - temp_raw |= rx_buffer[5]; - - *hum = (double)humid_raw * 100.0 / 1048576.0; - *temp = ((double)temp_raw * 200.0 / 1048576.0) - 50.0; - - return ret; + return AHT10_OK; } -static void signal_handler(int sig) { s_running = false; } \ No newline at end of file +static aht10_ret_t aht_impl_delay(void *pdev, uint32_t msec) { + usleep(msec * 1000); + + return AHT10_OK; +} + +static void signal_handler(int sig) { + s_running = false; +} \ No newline at end of file