-
Notifications
You must be signed in to change notification settings - Fork 493
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
AS7343: New 14-channel spectral sensor driver.
- Loading branch information
Showing
10 changed files
with
546 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
include(as7343.cmake) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
set(DRIVER_NAME as7343) | ||
add_library(${DRIVER_NAME} INTERFACE) | ||
|
||
target_sources(${DRIVER_NAME} INTERFACE | ||
${CMAKE_CURRENT_LIST_DIR}/${DRIVER_NAME}.cpp) | ||
|
||
target_include_directories(${DRIVER_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR}) | ||
|
||
# Pull in pico libraries that we need | ||
target_link_libraries(${DRIVER_NAME} INTERFACE pico_stdlib hardware_i2c pimoroni_i2c) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
#include <cstdlib> | ||
#include <math.h> | ||
#include <map> | ||
#include <vector> | ||
#include <cstring> | ||
|
||
#include "as7343.hpp" | ||
|
||
namespace pimoroni { | ||
|
||
bool AS7343::init() { | ||
if(interrupt != PIN_UNUSED) { | ||
gpio_set_function(interrupt, GPIO_FUNC_SIO); | ||
gpio_set_dir(interrupt, GPIO_IN); | ||
gpio_pull_up(interrupt); | ||
} | ||
|
||
reset(); | ||
|
||
bank_select(0); | ||
|
||
// Enable all 7 channels in output FIFO | ||
i2c->set_bits(address, reg::FIFO_MAP, 0, FIFO_MAP_CH5 | FIFO_MAP_CH4 | FIFO_MAP_CH3 | FIFO_MAP_CH2 | FIFO_MAP_CH1 | FIFO_MAP_CH0 | FIFO_MAP_ASTATUS); | ||
|
||
// Set the PON bit | ||
i2c->reg_write_uint8(address, reg::ENABLE, ENABLE_WEN | ENABLE_SMUXEN | ENABLE_SP_EN | ENABLE_PON); | ||
|
||
return true; | ||
} | ||
|
||
void AS7343::reset() { | ||
i2c->reg_write_uint8(address, reg::CONTROL, CONTROL_SW_RESET); | ||
sleep_ms(1000); | ||
} | ||
|
||
i2c_inst_t* AS7343::get_i2c() const { | ||
return i2c->get_i2c(); | ||
} | ||
|
||
int AS7343::get_sda() const { | ||
return i2c->get_sda(); | ||
} | ||
|
||
int AS7343::get_scl() const { | ||
return i2c->get_scl(); | ||
} | ||
|
||
int AS7343::get_int() const { | ||
return interrupt; | ||
} | ||
|
||
void AS7343::bank_select(uint8_t bank) { | ||
if(bank == 1) { | ||
i2c->set_bits(address, reg::CFG0, 0, CFG0_BANK); | ||
} else { | ||
i2c->clear_bits(address, reg::CFG0, 0, CFG0_BANK); | ||
} | ||
} | ||
|
||
void AS7343::get_version(uint8_t &auxid, uint8_t &revid, uint8_t &hwid) { | ||
bank_select(1); | ||
auxid = i2c->reg_read_uint8(address, reg::AUXID) & 0b00001111; | ||
revid = i2c->reg_read_uint8(address, reg::REVID) & 0b00000111; | ||
hwid = i2c->reg_read_uint8(address, reg::ID); | ||
bank_select(0); | ||
} | ||
|
||
void AS7343::set_gain(float gain) { | ||
if(gain == 0.5f) { | ||
i2c->reg_write_uint8(address, reg::CFG1, 0); | ||
} else { | ||
uint16_t ugain = (uint16_t)gain; | ||
uint16_t bitlength = 0; | ||
while(ugain > 0) { | ||
bitlength++; | ||
ugain >>= 1; | ||
} | ||
i2c->reg_write_uint8(address, reg::CFG1, bitlength & 0x1f); | ||
} | ||
} | ||
|
||
void AS7343::set_channels(channel_count channel_count) { | ||
this->read_cycles = uint8_t(channel_count) / 6; | ||
this->ch_count = (uint8_t)channel_count; | ||
uint8_t temp = i2c->reg_read_uint8(address, reg::CFG20) & ~CFG20_18_CH; | ||
switch(channel_count) { | ||
case channel_count::SIX_CHANNEL: | ||
temp |= CFG20_6_CH; | ||
break; | ||
case channel_count::TWELVE_CHANNEL: | ||
temp |= CFG20_12_CH; | ||
break; | ||
case channel_count::EIGHTEEN_CHANNEL: | ||
temp |= CFG20_18_CH; | ||
break; | ||
} | ||
i2c->reg_write_uint8(address, reg::CFG20, temp); | ||
} | ||
|
||
void AS7343::set_illumination_current(float current) { | ||
current -= 4; | ||
current /= 2.0f; | ||
uint8_t temp = i2c->reg_read_uint8(address, reg::LED) & 0b10000000; | ||
temp |= (uint8_t)current; | ||
i2c->reg_write_uint8(address, reg::LED, temp); | ||
} | ||
|
||
void AS7343::set_illumination_led(bool state) { | ||
uint8_t temp = i2c->reg_read_uint8(address, reg::LED) & 0b01111111; | ||
temp |= state ? 0x80 : 0x00; | ||
i2c->reg_write_uint8(address, reg::LED, temp); | ||
} | ||
|
||
void AS7343::set_measurement_time(float measurement_time_ms) { | ||
constexpr float resolution = 2.78f; | ||
i2c->reg_write_uint8(address, reg::WTIME, (uint8_t)((measurement_time_ms - resolution) / resolution)); | ||
} | ||
|
||
void AS7343::set_integration_time(float integration_time_us, uint8_t repeat) { | ||
constexpr float resolution = 2.78f; | ||
constexpr float max_astep = (65534 + 1) * resolution; | ||
|
||
if (integration_time_us <= max_astep) { | ||
i2c->reg_write_uint8(address, reg::ATIME, repeat - 1); | ||
i2c->reg_write_uint16(address, reg::ASTEP, (uint16_t)((integration_time_us - resolution) / resolution) & 0xfffe); | ||
} else { | ||
// Time out of range... | ||
} | ||
} | ||
|
||
void AS7343::read_fifo(uint16_t *buf) { | ||
uint16_t expected_results = read_cycles * 7; | ||
uint16_t result_slot = 0; | ||
|
||
while (i2c->reg_read_uint8(address, reg::FIFO_LVL) < expected_results) { | ||
sleep_ms(1); | ||
} | ||
|
||
while (i2c->reg_read_uint8(address, reg::FIFO_LVL) > 0 && expected_results > 0) { | ||
buf[result_slot] = i2c->reg_read_uint16(address, reg::FDATA); | ||
expected_results--; | ||
result_slot++; | ||
} | ||
} | ||
|
||
AS7343::reading AS7343::read() { | ||
reading result; | ||
read_fifo((uint16_t *)&result); | ||
return result; | ||
} | ||
|
||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
#pragma once | ||
|
||
#include <string> | ||
|
||
#include "hardware/i2c.h" | ||
#include "hardware/gpio.h" | ||
#include "common/pimoroni_common.hpp" | ||
#include "common/pimoroni_i2c.hpp" | ||
#include "as7343_regs.hpp" | ||
|
||
namespace pimoroni { | ||
|
||
class AS7343 { | ||
//-------------------------------------------------- | ||
// Constants | ||
//-------------------------------------------------- | ||
public: | ||
static const uint8_t DEFAULT_I2C_ADDRESS = 0x39; | ||
|
||
//-------------------------------------------------- | ||
// Enums | ||
//-------------------------------------------------- | ||
public: | ||
enum class channel_count : uint8_t { | ||
SIX_CHANNEL = 6, | ||
TWELVE_CHANNEL = 12, | ||
EIGHTEEN_CHANNEL = 18 | ||
}; | ||
/* | ||
enum class COMPENSATION_GAIN : float { | ||
F1 = 1.84f, | ||
F2 = 6.03f, | ||
FZ = 4.88f, | ||
F3 = 13.74f, | ||
F4 = 3.37f, | ||
FY = 2.82f, | ||
F5 = 6.72f, | ||
FXL = 2.22f, | ||
F6 = 3.17f, | ||
F7 = 1.95f, | ||
F8 = 12.25f, | ||
NIR = 1.00f, | ||
}; | ||
*/ | ||
|
||
//-------------------------------------------------- | ||
// Substructures | ||
//-------------------------------------------------- | ||
public: | ||
struct reading { | ||
// Cycle 1 | ||
uint16_t FZ = 0; // 428-480 nm | ||
uint16_t FY = 0; // 534-593 nm | ||
uint16_t FXL = 0; // 593-628 nm | ||
uint16_t NIR = 0; // 849-903 nm | ||
|
||
uint16_t c1_vis_tl = 0; // Visible top-left | ||
uint16_t c1_vis_br = 0; // Visible bottom-right | ||
uint16_t c1_astatus = 0; // (c1_astatus >> 8) & 0b10001111 | ||
// 0b10000000 = saturated | ||
// 0b00001111 = gain lowest nibble | ||
|
||
// Cycle 2 | ||
uint16_t F2 = 0; // 408-448 nm | ||
uint16_t F3 = 0; // 448-500 mn | ||
uint16_t F4 = 0; // 500-534 nm | ||
uint16_t F6 = 0; // 618-665 nm | ||
|
||
uint16_t c2_vis_tl = 0; | ||
uint16_t c2_vis_br = 0; | ||
uint16_t c2_astatus = 0; | ||
|
||
// Cycle 3 | ||
uint16_t F1 = 0; // 396-408 nm | ||
uint16_t F5 = 0; // 531-594 nm | ||
uint16_t F7 = 0; // 685-715 nm | ||
uint16_t F8 = 0; // 715-766 nm | ||
|
||
uint16_t c3_vis_tl = 0; | ||
uint16_t c3_vis_br = 0; | ||
uint16_t c3_astatus = 0; | ||
}; | ||
|
||
|
||
//-------------------------------------------------- | ||
// Variables | ||
//-------------------------------------------------- | ||
private: | ||
I2C *i2c; | ||
|
||
// interface pins with our standard defaults where appropriate | ||
int8_t address = DEFAULT_I2C_ADDRESS; | ||
uint interrupt = PIN_UNUSED; | ||
|
||
uint8_t read_cycles = 1; | ||
uint8_t ch_count = (uint8_t)channel_count::SIX_CHANNEL; | ||
|
||
|
||
//-------------------------------------------------- | ||
// Constructors/Destructor | ||
//-------------------------------------------------- | ||
public: | ||
AS7343(uint interrupt = PIN_UNUSED) : AS7343(new I2C(), interrupt) {}; | ||
|
||
AS7343(I2C *i2c, uint interrupt = PIN_UNUSED) : i2c(i2c), interrupt(interrupt) {} | ||
|
||
|
||
//-------------------------------------------------- | ||
// Methods | ||
//-------------------------------------------------- | ||
public: | ||
bool init(); | ||
void reset(); | ||
|
||
// For print access in micropython | ||
i2c_inst_t* get_i2c() const; | ||
int get_sda() const; | ||
int get_scl() const; | ||
int get_int() const; | ||
|
||
void get_version(uint8_t &auxid, uint8_t &revid, uint8_t &hwid); | ||
|
||
reading read(); | ||
|
||
void read_fifo(uint16_t *buf); | ||
|
||
void set_gain(float gain); | ||
void set_illumination_current(float current); | ||
void set_illumination_led(bool state); | ||
void set_measurement_time(float measurement_time_ms); | ||
void set_integration_time(float integration_time_us, uint8_t repeat=1); | ||
|
||
void set_channels(channel_count channel_count); | ||
|
||
private: | ||
void bank_select(uint8_t bank=0); | ||
}; | ||
|
||
} |
Oops, something went wrong.