From 691171918352ba288b84113a9e0874aba0a90f3f Mon Sep 17 00:00:00 2001 From: Jonathan Williamson Date: Sun, 17 Jan 2021 16:05:28 +0000 Subject: [PATCH] example driver for MSA301, ability to embed an image into binary and draw it on screen --- drivers/CMakeLists.txt | 3 +- drivers/msa301/CMakeLists.txt | 10 +++++ drivers/msa301/msa301.cpp | 60 +++++++++++++++++++++++++ drivers/msa301/msa301.hpp | 36 +++++++++++++++ examples/pico_explorer/CMakeLists.txt | 11 ++++- examples/pico_explorer/demo.cpp | 62 +++++++++++++++----------- examples/pico_explorer/fox.tga | Bin 0 -> 16568 bytes 7 files changed, 153 insertions(+), 29 deletions(-) create mode 100644 drivers/msa301/CMakeLists.txt create mode 100644 drivers/msa301/msa301.cpp create mode 100644 drivers/msa301/msa301.hpp create mode 100644 examples/pico_explorer/fox.tga 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 0000000000000000000000000000000000000000..0620774f6dcd11fe59b8f3cdd5bc7fdadba0e468 GIT binary patch literal 16568 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 MfBfTbfBk#;FZq2S!vFvP literal 0 HcmV?d00001