From 54169f41503bfd27d85e28d58b30f5271131aa09 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Wed, 27 Jan 2021 11:14:25 +0000 Subject: [PATCH 1/4] Add BH1745 driver --- drivers/CMakeLists.txt | 1 + drivers/bh1745/CMakeLists.txt | 1 + drivers/bh1745/bh1745.cmake | 9 ++ drivers/bh1745/bh1745.cpp | 172 ++++++++++++++++++++++++ drivers/bh1745/bh1745.hpp | 71 ++++++++++ examples/CMakeLists.txt | 1 + examples/breakout_bh1745/CMakeLists.txt | 10 ++ examples/breakout_bh1745/demo.cpp | 36 +++++ 8 files changed, 301 insertions(+) create mode 100644 drivers/bh1745/CMakeLists.txt create mode 100644 drivers/bh1745/bh1745.cmake create mode 100644 drivers/bh1745/bh1745.cpp create mode 100644 drivers/bh1745/bh1745.hpp create mode 100644 examples/breakout_bh1745/CMakeLists.txt create mode 100644 examples/breakout_bh1745/demo.cpp diff --git a/drivers/CMakeLists.txt b/drivers/CMakeLists.txt index 8ca192f5..617c999f 100644 --- a/drivers/CMakeLists.txt +++ b/drivers/CMakeLists.txt @@ -13,5 +13,6 @@ add_subdirectory(is31fl3731) add_subdirectory(fatfs) add_subdirectory(sdcard) add_subdirectory(as7262) +add_subdirectory(bh1745) add_subdirectory(button) add_subdirectory(rgbled) diff --git a/drivers/bh1745/CMakeLists.txt b/drivers/bh1745/CMakeLists.txt new file mode 100644 index 00000000..b6420b9f --- /dev/null +++ b/drivers/bh1745/CMakeLists.txt @@ -0,0 +1 @@ +include(bh1745.cmake) \ No newline at end of file diff --git a/drivers/bh1745/bh1745.cmake b/drivers/bh1745/bh1745.cmake new file mode 100644 index 00000000..6d286cd3 --- /dev/null +++ b/drivers/bh1745/bh1745.cmake @@ -0,0 +1,9 @@ +add_library(bh1745 INTERFACE) + +target_sources(bh1745 INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/bh1745.cpp) + +target_include_directories(bh1745 INTERFACE ${CMAKE_CURRENT_LIST_DIR}) + +# Pull in pico libraries that we need +target_link_libraries(bh1745 INTERFACE pico_stdlib hardware_i2c) diff --git a/drivers/bh1745/bh1745.cpp b/drivers/bh1745/bh1745.cpp new file mode 100644 index 00000000..f40d4c7c --- /dev/null +++ b/drivers/bh1745/bh1745.cpp @@ -0,0 +1,172 @@ +#include "bh1745.hpp" +#include + +namespace pimoroni { + int BH1745::init() { + i2c_init(i2c, 400000); + + gpio_set_function(sda, GPIO_FUNC_I2C); gpio_pull_up(sda); + gpio_set_function(scl, GPIO_FUNC_I2C); gpio_pull_up(scl); + + reset(); + + if (this->get_chip_id() != CHIP_ID || this->get_manufacturer() != MANUFACTURER) { + return 1; + } + + this->reset(); + this->clear_bits(REG_SYSTEM_CONTROL, 6); // Clear INT reset bit + this->set_measurement_time_ms(640); + this->set_bits(REG_MODE_CONTROL2, 4); // Enable RGBC + this->set_bits(REG_MODE_CONTROL3, 0, 0xff); // Turn on sensor + this->set_threshold_high(0x0000); // Set threshold so int will always fire + this->set_threshold_low(0xFFFF); // this lets us turn on the LEDs with the int pin + this->clear_bits(REG_INTERRUPT, 4); // Enable interrupt latch + + sleep_ms(320); + + return 0; + } + + uint8_t BH1745::get_chip_id() { + uint8_t chip_id; + this->read_bytes(REG_SYSTEM_CONTROL, &chip_id, 1); + return chip_id & 0b00111111; + } + + uint8_t BH1745::get_manufacturer() { + uint8_t manufacturer; + this->read_bytes(REG_MANUFACTURER, &manufacturer, 1); + return manufacturer; + } + + void BH1745::reset() { + this->set_bits(REG_SYSTEM_CONTROL, 7); + + while (this->get_bits(REG_SYSTEM_CONTROL, 7)) { + sleep_ms(100); + } + } + + void BH1745::set_measurement_time_ms(uint16_t value) { + uint8_t reg = 0; + switch(value) { + case 160: + reg = 0b000; + break; + case 320: + reg = 0b001; + break; + case 640: + reg = 0b010; + break; + case 1280: + reg = 0b011; + break; + case 2560: + reg = 0b100; + break; + case 5120: + reg = 0b101; + break; + } + this->write_bytes(REG_MODE_CONTROL1, ®, 1); + } + + void BH1745::set_threshold_high(uint16_t value) { + this->write_bytes(REG_THRESHOLD_HIGH, (uint8_t *)&value, 2); + } + + void BH1745::set_threshold_low(uint16_t value) { + this->write_bytes(REG_THRESHOLD_LOW, (uint8_t *)&value, 2); + } + + void BH1745::set_leds(bool state) { + if(state){ + this->set_bits(REG_INTERRUPT, 0); + } + else + { + this->clear_bits(REG_INTERRUPT, 0); + } + + } + + rgbc_t BH1745::get_rgb_scaled() { + rgbc_t rgbc = this->get_rgbc_raw(); + + if(rgbc.c > 0) { + rgbc.r = (uint16_t)((uint32_t)rgbc.r * 255 / rgbc.c) & 0xff; + rgbc.g = (uint16_t)((uint32_t)rgbc.g * 255 / rgbc.c) & 0xff; + rgbc.b = (uint16_t)((uint32_t)rgbc.b * 255 / rgbc.c) & 0xff; + } else { + rgbc.r = 0; + rgbc.g = 0; + rgbc.b = 0; + } + + return rgbc; + } + + rgbc_t BH1745::get_rgb_clamped() { + rgbc_t rgbc = this->get_rgbc_raw(); + + uint16_t vmax = std::max(rgbc.r, std::max(rgbc.g, rgbc.b)); + + rgbc.r = (uint16_t)((uint32_t)rgbc.r * 255 / vmax); + rgbc.g = (uint16_t)((uint32_t)rgbc.g * 255 / vmax); + rgbc.b = (uint16_t)((uint32_t)rgbc.b * 255 / vmax); + + return rgbc; + } + + rgbc_t BH1745::get_rgbc_raw() { + while(this->get_bits(REG_MODE_CONTROL2, 7) == 0) { + sleep_ms(1); + } + rgbc_t colour_data; + this->read_bytes(REG_COLOUR_DATA, (uint8_t *)&colour_data, 8); + colour_data.r *= this->channel_compensation[0]; + colour_data.g *= this->channel_compensation[1]; + colour_data.b *= this->channel_compensation[2]; + colour_data.c *= this->channel_compensation[3]; + return colour_data; + } + + // i2c functions + + int BH1745::write_bytes(uint8_t reg, uint8_t *buf, int len) { + uint8_t buffer[len + 1]; + buffer[0] = reg; + for(int x = 0; x < len; x++) { + buffer[x + 1] = buf[x]; + } + return i2c_write_blocking(this->i2c, this->address, buffer, len + 1, false); + }; + + int BH1745::read_bytes(uint8_t reg, uint8_t *buf, int len) { + i2c_write_blocking(this->i2c, this->address, ®, 1, true); + i2c_read_blocking(this->i2c, this->address, buf, len, false); + return len; + }; + + uint8_t BH1745::get_bits(uint8_t reg, uint8_t shift, uint8_t mask) { + uint8_t value; + this->read_bytes(reg, &value, 1); + return value & (mask << shift); + } + + void BH1745::set_bits(uint8_t reg, uint8_t shift, uint8_t mask) { + uint8_t value; + this->read_bytes(reg, &value, 1); + value |= mask << shift; + this->write_bytes(reg, &value, 1); + } + + void BH1745::clear_bits(uint8_t reg, uint8_t shift, uint8_t mask) { + uint8_t value; + this->read_bytes(reg, &value, 1); + value &= ~(mask << shift); + this->write_bytes(reg, &value, 1); + } +} \ No newline at end of file diff --git a/drivers/bh1745/bh1745.hpp b/drivers/bh1745/bh1745.hpp new file mode 100644 index 00000000..bf0a4843 --- /dev/null +++ b/drivers/bh1745/bh1745.hpp @@ -0,0 +1,71 @@ +#pragma once + +#include "hardware/i2c.h" +#include "hardware/gpio.h" + +#define REG_SYSTEM_CONTROL 0x40 +#define REG_MODE_CONTROL1 0x41 +#define REG_MODE_CONTROL2 0x42 +#define REG_MODE_CONTROL3 0x44 +#define REG_COLOUR_DATA 0x50 +#define REG_DINT_DATA 0x58 +#define REG_INTERRUPT 0x60 +#define REG_PERSISTENCE 0x61 +#define REG_THRESHOLD_LOW 0x64 +#define REG_THRESHOLD_HIGH 0x62 +#define REG_MANUFACTURER 0x92 + +#define CHIP_ID 0b001011 +#define MANUFACTURER 0xe0 + +#define I2C_ADDR 0x38 +#define I2C_ADDR_ALT 0x39 + +namespace pimoroni { + typedef struct { + uint16_t r; + uint16_t g; + uint16_t b; + uint16_t c; + } rgbc_t; + + class BH1745 { + public: + BH1745() {}; + + BH1745(uint8_t addr) : address(addr) {}; + + BH1745(i2c_inst_t *i2c, uint8_t addr, uint8_t sda, uint8_t scl, uint8_t interrupt) : + i2c(i2c), address(addr), sda(sda), scl(scl), interrupt(interrupt) {}; + + int init(); + uint8_t get_chip_id(); + uint8_t get_manufacturer(); + void set_threshold_high(uint16_t value); + void set_threshold_low(uint16_t value); + void set_measurement_time_ms(uint16_t value); + rgbc_t get_rgbc_raw(); + rgbc_t get_rgb_clamped(); + rgbc_t get_rgb_scaled(); + void reset(); + void set_leds(bool state=true); + + private: + i2c_inst_t *i2c = i2c0; + + // interface pins with our standard defaults where appropriate + int8_t address = 0x38; + int8_t sda = 4; + int8_t scl = 5; + int8_t interrupt = 22; + + float channel_compensation[4] = {2.2f, 1.0f, 1.8f, 10.0f}; + + // From i2cdevice + int write_bytes(uint8_t reg, uint8_t *buf, int len); + int read_bytes(uint8_t reg, uint8_t *buf, int len); + uint8_t get_bits(uint8_t reg, uint8_t shift, uint8_t mask=0b1); + void set_bits(uint8_t reg, uint8_t shift, uint8_t mask=0b1); + void clear_bits(uint8_t reg, uint8_t shift, uint8_t mask=0b1); + }; +} \ No newline at end of file diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 156f45d0..cc18a6aa 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -28,3 +28,4 @@ add_subdirectory(pico_trackball_display) add_subdirectory(pico_audio) add_subdirectory(pico_wireless) add_subdirectory(breakout_as7262) +add_subdirectory(breakout_bh1745) diff --git a/examples/breakout_bh1745/CMakeLists.txt b/examples/breakout_bh1745/CMakeLists.txt new file mode 100644 index 00000000..08b18200 --- /dev/null +++ b/examples/breakout_bh1745/CMakeLists.txt @@ -0,0 +1,10 @@ +add_executable( + breakout_bh1745 + demo.cpp +) + +# Pull in pico libraries that we need +target_link_libraries(breakout_bh1745 pico_stdlib hardware_spi bh1745) + +# create map/bin/hex file etc. +pico_add_extra_outputs(breakout_bh1745) \ No newline at end of file diff --git a/examples/breakout_bh1745/demo.cpp b/examples/breakout_bh1745/demo.cpp new file mode 100644 index 00000000..244f58b4 --- /dev/null +++ b/examples/breakout_bh1745/demo.cpp @@ -0,0 +1,36 @@ +#include +#include +#include +#include "pico/stdlib.h" + +#include "bh1745.hpp" + +using namespace pimoroni; + +BH1745 bh1745(0x39); + +int main() { + setup_default_uart(); + + if (bh1745.init() == 1) { + printf("Failed to set up sensor\n"); + return 1; + } + + uint8_t chip_id = bh1745.get_chip_id(); + printf("Found BH1745. Chip ID: 0x%02x\n", chip_id); + + bh1745.set_leds(true); + + while(true) { + rgbc_t colour = bh1745.get_rgbc_raw(); + printf("Colour: %d %d %d %d\n", colour.r, colour.g, colour.b, colour.c); + colour = bh1745.get_rgb_clamped(); + printf("Clamped: %d %d %d %d\n", colour.r, colour.g, colour.b, colour.c); + colour = bh1745.get_rgb_scaled(); + printf("Scaled: %d %d %d %d\n\n", colour.r, colour.g, colour.b, colour.c); + sleep_ms(1000); + } + + return 0; +} \ No newline at end of file From ea6acf2207cc02d71ab7cd7739449e275c56b548 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Mon, 12 Jul 2021 13:21:14 +0100 Subject: [PATCH 2/4] Porti BH1745 to Pimoroni I2C --- drivers/bh1745/bh1745.cmake | 2 +- drivers/bh1745/bh1745.cpp | 98 +++++++++---------------------- drivers/bh1745/bh1745.hpp | 58 ++++++++---------- examples/breakout_bh1745/demo.cpp | 5 +- 4 files changed, 59 insertions(+), 104 deletions(-) diff --git a/drivers/bh1745/bh1745.cmake b/drivers/bh1745/bh1745.cmake index 6d286cd3..15e02c7c 100644 --- a/drivers/bh1745/bh1745.cmake +++ b/drivers/bh1745/bh1745.cmake @@ -6,4 +6,4 @@ target_sources(bh1745 INTERFACE target_include_directories(bh1745 INTERFACE ${CMAKE_CURRENT_LIST_DIR}) # Pull in pico libraries that we need -target_link_libraries(bh1745 INTERFACE pico_stdlib hardware_i2c) +target_link_libraries(bh1745 INTERFACE pico_stdlib hardware_i2c pimoroni_i2c) diff --git a/drivers/bh1745/bh1745.cpp b/drivers/bh1745/bh1745.cpp index f40d4c7c..1600def7 100644 --- a/drivers/bh1745/bh1745.cpp +++ b/drivers/bh1745/bh1745.cpp @@ -3,47 +3,44 @@ namespace pimoroni { int BH1745::init() { - i2c_init(i2c, 400000); - - gpio_set_function(sda, GPIO_FUNC_I2C); gpio_pull_up(sda); - gpio_set_function(scl, GPIO_FUNC_I2C); gpio_pull_up(scl); - reset(); - if (this->get_chip_id() != CHIP_ID || this->get_manufacturer() != MANUFACTURER) { + if (this->get_chip_id() != BH1745_CHIP_ID || this->get_manufacturer() != BH1745_MANUFACTURER) { return 1; } - this->reset(); - this->clear_bits(REG_SYSTEM_CONTROL, 6); // Clear INT reset bit - this->set_measurement_time_ms(640); - this->set_bits(REG_MODE_CONTROL2, 4); // Enable RGBC - this->set_bits(REG_MODE_CONTROL3, 0, 0xff); // Turn on sensor - this->set_threshold_high(0x0000); // Set threshold so int will always fire - this->set_threshold_low(0xFFFF); // this lets us turn on the LEDs with the int pin - this->clear_bits(REG_INTERRUPT, 4); // Enable interrupt latch + reset(); + i2c->clear_bits(address, BH1745_REG_SYSTEM_CONTROL, 6); // Clear INT reset bit + set_measurement_time_ms(640); + i2c->set_bits(address, BH1745_REG_MODE_CONTROL2, 4); // Enable RGBC + i2c->set_bits(address, BH1745_REG_MODE_CONTROL3, 0, 0xff); // Turn on sensor + set_threshold_high(0x0000); // Set threshold so int will always fire + set_threshold_low(0xFFFF); // this lets us turn on the LEDs with the int pin + i2c->clear_bits(address, BH1745_REG_INTERRUPT, 4); // Enable interrupt latch sleep_ms(320); return 0; } + i2c_inst_t* BH1745::get_i2c() const { + return i2c->get_i2c(); + } + uint8_t BH1745::get_chip_id() { - uint8_t chip_id; - this->read_bytes(REG_SYSTEM_CONTROL, &chip_id, 1); + uint8_t chip_id = i2c->reg_read_uint8(address, BH1745_REG_SYSTEM_CONTROL); return chip_id & 0b00111111; } uint8_t BH1745::get_manufacturer() { - uint8_t manufacturer; - this->read_bytes(REG_MANUFACTURER, &manufacturer, 1); + uint8_t manufacturer = i2c->reg_read_uint8(address, BH1745_REG_MANUFACTURER); return manufacturer; } void BH1745::reset() { - this->set_bits(REG_SYSTEM_CONTROL, 7); + i2c->set_bits(address, BH1745_REG_SYSTEM_CONTROL, 7); - while (this->get_bits(REG_SYSTEM_CONTROL, 7)) { + while (i2c->get_bits(address, BH1745_REG_SYSTEM_CONTROL, 7)) { sleep_ms(100); } } @@ -70,24 +67,24 @@ namespace pimoroni { reg = 0b101; break; } - this->write_bytes(REG_MODE_CONTROL1, ®, 1); + i2c->write_bytes(address, BH1745_REG_MODE_CONTROL1, ®, 1); } void BH1745::set_threshold_high(uint16_t value) { - this->write_bytes(REG_THRESHOLD_HIGH, (uint8_t *)&value, 2); + i2c->write_bytes(address, BH1745_REG_THRESHOLD_HIGH, (uint8_t *)&value, 2); } void BH1745::set_threshold_low(uint16_t value) { - this->write_bytes(REG_THRESHOLD_LOW, (uint8_t *)&value, 2); + i2c->write_bytes(address, BH1745_REG_THRESHOLD_LOW, (uint8_t *)&value, 2); } void BH1745::set_leds(bool state) { if(state){ - this->set_bits(REG_INTERRUPT, 0); + i2c->set_bits(address, BH1745_REG_INTERRUPT, 0); } else { - this->clear_bits(REG_INTERRUPT, 0); + i2c->clear_bits(address, BH1745_REG_INTERRUPT, 0); } } @@ -109,7 +106,7 @@ namespace pimoroni { } rgbc_t BH1745::get_rgb_clamped() { - rgbc_t rgbc = this->get_rgbc_raw(); + rgbc_t rgbc = get_rgbc_raw(); uint16_t vmax = std::max(rgbc.r, std::max(rgbc.g, rgbc.b)); @@ -121,52 +118,15 @@ namespace pimoroni { } rgbc_t BH1745::get_rgbc_raw() { - while(this->get_bits(REG_MODE_CONTROL2, 7) == 0) { + while(i2c->get_bits(address, BH1745_REG_MODE_CONTROL2, 7) == 0) { sleep_ms(1); } rgbc_t colour_data; - this->read_bytes(REG_COLOUR_DATA, (uint8_t *)&colour_data, 8); - colour_data.r *= this->channel_compensation[0]; - colour_data.g *= this->channel_compensation[1]; - colour_data.b *= this->channel_compensation[2]; - colour_data.c *= this->channel_compensation[3]; + i2c->read_bytes(address, BH1745_REG_COLOUR_DATA, (uint8_t *)&colour_data, 8); + colour_data.r *= channel_compensation[0]; + colour_data.g *= channel_compensation[1]; + colour_data.b *= channel_compensation[2]; + colour_data.c *= channel_compensation[3]; return colour_data; } - - // i2c functions - - int BH1745::write_bytes(uint8_t reg, uint8_t *buf, int len) { - uint8_t buffer[len + 1]; - buffer[0] = reg; - for(int x = 0; x < len; x++) { - buffer[x + 1] = buf[x]; - } - return i2c_write_blocking(this->i2c, this->address, buffer, len + 1, false); - }; - - int BH1745::read_bytes(uint8_t reg, uint8_t *buf, int len) { - i2c_write_blocking(this->i2c, this->address, ®, 1, true); - i2c_read_blocking(this->i2c, this->address, buf, len, false); - return len; - }; - - uint8_t BH1745::get_bits(uint8_t reg, uint8_t shift, uint8_t mask) { - uint8_t value; - this->read_bytes(reg, &value, 1); - return value & (mask << shift); - } - - void BH1745::set_bits(uint8_t reg, uint8_t shift, uint8_t mask) { - uint8_t value; - this->read_bytes(reg, &value, 1); - value |= mask << shift; - this->write_bytes(reg, &value, 1); - } - - void BH1745::clear_bits(uint8_t reg, uint8_t shift, uint8_t mask) { - uint8_t value; - this->read_bytes(reg, &value, 1); - value &= ~(mask << shift); - this->write_bytes(reg, &value, 1); - } } \ No newline at end of file diff --git a/drivers/bh1745/bh1745.hpp b/drivers/bh1745/bh1745.hpp index bf0a4843..3da7e792 100644 --- a/drivers/bh1745/bh1745.hpp +++ b/drivers/bh1745/bh1745.hpp @@ -2,24 +2,22 @@ #include "hardware/i2c.h" #include "hardware/gpio.h" +#include "common/pimoroni_i2c.hpp" -#define REG_SYSTEM_CONTROL 0x40 -#define REG_MODE_CONTROL1 0x41 -#define REG_MODE_CONTROL2 0x42 -#define REG_MODE_CONTROL3 0x44 -#define REG_COLOUR_DATA 0x50 -#define REG_DINT_DATA 0x58 -#define REG_INTERRUPT 0x60 -#define REG_PERSISTENCE 0x61 -#define REG_THRESHOLD_LOW 0x64 -#define REG_THRESHOLD_HIGH 0x62 -#define REG_MANUFACTURER 0x92 +#define BH1745_REG_SYSTEM_CONTROL 0x40 +#define BH1745_REG_MODE_CONTROL1 0x41 +#define BH1745_REG_MODE_CONTROL2 0x42 +#define BH1745_REG_MODE_CONTROL3 0x44 +#define BH1745_REG_COLOUR_DATA 0x50 +#define BH1745_REG_DINT_DATA 0x58 +#define BH1745_REG_INTERRUPT 0x60 +#define BH1745_REG_PERSISTENCE 0x61 +#define BH1745_REG_THRESHOLD_LOW 0x64 +#define BH1745_REG_THRESHOLD_HIGH 0x62 +#define BH1745_REG_MANUFACTURER 0x92 -#define CHIP_ID 0b001011 -#define MANUFACTURER 0xe0 - -#define I2C_ADDR 0x38 -#define I2C_ADDR_ALT 0x39 +#define BH1745_CHIP_ID 0b001011 +#define BH1745_MANUFACTURER 0xe0 namespace pimoroni { typedef struct { @@ -31,14 +29,19 @@ namespace pimoroni { class BH1745 { public: - BH1745() {}; + static const uint8_t DEFAULT_I2C_ADDRESS = 0x38; + static const uint8_t I2C_ADDRESS_ALTERNATE = 0x39; - BH1745(uint8_t addr) : address(addr) {}; + BH1745(I2C *i2c, uint8_t address = DEFAULT_I2C_ADDRESS) : + i2c(i2c), address(address) {} - BH1745(i2c_inst_t *i2c, uint8_t addr, uint8_t sda, uint8_t scl, uint8_t interrupt) : - i2c(i2c), address(addr), sda(sda), scl(scl), interrupt(interrupt) {}; + BH1745(i2c_inst_t *i2c, uint8_t addr, uint8_t sda, uint8_t scl, uint interrupt) : + BH1745(new I2C(sda, scl), address) {}; int init(); + + i2c_inst_t* get_i2c() const; + uint8_t get_chip_id(); uint8_t get_manufacturer(); void set_threshold_high(uint16_t value); @@ -51,21 +54,12 @@ namespace pimoroni { void set_leds(bool state=true); private: - i2c_inst_t *i2c = i2c0; + I2C *i2c; // interface pins with our standard defaults where appropriate - int8_t address = 0x38; - int8_t sda = 4; - int8_t scl = 5; - int8_t interrupt = 22; + int8_t address = DEFAULT_I2C_ADDRESS; + uint interrupt = 22; float channel_compensation[4] = {2.2f, 1.0f, 1.8f, 10.0f}; - - // From i2cdevice - int write_bytes(uint8_t reg, uint8_t *buf, int len); - int read_bytes(uint8_t reg, uint8_t *buf, int len); - uint8_t get_bits(uint8_t reg, uint8_t shift, uint8_t mask=0b1); - void set_bits(uint8_t reg, uint8_t shift, uint8_t mask=0b1); - void clear_bits(uint8_t reg, uint8_t shift, uint8_t mask=0b1); }; } \ No newline at end of file diff --git a/examples/breakout_bh1745/demo.cpp b/examples/breakout_bh1745/demo.cpp index 244f58b4..fbdbfcee 100644 --- a/examples/breakout_bh1745/demo.cpp +++ b/examples/breakout_bh1745/demo.cpp @@ -7,10 +7,11 @@ using namespace pimoroni; -BH1745 bh1745(0x39); +I2C i2c(BOARD::BREAKOUT_GARDEN); +BH1745 bh1745(&i2c, BH1745::DEFAULT_I2C_ADDRESS); int main() { - setup_default_uart(); + stdio_init_all(); if (bh1745.init() == 1) { printf("Failed to set up sensor\n"); From b80b714c4fc48558652f332f0ee2e7d03d566f37 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Mon, 12 Jul 2021 15:26:41 +0100 Subject: [PATCH 3/4] BH1745 MicroPython bindings & example --- drivers/bh1745/bh1745.cpp | 14 +- drivers/bh1745/bh1745.hpp | 5 +- examples/breakout_bh1745/CMakeLists.txt | 6 +- examples/breakout_bh1745/demo.cpp | 2 +- libraries/CMakeLists.txt | 1 + libraries/breakout_bh1745/CMakeLists.txt | 1 + .../breakout_bh1745/breakout_bh1745.cmake | 11 + libraries/breakout_bh1745/breakout_bh1745.cpp | 5 + libraries/breakout_bh1745/breakout_bh1745.hpp | 8 + .../examples/breakout_bh1745/bh1745_demo.py | 21 ++ .../modules/breakout_bh1745/breakout_bh1745.c | 60 +++++ .../breakout_bh1745/breakout_bh1745.cpp | 208 ++++++++++++++++++ .../modules/breakout_bh1745/breakout_bh1745.h | 26 +++ .../modules/breakout_bh1745/micropython.cmake | 20 ++ micropython/modules/micropython.cmake | 1 + 15 files changed, 378 insertions(+), 11 deletions(-) create mode 100644 libraries/breakout_bh1745/CMakeLists.txt create mode 100644 libraries/breakout_bh1745/breakout_bh1745.cmake create mode 100644 libraries/breakout_bh1745/breakout_bh1745.cpp create mode 100644 libraries/breakout_bh1745/breakout_bh1745.hpp create mode 100644 micropython/examples/breakout_bh1745/bh1745_demo.py create mode 100644 micropython/modules/breakout_bh1745/breakout_bh1745.c create mode 100644 micropython/modules/breakout_bh1745/breakout_bh1745.cpp create mode 100644 micropython/modules/breakout_bh1745/breakout_bh1745.h create mode 100644 micropython/modules/breakout_bh1745/micropython.cmake diff --git a/drivers/bh1745/bh1745.cpp b/drivers/bh1745/bh1745.cpp index 1600def7..0960e800 100644 --- a/drivers/bh1745/bh1745.cpp +++ b/drivers/bh1745/bh1745.cpp @@ -2,11 +2,11 @@ #include namespace pimoroni { - int BH1745::init() { + bool BH1745::init() { reset(); if (this->get_chip_id() != BH1745_CHIP_ID || this->get_manufacturer() != BH1745_MANUFACTURER) { - return 1; + return false; } reset(); @@ -20,11 +20,15 @@ namespace pimoroni { sleep_ms(320); - return 0; + return true; } - i2c_inst_t* BH1745::get_i2c() const { - return i2c->get_i2c(); + I2C* BH1745::get_i2c() const { + return i2c; + } + + int BH1745::get_address() const { + return address; } uint8_t BH1745::get_chip_id() { diff --git a/drivers/bh1745/bh1745.hpp b/drivers/bh1745/bh1745.hpp index 3da7e792..257de041 100644 --- a/drivers/bh1745/bh1745.hpp +++ b/drivers/bh1745/bh1745.hpp @@ -38,9 +38,10 @@ namespace pimoroni { BH1745(i2c_inst_t *i2c, uint8_t addr, uint8_t sda, uint8_t scl, uint interrupt) : BH1745(new I2C(sda, scl), address) {}; - int init(); + bool init(); - i2c_inst_t* get_i2c() const; + I2C* get_i2c() const; + int get_address() const; uint8_t get_chip_id(); uint8_t get_manufacturer(); diff --git a/examples/breakout_bh1745/CMakeLists.txt b/examples/breakout_bh1745/CMakeLists.txt index 08b18200..b76714b6 100644 --- a/examples/breakout_bh1745/CMakeLists.txt +++ b/examples/breakout_bh1745/CMakeLists.txt @@ -1,10 +1,10 @@ add_executable( - breakout_bh1745 + breakout_bh1745_demo demo.cpp ) # Pull in pico libraries that we need -target_link_libraries(breakout_bh1745 pico_stdlib hardware_spi bh1745) +target_link_libraries(breakout_bh1745_demo pico_stdlib hardware_spi bh1745) # create map/bin/hex file etc. -pico_add_extra_outputs(breakout_bh1745) \ No newline at end of file +pico_add_extra_outputs(breakout_bh1745_demo) \ No newline at end of file diff --git a/examples/breakout_bh1745/demo.cpp b/examples/breakout_bh1745/demo.cpp index fbdbfcee..8986cdb7 100644 --- a/examples/breakout_bh1745/demo.cpp +++ b/examples/breakout_bh1745/demo.cpp @@ -13,7 +13,7 @@ BH1745 bh1745(&i2c, BH1745::DEFAULT_I2C_ADDRESS); int main() { stdio_init_all(); - if (bh1745.init() == 1) { + if (!bh1745.init()) { printf("Failed to set up sensor\n"); return 1; } diff --git a/libraries/CMakeLists.txt b/libraries/CMakeLists.txt index ae8ffd38..0ff54c42 100644 --- a/libraries/CMakeLists.txt +++ b/libraries/CMakeLists.txt @@ -14,6 +14,7 @@ add_subdirectory(breakout_trackball) add_subdirectory(breakout_sgp30) add_subdirectory(breakout_as7262) add_subdirectory(breakout_msa301) +add_subdirectory(breakout_bh1745) add_subdirectory(pico_graphics) add_subdirectory(pico_display) add_subdirectory(pico_unicorn) diff --git a/libraries/breakout_bh1745/CMakeLists.txt b/libraries/breakout_bh1745/CMakeLists.txt new file mode 100644 index 00000000..40e8a8c4 --- /dev/null +++ b/libraries/breakout_bh1745/CMakeLists.txt @@ -0,0 +1 @@ +include(breakout_bh1745.cmake) diff --git a/libraries/breakout_bh1745/breakout_bh1745.cmake b/libraries/breakout_bh1745/breakout_bh1745.cmake new file mode 100644 index 00000000..de5e7e48 --- /dev/null +++ b/libraries/breakout_bh1745/breakout_bh1745.cmake @@ -0,0 +1,11 @@ +set(LIB_NAME breakout_bh1745) +add_library(${LIB_NAME} INTERFACE) + +target_sources(${LIB_NAME} INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/${LIB_NAME}.cpp +) + +target_include_directories(${LIB_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR}) + +# Pull in pico libraries that we need +target_link_libraries(${LIB_NAME} INTERFACE pico_stdlib bh1745 pimoroni_i2c) diff --git a/libraries/breakout_bh1745/breakout_bh1745.cpp b/libraries/breakout_bh1745/breakout_bh1745.cpp new file mode 100644 index 00000000..e860379f --- /dev/null +++ b/libraries/breakout_bh1745/breakout_bh1745.cpp @@ -0,0 +1,5 @@ +#include "breakout_bh1745.hpp" + +namespace pimoroni { + +} diff --git a/libraries/breakout_bh1745/breakout_bh1745.hpp b/libraries/breakout_bh1745/breakout_bh1745.hpp new file mode 100644 index 00000000..116d9980 --- /dev/null +++ b/libraries/breakout_bh1745/breakout_bh1745.hpp @@ -0,0 +1,8 @@ +#pragma once + +#include "drivers/bh1745/bh1745.hpp" + +namespace pimoroni { + + typedef BH1745 BreakoutBH1745; +} diff --git a/micropython/examples/breakout_bh1745/bh1745_demo.py b/micropython/examples/breakout_bh1745/bh1745_demo.py new file mode 100644 index 00000000..6188872e --- /dev/null +++ b/micropython/examples/breakout_bh1745/bh1745_demo.py @@ -0,0 +1,21 @@ +import time + +import pimoroni_i2c +import breakout_bh1745 + +PINS_BREAKOUT_GARDEN = {"sda": 4, "scl": 5} +PINS_PICO_EXPLORER = {"sda": 20, "scl": 21} + +I2C = pimoroni_i2c.PimoroniI2C(**PINS_BREAKOUT_GARDEN) +bh1745 = breakout_bh1745.BreakoutBH1745(I2C) + +bh1745.leds(True) + +while True: + rgbc_raw = bh1745.rgbc_raw() + rgb_clamped = bh1745.rgbc_clamped() + rgb_scaled = bh1745.rgbc_scaled() + print("Raw: {}, {}, {}, {}".format(*rgbc_raw)) + print("Clamped: {}, {}, {}, {}".format(*rgb_clamped)) + print("Scaled: #{:02x}{:02x}{:02x}".format(*rgb_scaled)) + time.sleep(5) diff --git a/micropython/modules/breakout_bh1745/breakout_bh1745.c b/micropython/modules/breakout_bh1745/breakout_bh1745.c new file mode 100644 index 00000000..6eef11f5 --- /dev/null +++ b/micropython/modules/breakout_bh1745/breakout_bh1745.c @@ -0,0 +1,60 @@ +#include "breakout_bh1745.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// BreakoutBH1745 Class +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/***** Methods *****/ +MP_DEFINE_CONST_FUN_OBJ_1(BreakoutBH1745_chip_id_obj, BreakoutBH1745_chip_id); +MP_DEFINE_CONST_FUN_OBJ_1(BreakoutBH1745_manufacturer_id_obj, BreakoutBH1745_manufacturer_id); +MP_DEFINE_CONST_FUN_OBJ_1(BreakoutBH1745_rgbc_raw_obj, BreakoutBH1745_rgbc_raw); +MP_DEFINE_CONST_FUN_OBJ_1(BreakoutBH1745_rgbc_clamped_obj, BreakoutBH1745_rgbc_clamped); +MP_DEFINE_CONST_FUN_OBJ_1(BreakoutBH1745_rgbc_scaled_obj, BreakoutBH1745_rgbc_scaled); +MP_DEFINE_CONST_FUN_OBJ_KW(BreakoutBH1745_leds_obj, 2, BreakoutBH1745_leds); +MP_DEFINE_CONST_FUN_OBJ_KW(BreakoutBH1745_threshold_obj, 3, BreakoutBH1745_threshold); +MP_DEFINE_CONST_FUN_OBJ_KW(BreakoutBH1745_measurement_time_ms_obj, 2, BreakoutBH1745_measurement_time_ms); + +/***** Binding of Methods *****/ +STATIC const mp_rom_map_elem_t BreakoutBH1745_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_chip_id), MP_ROM_PTR(&BreakoutBH1745_chip_id_obj) }, + { MP_ROM_QSTR(MP_QSTR_manufacturer_id), MP_ROM_PTR(&BreakoutBH1745_manufacturer_id_obj) }, + { MP_ROM_QSTR(MP_QSTR_rgbc_raw), MP_ROM_PTR(&BreakoutBH1745_rgbc_raw_obj) }, + { MP_ROM_QSTR(MP_QSTR_rgbc_clamped), MP_ROM_PTR(&BreakoutBH1745_rgbc_clamped_obj) }, + { MP_ROM_QSTR(MP_QSTR_rgbc_scaled), MP_ROM_PTR(&BreakoutBH1745_rgbc_scaled_obj) }, + { MP_ROM_QSTR(MP_QSTR_threshold), MP_ROM_PTR(&BreakoutBH1745_threshold_obj) }, + { MP_ROM_QSTR(MP_QSTR_measurement_time_ms), MP_ROM_PTR(&BreakoutBH1745_measurement_time_ms_obj) }, + { MP_ROM_QSTR(MP_QSTR_leds), MP_ROM_PTR(&BreakoutBH1745_leds_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(BreakoutBH1745_locals_dict, BreakoutBH1745_locals_dict_table); + +/***** Class Definition *****/ +const mp_obj_type_t breakout_bh1745_BreakoutBH1745_type = { + { &mp_type_type }, + .name = MP_QSTR_breakout_bh1745, + .print = BreakoutBH1745_print, + .make_new = BreakoutBH1745_make_new, + .locals_dict = (mp_obj_dict_t*)&BreakoutBH1745_locals_dict, +}; + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// breakout_bh1745 Module +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/***** Globals Table *****/ +STATIC const mp_map_elem_t breakout_bh1745_globals_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_breakout_bh1745) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_BreakoutBH1745), (mp_obj_t)&breakout_bh1745_BreakoutBH1745_type }, +}; +STATIC MP_DEFINE_CONST_DICT(mp_module_breakout_bh1745_globals, breakout_bh1745_globals_table); + +/***** Module Definition *****/ +const mp_obj_module_t breakout_bh1745_user_cmodule = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&mp_module_breakout_bh1745_globals, +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +MP_REGISTER_MODULE(MP_QSTR_breakout_bh1745, breakout_bh1745_user_cmodule, MODULE_BREAKOUT_LTR559_ENABLED); +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/micropython/modules/breakout_bh1745/breakout_bh1745.cpp b/micropython/modules/breakout_bh1745/breakout_bh1745.cpp new file mode 100644 index 00000000..de3c60b5 --- /dev/null +++ b/micropython/modules/breakout_bh1745/breakout_bh1745.cpp @@ -0,0 +1,208 @@ +#include "libraries/breakout_bh1745/breakout_bh1745.hpp" +#include + +#define MP_OBJ_TO_PTR2(o, t) ((t *)(uintptr_t)(o)) + +// SDA/SCL on even/odd pins, I2C0/I2C1 on even/odd pairs of pins. +#define IS_VALID_SCL(i2c, pin) (((pin) & 1) == 1 && (((pin) & 2) >> 1) == (i2c)) +#define IS_VALID_SDA(i2c, pin) (((pin) & 1) == 0 && (((pin) & 2) >> 1) == (i2c)) + + +using namespace pimoroni; + +extern "C" { +#include "breakout_bh1745.h" +#include "pimoroni_i2c.h" + +/***** I2C Struct *****/ +typedef struct _PimoroniI2C_obj_t { + mp_obj_base_t base; + I2C *i2c; +} _PimoroniI2C_obj_t; + +/***** Variables Struct *****/ +typedef struct _breakout_bh1745_BreakoutBH1745_obj_t { + mp_obj_base_t base; + BreakoutBH1745 *breakout; +} breakout_bh1745_BreakoutBH1745_obj_t; + +/***** Print *****/ +void BreakoutBH1745_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + (void)kind; //Unused input parameter + breakout_bh1745_BreakoutBH1745_obj_t *self = MP_OBJ_TO_PTR2(self_in, breakout_bh1745_BreakoutBH1745_obj_t); + BreakoutBH1745* breakout = self->breakout; + mp_print_str(print, "BreakoutBH1745("); + + mp_print_str(print, "i2c = "); + mp_obj_print_helper(print, mp_obj_new_int((breakout->get_i2c()->get_i2c() == i2c0) ? 0 : 1), PRINT_REPR); + + mp_print_str(print, ", address = 0x"); + char buf[3]; + sprintf(buf, "%02X", breakout->get_address()); + mp_print_str(print, buf); + + mp_print_str(print, ", sda = "); + mp_obj_print_helper(print, mp_obj_new_int(breakout->get_i2c()->get_sda()), PRINT_REPR); + + mp_print_str(print, ", scl = "); + mp_obj_print_helper(print, mp_obj_new_int(breakout->get_i2c()->get_scl()), PRINT_REPR); + + mp_print_str(print, ")"); +} + +/***** Constructor *****/ +mp_obj_t BreakoutBH1745_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + breakout_bh1745_BreakoutBH1745_obj_t *self = nullptr; + + enum { ARG_i2c, ARG_address }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_i2c, MP_ARG_OBJ, {.u_obj = nullptr} }, + { MP_QSTR_address, MP_ARG_INT, {.u_int = BH1745::DEFAULT_I2C_ADDRESS} }, + }; + + // Parse args. + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + if(!MP_OBJ_IS_TYPE(args[ARG_i2c].u_obj, &PimoroniI2C_type)) { + mp_raise_ValueError(MP_ERROR_TEXT("BreakoutBH1745: Bad i2C object")); + return mp_const_none; + } + + _PimoroniI2C_obj_t *i2c = (_PimoroniI2C_obj_t *)MP_OBJ_TO_PTR(args[ARG_i2c].u_obj); + + self = m_new_obj(breakout_bh1745_BreakoutBH1745_obj_t); + self->base.type = &breakout_bh1745_BreakoutBH1745_type; + + self->breakout = new BreakoutBH1745(i2c->i2c, args[ARG_address].u_int); + + if(!self->breakout->init()) { + mp_raise_msg(&mp_type_RuntimeError, "BreakoutBH1745: breakout not found when initialising"); + } + + return MP_OBJ_FROM_PTR(self); +} + +mp_obj_t BreakoutBH1745_chip_id(mp_obj_t self_in) { + breakout_bh1745_BreakoutBH1745_obj_t *self = MP_OBJ_TO_PTR2(self_in, breakout_bh1745_BreakoutBH1745_obj_t); + return mp_obj_new_int(self->breakout->get_chip_id()); +} + +mp_obj_t BreakoutBH1745_manufacturer_id(mp_obj_t self_in) { + breakout_bh1745_BreakoutBH1745_obj_t *self = MP_OBJ_TO_PTR2(self_in, breakout_bh1745_BreakoutBH1745_obj_t); + return mp_obj_new_int(self->breakout->get_manufacturer()); +} + +mp_obj_t BreakoutBH1745_rgbc_raw(mp_obj_t self_in) { + breakout_bh1745_BreakoutBH1745_obj_t *self = MP_OBJ_TO_PTR2(self_in, breakout_bh1745_BreakoutBH1745_obj_t); + + const rgbc_t reading = self->breakout->get_rgbc_raw(); + + mp_obj_t tuple[4]; + tuple[RGBC_R] = mp_obj_new_int(reading.r); + tuple[RGBC_G] = mp_obj_new_int(reading.g); + tuple[RGBC_B] = mp_obj_new_int(reading.b); + tuple[RGBC_C] = mp_obj_new_int(reading.c); + + return mp_obj_new_tuple(4, tuple); +} + +mp_obj_t BreakoutBH1745_rgbc_clamped(mp_obj_t self_in) { + breakout_bh1745_BreakoutBH1745_obj_t *self = MP_OBJ_TO_PTR2(self_in, breakout_bh1745_BreakoutBH1745_obj_t); + + const rgbc_t reading = self->breakout->get_rgb_clamped(); + + mp_obj_t tuple[4]; + tuple[RGBC_R] = mp_obj_new_int(reading.r); + tuple[RGBC_G] = mp_obj_new_int(reading.g); + tuple[RGBC_B] = mp_obj_new_int(reading.b); + tuple[RGBC_C] = mp_obj_new_int(reading.c); + + return mp_obj_new_tuple(4, tuple); +} + +mp_obj_t BreakoutBH1745_rgbc_scaled(mp_obj_t self_in) { + breakout_bh1745_BreakoutBH1745_obj_t *self = MP_OBJ_TO_PTR2(self_in, breakout_bh1745_BreakoutBH1745_obj_t); + + const rgbc_t reading = self->breakout->get_rgb_scaled(); + + mp_obj_t tuple[4]; + tuple[RGBC_R] = mp_obj_new_int(reading.r); + tuple[RGBC_G] = mp_obj_new_int(reading.g); + tuple[RGBC_B] = mp_obj_new_int(reading.b); + tuple[RGBC_C] = mp_obj_new_int(reading.c); + + return mp_obj_new_tuple(4, tuple); +} + +mp_obj_t BreakoutBH1745_threshold(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_self, ARG_lower, ARG_upper }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_lower, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_upper, MP_ARG_REQUIRED | MP_ARG_INT }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + breakout_bh1745_BreakoutBH1745_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, breakout_bh1745_BreakoutBH1745_obj_t); + + int lower = args[ARG_lower].u_int; + int upper = args[ARG_upper].u_int; + + if(lower < 0 || lower > 65535) { + mp_raise_ValueError("lower out of range. Expected 0 to 65535"); + } else if(upper < 0 || upper > 65535) { + mp_raise_ValueError("upper out of range. Expected 0 to 65535"); + } else { + self->breakout->set_threshold_low(lower); + self->breakout->set_threshold_high(upper); + } + + return mp_const_none; +} + +mp_obj_t BreakoutBH1745_measurement_time_ms(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_self, ARG_time }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_time, MP_ARG_REQUIRED | MP_ARG_INT }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + breakout_bh1745_BreakoutBH1745_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, breakout_bh1745_BreakoutBH1745_obj_t); + + int measurement_time = args[ARG_time].u_int; + + if(measurement_time < 0 || measurement_time > 65535) { + mp_raise_ValueError("Time out of range. Expected 0 to 65535"); + } else { + self->breakout->set_measurement_time_ms(measurement_time); + } + + return mp_const_none; +} + +mp_obj_t BreakoutBH1745_leds(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_self, ARG_led_state }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_led_state, MP_ARG_REQUIRED | MP_ARG_BOOL }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + breakout_bh1745_BreakoutBH1745_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, breakout_bh1745_BreakoutBH1745_obj_t); + + bool state = args[ARG_led_state].u_bool; + + self->breakout->set_leds(state); + + return mp_const_none; +} + +} diff --git a/micropython/modules/breakout_bh1745/breakout_bh1745.h b/micropython/modules/breakout_bh1745/breakout_bh1745.h new file mode 100644 index 00000000..2272e94b --- /dev/null +++ b/micropython/modules/breakout_bh1745/breakout_bh1745.h @@ -0,0 +1,26 @@ +// Include MicroPython API. +#include "py/runtime.h" +#include "py/objstr.h" + +/***** Constants *****/ +enum { + RGBC_R, + RGBC_G, + RGBC_B, + RGBC_C +}; + +/***** Extern of Class Definition *****/ +extern const mp_obj_type_t breakout_bh1745_BreakoutBH1745_type; + +/***** Extern of Class Methods *****/ +extern void BreakoutBH1745_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); +extern mp_obj_t BreakoutBH1745_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args); +extern mp_obj_t BreakoutBH1745_chip_id(mp_obj_t self_in); +extern mp_obj_t BreakoutBH1745_manufacturer_id(mp_obj_t self_in); +extern mp_obj_t BreakoutBH1745_threshold(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); +extern mp_obj_t BreakoutBH1745_measurement_time_ms(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); +extern mp_obj_t BreakoutBH1745_rgbc_raw(mp_obj_t self_in); +extern mp_obj_t BreakoutBH1745_rgbc_clamped(mp_obj_t self_in); +extern mp_obj_t BreakoutBH1745_rgbc_scaled(mp_obj_t self_in); +extern mp_obj_t BreakoutBH1745_leds(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); diff --git a/micropython/modules/breakout_bh1745/micropython.cmake b/micropython/modules/breakout_bh1745/micropython.cmake new file mode 100644 index 00000000..f35f9b0b --- /dev/null +++ b/micropython/modules/breakout_bh1745/micropython.cmake @@ -0,0 +1,20 @@ +set(MOD_NAME breakout_bh1745) +string(TOUPPER ${MOD_NAME} MOD_NAME_UPPER) +add_library(usermod_${MOD_NAME} INTERFACE) + +target_sources(usermod_${MOD_NAME} INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/${MOD_NAME}.c + ${CMAKE_CURRENT_LIST_DIR}/${MOD_NAME}.cpp + ${CMAKE_CURRENT_LIST_DIR}/../../../libraries/${MOD_NAME}/${MOD_NAME}.cpp + ${CMAKE_CURRENT_LIST_DIR}/../../../drivers/bh1745/bh1745.cpp +) + +target_include_directories(usermod_${MOD_NAME} INTERFACE + ${CMAKE_CURRENT_LIST_DIR} +) + +target_compile_definitions(usermod_${MOD_NAME} INTERFACE + -DMODULE_${MOD_NAME_UPPER}_ENABLED=1 +) + +target_link_libraries(usermod INTERFACE usermod_${MOD_NAME}) \ No newline at end of file diff --git a/micropython/modules/micropython.cmake b/micropython/modules/micropython.cmake index 59956b8e..33dd2eec 100644 --- a/micropython/modules/micropython.cmake +++ b/micropython/modules/micropython.cmake @@ -21,6 +21,7 @@ include(breakout_rtc/micropython) include(breakout_trackball/micropython) include(breakout_sgp30/micropython) include(breakout_colourlcd240x240/micropython) +include(breakout_bh1745/micropython) include(pico_scroll/micropython) include(pico_rgb_keypad/micropython) From a0c2201df265bb40346f31b7c2a78b8a206745eb Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Fri, 30 Jul 2021 13:46:28 +0100 Subject: [PATCH 4/4] BH1745: Add I2C address constants --- micropython/modules/breakout_bh1745/breakout_bh1745.c | 3 +++ micropython/modules/breakout_bh1745/breakout_bh1745.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/micropython/modules/breakout_bh1745/breakout_bh1745.c b/micropython/modules/breakout_bh1745/breakout_bh1745.c index 6eef11f5..8c9211c8 100644 --- a/micropython/modules/breakout_bh1745/breakout_bh1745.c +++ b/micropython/modules/breakout_bh1745/breakout_bh1745.c @@ -45,6 +45,9 @@ const mp_obj_type_t breakout_bh1745_BreakoutBH1745_type = { STATIC const mp_map_elem_t breakout_bh1745_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_breakout_bh1745) }, { MP_OBJ_NEW_QSTR(MP_QSTR_BreakoutBH1745), (mp_obj_t)&breakout_bh1745_BreakoutBH1745_type }, + + { MP_ROM_QSTR(MP_QSTR_I2C_ADDRESS_DEFAULT), MP_ROM_INT(BH1745_I2C_ADDRESS_DEFAULT) }, + { MP_ROM_QSTR(MP_QSTR_I2C_ADDRESS_ALT), MP_ROM_INT(BH1745_I2C_ADDRESS_ALTERNATE) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_breakout_bh1745_globals, breakout_bh1745_globals_table); diff --git a/micropython/modules/breakout_bh1745/breakout_bh1745.h b/micropython/modules/breakout_bh1745/breakout_bh1745.h index 2272e94b..0b3065e7 100644 --- a/micropython/modules/breakout_bh1745/breakout_bh1745.h +++ b/micropython/modules/breakout_bh1745/breakout_bh1745.h @@ -10,6 +10,9 @@ enum { RGBC_C }; +static const uint8_t BH1745_I2C_ADDRESS_DEFAULT = 0x38; +static const uint8_t BH1745_I2C_ADDRESS_ALTERNATE = 0x39; + /***** Extern of Class Definition *****/ extern const mp_obj_type_t breakout_bh1745_BreakoutBH1745_type;