diff --git a/drivers/CMakeLists.txt b/drivers/CMakeLists.txt index 1642f9a3..57d6b5df 100644 --- a/drivers/CMakeLists.txt +++ b/drivers/CMakeLists.txt @@ -1 +1,2 @@ -add_subdirectory(st7789) \ No newline at end of file +add_subdirectory(st7789) +add_subdirectory(msa301) \ No newline at end of file diff --git a/drivers/msa301/CMakeLists.txt b/drivers/msa301/CMakeLists.txt new file mode 100644 index 00000000..85e32500 --- /dev/null +++ b/drivers/msa301/CMakeLists.txt @@ -0,0 +1,10 @@ +add_library(msa301 INTERFACE) + +target_sources(msa301 INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/msa301.cpp +) + +target_include_directories(msa301 INTERFACE ${CMAKE_CURRENT_LIST_DIR}) + +# Pull in pico libraries that we need +target_link_libraries(msa301 INTERFACE pico_stdlib hardware_i2c) \ No newline at end of file diff --git a/drivers/msa301/msa301.cpp b/drivers/msa301/msa301.cpp new file mode 100644 index 00000000..dedc17d7 --- /dev/null +++ b/drivers/msa301/msa301.cpp @@ -0,0 +1,60 @@ +#include +#include +#include +#include + +#include "msa301.hpp" + +namespace pimoroni { + + enum reg { + RESET = 0x00, + X_AXIS = 0x02, + Y_AXIS = 0x04, + Z_AXIS = 0x06 + // todo: lots of other features + }; + + void MSA301::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(); + + i2c_reg_write_uint8(0x11, 0x00); // set power mode + i2c_reg_write_uint8(0x0f, 0x00); // set range & resolution + } + + void MSA301::i2c_reg_write_uint8(uint8_t reg, uint8_t value) { + uint8_t buffer[2] = {reg, value}; + i2c_write_blocking(i2c, address, buffer, 2, false); + } + + int16_t MSA301::i2c_reg_read_int16(uint8_t reg) { + int16_t value; + i2c_write_blocking(i2c, address, ®, 1, true); + i2c_read_blocking(i2c, address, (uint8_t *)&value, 2, false); + return value; + } + + void MSA301::reset() { + i2c_reg_write_uint8(reg::RESET, 0b00100100); + sleep_ms(1); + } + + float MSA301::get_axis(uint8_t axis, uint8_t sample_count) { + if(sample_count > 1) { + int32_t total = 0; + for(uint8_t i = 0; i < sample_count; i++) { + total += i2c_reg_read_int16(axis); + } + total /= sample_count; + return total / 16384.0f; + } + + return i2c_reg_read_int16(axis) / 16384.0f; + } + +} \ No newline at end of file diff --git a/drivers/msa301/msa301.hpp b/drivers/msa301/msa301.hpp new file mode 100644 index 00000000..95befd3d --- /dev/null +++ b/drivers/msa301/msa301.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include "hardware/i2c.h" +#include "hardware/gpio.h" + +namespace pimoroni { + + class MSA301 { + i2c_inst_t *i2c = i2c0; + + // interface pins with our standard defaults where appropriate + int8_t address = 0x26; + int8_t sda = 20; + int8_t scl = 21; + int8_t interrupt = 22; + + public: + MSA301() {} + + MSA301(i2c_inst_t *i2c, uint8_t sda, uint8_t scl, uint8_t interrupt) : + i2c(i2c), sda(sda), scl(scl), interrupt(interrupt) {} + + void init(); + void reset(); + + void i2c_reg_write_uint8(uint8_t reg, uint8_t value); + int16_t i2c_reg_read_int16(uint8_t reg); + + float get_axis(uint8_t axis, uint8_t sample_count = 1); + + const uint8_t X = 0x02; + const uint8_t Y = 0x04; + const uint8_t Z = 0x06; + }; + +} diff --git a/examples/pico_explorer/CMakeLists.txt b/examples/pico_explorer/CMakeLists.txt index 51552e7e..fef6f526 100644 --- a/examples/pico_explorer/CMakeLists.txt +++ b/examples/pico_explorer/CMakeLists.txt @@ -1,10 +1,17 @@ +add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/fox.o + COMMAND arm-none-eabi-ld -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/fox.o ${CMAKE_CURRENT_SOURCE_DIR}/fox.tga + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/fox.tga +) + add_executable( explorer demo.cpp + fox.o ) # Pull in pico libraries that we need -target_link_libraries(explorer pico_stdlib pico_explorer) +target_link_libraries(explorer pico_stdlib pico_explorer msa301) # create map/bin/hex file etc. -pico_add_extra_outputs(explorer) \ No newline at end of file +pico_add_extra_outputs(explorer) diff --git a/examples/pico_explorer/demo.cpp b/examples/pico_explorer/demo.cpp index 29806f36..cc8165f4 100644 --- a/examples/pico_explorer/demo.cpp +++ b/examples/pico_explorer/demo.cpp @@ -4,30 +4,17 @@ #include #include "pico_explorer.hpp" +#include "msa301.hpp" using namespace pimoroni; extern unsigned char image_tif[]; extern unsigned int image_tif_len; -PicoExplorer pico_explorer; -/* -void pixel(int x, int y, uint16_t c) { - x *= 2; - y *= 2; - pico_display.frame_buffer[x + y * 240] = c; - pico_display.frame_buffer[x + 1 + y * 240] = c; - pico_display.frame_buffer[x + 1 + (y + 1) * 240] = c; - pico_display.frame_buffer[x + (y + 1) * 240] = c; -} +extern unsigned char _binary__home_jon_pimoroni_pico_examples_pico_explorer_fox_tga_start[]; -void rect(int x, int y, int w, int h, uint16_t c) { - for(int rx = x; rx < x + w; rx++) { - for(int ry = y; ry < y + h; ry++) { - pixel(rx, ry, c); - } - } -}*/ +PicoExplorer pico_explorer; +MSA301 msa301; uint8_t arrow[] = { 0b00010000, @@ -70,15 +57,7 @@ void sprite(uint8_t *p, int x, int y, bool flip, uint16_t c) { }*/ int main() { - pico_explorer.set_backlight(100); - - // uint16_t white = pico_display.create_pen(255, 255, 255); - // uint16_t black = pico_display.create_pen(0, 0, 0); - // uint16_t red = pico_display.create_pen(255, 0, 0); - // uint16_t green = pico_display.create_pen(0, 255, 0); - // uint16_t dark_grey = pico_display.create_pen(20, 40, 60); - // uint16_t dark_green = pico_display.create_pen(10, 100, 10); - // uint16_t blue = pico_display.create_pen(0, 0, 255); + msa301.init(); bool a_pressed = false; bool b_pressed = false; @@ -146,8 +125,39 @@ int main() { pico_explorer.circle(bv * 140 + 50, 210, 15); pico_explorer.set_motor(pico_explorer.MOTOR1, pico_explorer.FORWARD, bv); + pico_explorer.set_motor(pico_explorer.MOTOR2, pico_explorer.FORWARD, rv); pico_explorer.set_tone(100 + (bv * 1000), rv); + + pico_explorer.set_pen(255, 255, 255); + pico_explorer.text("x: " + std::to_string(msa301.get_axis(msa301.X, 16)), 10, 190, 100); + pico_explorer.text("y: " + std::to_string(msa301.get_axis(msa301.Y, 16)), 10, 205, 100); + pico_explorer.text("z: " + std::to_string(msa301.get_axis(msa301.Z, 16)), 10, 220, 100); + + uint16_t xpos = (msa301.get_axis(msa301.X, 16) * 120) + 120; + uint16_t ypos = (msa301.get_axis(msa301.Z, 16) * 120) + 120; + pico_explorer.set_pen(255, 255, 255); + pico_explorer.circle(xpos, ypos, 20); + pico_explorer.set_pen(255, 0, 255); + pico_explorer.circle(xpos, ypos, 15); + + float xoff = sin(i / 20.0f) * 50.0f; + xoff += 120 - (81 / 2); + float yoff = cos(i / 20.0f) * 50.0f; + yoff += 120 - (68 / 2); + for(int y = 0; y < 68; y++) { + uint16_t *dest = pico_explorer.frame_buffer + (y * 240); + uint8_t *src = _binary__home_jon_pimoroni_pico_examples_pico_explorer_fox_tga_start + 18 + (y * 81 * 3); + for(int x = 0; x < 81; x++) { + uint8_t r = *src++; + uint8_t g = *src++; + uint8_t b = *src++; + + pico_explorer.set_pen(r, g, b); + pico_explorer.pixel(x + xoff, 68 - y + yoff); + } + } + /* if(pico_display.is_pressed(pico_display.A)) { pico_display.rectangle(0, 0, 18, 18); diff --git a/examples/pico_explorer/fox.tga b/examples/pico_explorer/fox.tga new file mode 100644 index 00000000..0620774f Binary files /dev/null and b/examples/pico_explorer/fox.tga differ