From 169a9d51b2acfd8c6375f15baaab72b8da79f845 Mon Sep 17 00:00:00 2001 From: Jonathan BAUDIN Date: Thu, 26 Sep 2024 13:42:01 +0000 Subject: [PATCH 1/2] feat(samples): Add a sample of the STeaMi's main features --- samples/OOB/accelero.h | 63 ++++++++++ samples/OOB/buzzer.h | 92 ++++++++++++++ samples/OOB/compass.h | 111 +++++++++++++++++ samples/OOB/game.h | 263 +++++++++++++++++++++++++++++++++++++++++ samples/OOB/menu.h | 121 +++++++++++++++++++ samples/OOB/oob.cpp | 141 ++++++++++++++++++++++ samples/OOB/oob.h | 8 ++ samples/OOB/rgb.h | 70 +++++++++++ samples/OOB/sensors.h | 34 ++++++ samples/OOB/utils.h | 53 +++++++++ samples/main.cpp | 2 + 11 files changed, 958 insertions(+) create mode 100644 samples/OOB/accelero.h create mode 100644 samples/OOB/buzzer.h create mode 100644 samples/OOB/compass.h create mode 100644 samples/OOB/game.h create mode 100644 samples/OOB/menu.h create mode 100644 samples/OOB/oob.cpp create mode 100644 samples/OOB/oob.h create mode 100644 samples/OOB/rgb.h create mode 100644 samples/OOB/sensors.h create mode 100644 samples/OOB/utils.h diff --git a/samples/OOB/accelero.h b/samples/OOB/accelero.h new file mode 100644 index 0000000..1abd2b3 --- /dev/null +++ b/samples/OOB/accelero.h @@ -0,0 +1,63 @@ +#pragma once + +#include "ism330dl.h" +#include "utils.h" + +extern codal::STM32Pin* btnMenu; +extern codal::ISM330DL* ism; +extern codal::SSD1327_SPI* ssd; + +class Ball { + public: + int x; + int y; + float ax; + float ay; + float speed; + int radius; + + Ball(int x, int y, int radius) : x{x}, y{y}, ax{0}, ay{0}, speed{3}, radius{radius} {} + + float low_limit() { return 18 + radius; } + float high_limit() { return 110 - radius; } + + void update(ISM_Data& accel) + { + ax = clampf(ax + (accel.y), -5, 5); + ay = clampf(ay - (accel.x), -5, 5); + + x += ax * speed; + y += ay * speed; + + if (x < low_limit() || x > high_limit()) { + ax *= -0.8; + x = clampf(x, low_limit(), high_limit()); + } + + if (y < low_limit() || y > high_limit()) { + ay *= -0.8; + y = clampf(y, low_limit(), high_limit()); + } + } + + void draw() { ssd->drawCircle(x, y, radius, false, 0xFF); } +}; + +void accelero_prog() +{ + Ball ball(64, 64, 8); + while (true) { + if (click_button(btnMenu)) { + break; + } + + auto accel = ism->readAccelerometerData(); + + ball.update(accel); + + ssd->fill(0x00); + ssd->drawRectangle(18, 18, 110, 110, false, 0xFF); + ball.draw(); + ssd->show(); + } +} \ No newline at end of file diff --git a/samples/OOB/buzzer.h b/samples/OOB/buzzer.h new file mode 100644 index 0000000..fa96f7e --- /dev/null +++ b/samples/OOB/buzzer.h @@ -0,0 +1,92 @@ +#pragma once + +#include + +#include "utils.h" + +extern codal::STM32Pin* btnMenu; +extern codal::STM32Pin* buzzer; +extern codal::SSD1327_SPI* ssd; +extern codal::MCP23009E* mcp; + +void buzzer_prog() +{ + uint8_t* cursor = new uint8_t(2); + int* freq = new int(440); + + mcp->interruptOnFalling(MCP_GP_BOTTOM, [=]() { + int p = pow(10, *cursor); + int digit = int(*freq / p) % 10; + if (digit == 0) { + return; + } + + *freq -= p; + buzzer->setAnalogPeriodUs(1000000 / *freq); + buzzer->setAnalogValue(255); + }); + + mcp->interruptOnFalling(MCP_GP_UP, [=]() { + int p = pow(10, *cursor); + int digit = int(*freq / p) % 10; + if (digit == 9) { + return; + } + + *freq += p; + buzzer->setAnalogPeriodUs(1000000 / *freq); + buzzer->setAnalogValue(255); + }); + + mcp->interruptOnFalling(MCP_GP_LEFT, [=]() { + if (*cursor < 5) { + (*cursor)++; + } + }); + + mcp->interruptOnFalling(MCP_GP_RIGHT, [=]() { + if (*cursor > 0) { + (*cursor)--; + } + }); + + buzzer->setAnalogPeriodUs(1000000 / *freq); + buzzer->setAnalogValue(255); + + while (1) { + if (click_button(btnMenu)) { + break; + } + + auto freqStr = std::to_string(*freq); + string cursorStr = " "; + + while (freqStr.size() < 5) { + freqStr = "0" + freqStr; + } + + for (int8_t i = 4; i >= 0; --i) { + if (i == *cursor) { + cursorStr.push_back('^'); + } + else { + cursorStr.push_back(' '); + } + } + + ssd->fill(0x00); + ssd->drawText("Freq: " + freqStr + "Hz", 15, 40, 0xFF); + ssd->drawText(cursorStr, 15, 48, 0xFF); + ssd->drawText("< / >: change digit", 5, 66, 0xFF); + ssd->drawText("^ / v: de/increase", 5, 75, 0xFF); + ssd->show(); + + fiber_sleep(100); + } + + buzzer->setAnalogValue(0); + mcp->disableInterrupt(MCP_GP_BOTTOM); + mcp->disableInterrupt(MCP_GP_UP); + delete cursor; + delete freq; +} \ No newline at end of file diff --git a/samples/OOB/compass.h b/samples/OOB/compass.h new file mode 100644 index 0000000..fa04596 --- /dev/null +++ b/samples/OOB/compass.h @@ -0,0 +1,111 @@ +#pragma once + +#include +#include +#include + +#include "lis2mdl.h" +#include "utils.h" + +extern codal::STM32Pin* btnMenu; +extern codal::STM32Pin* btnA; +extern codal::LIS2MDL* lis; +extern codal::SSD1327_SPI* ssd; + +constexpr float TRI_ANGLE = 155.0 * 0.017452792; + +float mapf(float x, float in_min, float in_max, float out_min, float out_max) +{ + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; +} + +Lis2Data average_measure(unsigned nb_measure) +{ + Lis2Data data{.x = 0, .y = 0, .z = 0}; + + for (unsigned i = 0; i < nb_measure; ++i) { + Lis2Data magn = lis->readData(); + + data.x += magn.x; + data.y += magn.y; + } + + data.x /= float(nb_measure); + data.y /= float(nb_measure); + + return data; +} + +void compass_prog() +{ + float size = 32; + float cx = 64; + float cy = 64; + float calib_min_x = std::numeric_limits::max(); + float calib_max_x = std::numeric_limits::min(); + float calib_min_y = std::numeric_limits::max(); + float calib_max_y = std::numeric_limits::min(); + + // calibration + ssd->fill(0x00); + ssd->drawRectangle(25, 14, 102, 40, true, 0xFF); + ssd->drawText("CALIBRATION", 31, 18, 0x00); + ssd->drawText("MAGNETOMETER", 28, 29, 0x00); + ssd->drawText("Move the STeaMi", 21, 49, 0xFF); + ssd->drawText("by making \"8\" shapes", 5, 60, 0xFF); + ssd->drawText("Push \"A\" to finish", 12, 86, 0xFF); + ssd->show(); + + while (true) { + if (click_button(btnA)) { + break; + } + + Lis2Data magn = average_measure(20); + + calib_max_x = std::max(calib_max_x, magn.x); + calib_min_x = std::min(calib_min_x, magn.x); + + calib_max_y = std::max(calib_max_y, magn.y); + calib_min_y = std::min(calib_min_y, magn.y); + } + + printf("Calibration:\n\tx: [%.2f, %.2f]\n\ty: [%.2f, %.2f]\n", calib_min_x, calib_max_x, calib_min_y, calib_max_y); + + while (true) { + if (click_button(btnMenu)) { + break; + } + + Lis2Data magn = average_measure(10); + + float x = mapf(magn.x, calib_min_x, calib_max_x, -1, 1); + float y = -mapf(magn.y, calib_min_y, calib_max_y, -1, 1); + float angle = std::atan2(y, x); + + + double Acos = cos(angle); + double Asin = sin(angle); + double Bcos = cos(angle - TRI_ANGLE); + double Bsin = sin(angle - TRI_ANGLE); + double Ccos = cos(angle + TRI_ANGLE); + double Csin = sin(angle + TRI_ANGLE); + + + ssd->fill(0x00); + ssd->drawCircle(64, 64, 50, false, 0xFF); + ssd->drawCircle(64, 64, 2, true, 0xFF); + + ssd->drawSegment(cx + (size * Bcos), cy + (size * Bsin), cx + (size * Acos), cy + (size * Asin), 1, 0xFF); + ssd->drawSegment(cx + (size * Ccos), cy + (size * Csin), cx + (size * Acos), cy + (size * Asin), 1, 0xFF); + ssd->drawSegment(cx + (size * Ccos), cy + (size * Csin), cx + (size * Bcos), cy + (size * Bsin), 1, 0xFF); + + ssd->drawText("N", 61, 2, 0xFF); + ssd->drawText("S", 61, 119, 0xFF); + ssd->drawText("O", 2, 61, 0xFF); + ssd->drawText("E", 121, 61, 0xFF); + ssd->show(); + + target_wait(100); + } +} \ No newline at end of file diff --git a/samples/OOB/game.h b/samples/OOB/game.h new file mode 100644 index 0000000..73dcd7e --- /dev/null +++ b/samples/OOB/game.h @@ -0,0 +1,263 @@ +#pragma once + +#include +#include + +#include "clock.h" +#include "ssd1327.h" +#include "utils.h" + +constexpr double DEG_TO_RAD = 0.017452792; + +extern codal::STM32Pin* btnMenu; +extern codal::STM32Pin* btnA; +extern codal::STM32Pin* btnB; +extern codal::SSD1327_SPI* ssd; +extern codal::MCP23009E* mcp; + +class Earth { + public: + int size; + bool is_explode; + Earth(int size) : size{size}, is_explode{false} {} + void draw() + { + ssd->drawCircle(64, 64, size, true, 0xFF); + ssd->drawText("Home", 53, 60, 0x00); + } +}; + +class Ship { + public: + int angle; + unsigned cx; + unsigned cy; + unsigned size; + unsigned speed; + Earth& earth; + + Ship(Earth& earth, unsigned speed) : angle{0}, cx{0}, cy{0}, size{5}, speed{speed}, earth{earth} + { + compute_center(); + } + + void move_left() + { + angle = wrap(angle - speed, 0, 359); + compute_center(); + } + void move_right() + { + angle = wrap(angle + speed, 0, 359); + compute_center(); + } + + void compute_center() + { + double c = cos(double(angle) * DEG_TO_RAD); + double s = sin(double(angle) * DEG_TO_RAD); + cx = 64 + (earth.size + 5) * c; + cy = 64 + (earth.size + 5) * s; + } + + void draw() + { + double Acos = cos(double(angle) * DEG_TO_RAD); + double Asin = sin(double(angle) * DEG_TO_RAD); + double Bcos = cos(double(angle - 120) * DEG_TO_RAD); + double Bsin = sin(double(angle - 120) * DEG_TO_RAD); + double Ccos = cos(double(angle + 120) * DEG_TO_RAD); + double Csin = sin(double(angle + 120) * DEG_TO_RAD); + + ssd->drawSegment(cx + (size * Bcos), cy + (size * Bsin), cx + (size * Acos), cy + (size * Asin), 1, 0xFF); + ssd->drawSegment(cx + (size * Ccos), cy + (size * Csin), cx + (size * Acos), cy + (size * Asin), 1, 0xFF); + ssd->drawSegment(cx + (size * Ccos), cy + (size * Csin), cx + (size * Bcos), cy + (size * Bsin), 1, 0xFF); + } +}; + +class Enemy { + public: + float cosine; + float sine; + unsigned size; + float distance; + bool is_dead; + + Enemy(unsigned size) : size{size}, distance{64}, is_dead{false} + { + int angle = target_random(360); + cosine = cos(angle * DEG_TO_RAD); + sine = sin(angle * DEG_TO_RAD); + } + + void draw() + { + if (is_dead) { + return; + } + + ssd->drawPolygon(pos_x(), pos_y(), 5, size, 1, 0xFF); + } + + int pos_x() { return 64 + distance * cosine; } + + int pos_y() { return 64 + distance * sine; } + + void update(Earth& earth) + { + if (is_dead) { + return; + } + + if (distance <= earth.size) { + earth.is_explode = true; + } + + distance -= 0.8; + } +}; + +class Bullet { + public: + float cosine; + float sine; + unsigned size; + float distance; + bool is_out; + + Bullet(int angle, unsigned size, float distance) : size{size}, distance{distance}, is_out{false} + { + cosine = cos(angle * DEG_TO_RAD); + sine = sin(angle * DEG_TO_RAD); + } + + void draw() + { + if (is_out) { + return; + } + ssd->drawCircle(pos_x(), pos_y(), size, true, 0xFF); + } + + int pos_x() { return 64 + distance * cosine; } + + int pos_y() { return 64 + distance * sine; } + + void update(Enemy& enemy) + { + if (is_out) { + return; + } + + int x = pow(pos_x() - enemy.pos_x(), 2); + int y = pow(pos_y() - enemy.pos_y(), 2); + int radius = pow(max(size, enemy.size), 2); + + if (x + y <= radius) { + enemy.is_dead = true; + is_out = true; + } + else { + distance += 2; + is_out = distance > (64 + size); + } + } +}; + +void game() +{ + Earth earth(15); + Ship ship(earth, 8); + Enemy enemy(5); + std::vector bullets(3, Bullet(0, 0, 200)); + + uint32_t score = 0; + bool is_playing = true; + bool can_shoot = true; + target_seed_random(getCurrentMillis()); + + while (true) { + if (click_button(btnMenu)) { + break; + } + + if (is_playing) { + if (mcp->getLevel(MCP_GP_RIGHT) == codal::MCP_LOGIC_LEVEL::LOW) { + ship.move_right(); + } + else if (mcp->getLevel(MCP_GP_LEFT) == codal::MCP_LOGIC_LEVEL::LOW) { + ship.move_left(); + } + + if (btnA->getDigitalValue() == 0 && can_shoot) { + for (unsigned i = 0; i < bullets.size(); ++i) { + if (bullets[i].is_out) { + bullets[i] = Bullet(ship.angle, 1, earth.size + 5); + can_shoot = false; + break; + } + } + } + else if (btnA->getDigitalValue() == 1) { + can_shoot = true; + } + + if (enemy.is_dead) { + score++; + enemy = Enemy(enemy.size); + } + + if (earth.is_explode) { + is_playing = false; + continue; + } + + for (unsigned i = 0; i < bullets.size(); ++i) { + bullets[i].update(enemy); + } + + enemy.update(earth); + + ssd->fill(0x00); + + if (score >= 100) + ssd->drawText(std::to_string(score), 56, 2, 0xFF); + else if (score >= 10) + ssd->drawText(std::to_string(score), 59, 2, 0xFF); + else + ssd->drawText(std::to_string(score), 62, 2, 0xFF); + + earth.draw(); + ship.draw(); + + for (unsigned i = 0; i < bullets.size(); ++i) { + bullets[i].draw(); + } + enemy.draw(); + + ssd->show(); + } + else { + if (click_button(btnB)) { + score = 0; + is_playing = true; + earth.is_explode = false; + enemy.is_dead = true; + for (unsigned i = 0; i < bullets.size(); ++i) { + bullets[i].is_out = true; + } + } + + ssd->fill(0x00); + ssd->drawRectangle(38, 28, 95, 39, true, 0xFF); + ssd->drawText("GAME OVER", 40, 30, 0x00); + ssd->drawText("Score: " + std::to_string(score), 35, 50, 0xFF); + ssd->drawText("Press \"B\"", 27, 78, 0xFF); + ssd->drawText("ro restart !", 31, 89, 0xFF); + ssd->show(); + } + } + + ssd->fill(0x00); + ssd->show(); +} \ No newline at end of file diff --git a/samples/OOB/menu.h b/samples/OOB/menu.h new file mode 100644 index 0000000..b7c900b --- /dev/null +++ b/samples/OOB/menu.h @@ -0,0 +1,121 @@ +#pragma once + +#include +#include +#include + +#include "ssd1327.h" + +constexpr int MENU_POS_X = 25; +constexpr int MENU_POS_X_CURSOR = 15; +constexpr int MENU_MIDDLE_POS_Y = 60; +constexpr int MENU_LINE_HEIGHT = 9; +constexpr char MENU_SELECT_SYM = '>'; +constexpr uint8_t MENU_ENTRY_PER_SCREEN = 9; + +struct MenuEntry { + std::string name; + std::function func; +}; + +class ScreenMenu { + public: + ScreenMenu(codal::SSD1327& ssd, std::vector entries) + : ssd(ssd), entries(entries), menuOffset(0), cursorPos(0) + { + midMenu = std::min(4, (int)entries.size() / 2); + } + + void moveUp() + { + printCursor(0x00); + + cursorPos--; + + if (cursorPos < menuOffset) { + if (!moveDownMenu()) cursorPos = entries.size() - 1; + } + + printCursor(0xFF); + ssd.show(); + } + + void moveDown() + { + printCursor(0x00); + + cursorPos++; + + if (cursorPos >= (menuOffset + MENU_ENTRY_PER_SCREEN)) { + if (!moveUpMenu()) cursorPos = 0; + } + + printCursor(0xFF); + ssd.show(); + } + + void execute() { entries[cursorPos].func(); } + + void show() + { + printMenu(); + printCursor(0xFF); + ssd.show(); + } + + private: + codal::SSD1327& ssd; + std::vector entries; + + int8_t menuOffset; + int8_t cursorPos; + uint8_t midMenu; + + void printCursor(uint16_t color) + { + unsigned midPoint = MENU_MIDDLE_POS_Y - midMenu * MENU_LINE_HEIGHT; + + ssd.drawChar(MENU_SELECT_SYM, MENU_POS_X_CURSOR, + midPoint + (cursorPos * MENU_LINE_HEIGHT) - (menuOffset * MENU_LINE_HEIGHT), color); + } + + void printMenu() + { + ssd.fill(0x00); + + unsigned midPoint = MENU_MIDDLE_POS_Y - midMenu * MENU_LINE_HEIGHT; + + for (uint8_t i = menuOffset; i < menuOffset + MENU_ENTRY_PER_SCREEN; ++i) { + unsigned relativePos = (i * MENU_LINE_HEIGHT) - (menuOffset * MENU_LINE_HEIGHT); + ssd.drawText(entries[i].name, MENU_POS_X, midPoint + relativePos, 0xFF); + } + } + + bool moveUpMenu() + { + bool result = true; + menuOffset++; + + if ((menuOffset + MENU_ENTRY_PER_SCREEN) > (int8_t)entries.size()) { + menuOffset = 0; + result = false; + } + + printMenu(); + return result; + } + + bool moveDownMenu() + { + bool result = true; + menuOffset--; + + if (menuOffset < 0) { + menuOffset = std::max(0, (int8_t)entries.size() - MENU_ENTRY_PER_SCREEN); + result = false; + } + + printMenu(); + return result; + } +}; \ No newline at end of file diff --git a/samples/OOB/oob.cpp b/samples/OOB/oob.cpp new file mode 100644 index 0000000..48fd406 --- /dev/null +++ b/samples/OOB/oob.cpp @@ -0,0 +1,141 @@ +#include "oob.h" + +using namespace codal; +using namespace std; + +#include +#include +#include +#include +#include + +#include "APDS9960.h" +#include "HTS221.h" +#include "STM32Pin.h" +#include "STM32RTC.h" +#include "STM32SAI.h" +#include "VL53L1X.h" +#include "WSEN-PADS.h" +#include "ism330dl.h" +#include "lis2mdl.h" +#include "mcp23009-e.h" +#include "menu.h" +#include "pcm_utils.h" +#include "pdm2pcm.h" +#include "ssd1327.h" +// #include "STM32SingleWireSerial.h" + +#include "accelero.h" +#include "buzzer.h" +#include "compass.h" +#include "game.h" +#include "rgb.h" +#include "sensors.h" +#include "utils.h" + +typedef void (*prog_func)(void); + +STM32SPI* spi = nullptr; +STM32Pin* cs = nullptr; +STM32Pin* dc = nullptr; +STM32Pin* rst = nullptr; +STM32Pin* led_red = nullptr; +STM32Pin* led_green = nullptr; +STM32Pin* led_blue = nullptr; +SSD1327_SPI* ssd = nullptr; + +STM32Pin* btnMenu = nullptr; +STM32Pin* btnA = nullptr; +STM32Pin* btnB = nullptr; +STM32Pin* buzzer = nullptr; + +MCP23009E* mcp = nullptr; +HTS221* hts = nullptr; +WSEN_PADS* pres = nullptr; +VL53L1X* tof = nullptr; +ISM330DL* ism = nullptr; +LIS2MDL* lis = nullptr; + +void Demo_OOB(codal::STM32STEAM32_WB55RG& steam32) +{ + spi = &steam32.spi1; + cs = &steam32.io.PD_0; + dc = &steam32.io.PB_4; + rst = &steam32.io.PA_12; + ssd = new SSD1327_SPI(*spi, *cs, *dc, *rst, 128, 128); + btnMenu = &steam32.io.PA_0; + btnA = &steam32.io.PA_7; + btnB = &steam32.io.PA_8; + buzzer = &steam32.io.PA_11; + + led_red = &steam32.io.PC_12; + led_green = &steam32.io.PC_11; + led_blue = &steam32.io.PC_10; + + buzzer->setAnalogValue(0); + + steam32.serial.init(115200); + steam32.sleep(500); + + printf("Init...\r\n"); + + ssd->init(); + ssd->fill(0x00); + ssd->drawText("Initialization...", 20, 60, 0xFF); + ssd->show(); + + printf("Init. MCP23009E...\n"); + mcp = new MCP23009E(steam32.i2c1, 0x40, steam32.io.PB_1, steam32.io.PB_0); + mcp->setup(MCP_GP_RIGHT, MCP_DIR::INPUT); + mcp->setup(MCP_GP_BOTTOM, MCP_DIR::INPUT); + mcp->setup(MCP_GP_LEFT, MCP_DIR::INPUT); + mcp->setup(MCP_GP_UP, MCP_DIR::INPUT); + + printf("Init. HTS221...\n"); + hts = new HTS221(&steam32.i2c1, 0xBE); + hts->init(); + hts->setOutputRate(codal::HTS221_OUTPUT_RATE::RATE_7HZ); + + printf("Init. WSEN_PADS...\n"); + pres = new WSEN_PADS(steam32.i2c1, 0xBA); + pres->init(); + + printf("Init. VL53L1X...\n"); + tof = new VL53L1X(&steam32.i2c1); + tof->init(); + + printf("Init. ISM330DL...\n"); + ism = new ISM330DL(&steam32.i2c1); + ism->init(); + ism->setAccelerometerODR(ISM_ODR::F_1_66_KHZ); + ism->setGyroscopeODR(ISM_ODR::F_208_HZ); + + printf("Init. LIS2MDL...\n"); + lis = new LIS2MDL(&steam32.i2c1); + lis->init(); + + unsigned select_prog = 0; + vector progs({game, buzzer_prog, sensors_prog, rgb_prog, compass_prog, accelero_prog}); + + printf("Init done\nHello STeamy !\r\n"); + ssd->fill(0x00); + ssd->drawText("Use the 'Menu' key", 11, 46, 0xFF); + ssd->drawText("to change demo", 22, 60, 0xFF); + ssd->show(); + + while (true) { + if (click_button(btnMenu)) { + break; + } + } + ssd->fill(0x00); + ssd->show(); + + while (1) { + progs[select_prog](); + + if (++select_prog >= progs.size()) { + select_prog = 0; + } + } +} \ No newline at end of file diff --git a/samples/OOB/oob.h b/samples/OOB/oob.h new file mode 100644 index 0000000..9f05865 --- /dev/null +++ b/samples/OOB/oob.h @@ -0,0 +1,8 @@ +#pragma once +#include "STM32STEAM32_WB55RG.h" + +#ifndef SAMPLE_MAIN +#define SAMPLE_MAIN Demo_OOB +#endif + +void Demo_OOB(codal::STM32STEAM32_WB55RG& steam32); \ No newline at end of file diff --git a/samples/OOB/rgb.h b/samples/OOB/rgb.h new file mode 100644 index 0000000..217fb4f --- /dev/null +++ b/samples/OOB/rgb.h @@ -0,0 +1,70 @@ +#pragma once + +#include + +extern codal::MCP23009E* mcp; +extern codal::STM32Pin* btnMenu; +extern codal::STM32Pin* led_red; +extern codal::STM32Pin* led_green; +extern codal::STM32Pin* led_blue; + +void rgb_prog() +{ + uint8_t* select_line = new uint8_t(0); + int state_red = 0; + int state_green = 0; + int state_blue = 0; + + mcp->interruptOnFalling(MCP_GP_BOTTOM, [=]() { + if (*select_line < 2) { + (*select_line)++; + } + }); + + mcp->interruptOnFalling(MCP_GP_UP, [=]() { + if (*select_line > 0) { + (*select_line)--; + } + }); + + while (1) { + if (click_button(btnMenu)) { + break; + } + + if (click_button(btnA)) { + switch (*select_line) { + case 0: + state_red = state_red == 0 ? 1 : 0; + led_red->setDigitalValue(state_red); + break; + + case 1: + state_green = state_green == 0 ? 1 : 0; + led_green->setDigitalValue(state_green); + break; + + case 2: + state_blue = state_blue == 0 ? 1 : 0; + led_blue->setDigitalValue(state_blue); + break; + } + } + + ssd->fill(0x00); + ssd->drawText("Toggle Red LED", 15, 51, 0xFF); + ssd->drawText("Toggle Green LED", 15, 60, 0xFF); + ssd->drawText("Toggle Blue LED", 15, 69, 0xFF); + ssd->drawText(">", 5, (*select_line) * 9 + 51, 0xFF); + ssd->show(); + + fiber_sleep(1); + } + + mcp->disableInterrupt(MCP_GP_BOTTOM); + mcp->disableInterrupt(MCP_GP_UP); + led_red->setDigitalValue(0); + led_green->setDigitalValue(0); + led_blue->setDigitalValue(0); + delete select_line; +} diff --git a/samples/OOB/sensors.h b/samples/OOB/sensors.h new file mode 100644 index 0000000..3a3c7b0 --- /dev/null +++ b/samples/OOB/sensors.h @@ -0,0 +1,34 @@ +#pragma once + +#include "HTS221.h" +#include "ssd1327.h" +#include "utils.h" + +extern codal::SSD1327_SPI* ssd; +extern codal::HTS221* hts; +extern codal::WSEN_PADS* pres; +extern codal::VL53L1X* tof; + +void sensors_prog() +{ + while (1) { + fiber_sleep(125); + + if (click_button(btnMenu)) { + break; + } + + if (!hts->isTemperatureDataAvailable() || !hts->isHumidityDataAvailable()) { + printf("HTS221 not ready\r\n"); + continue; + } + + ssd->fill(0x00); + ssd->drawText("Temperature: " + fToStr(hts->getTemperature(), 2) + " C", 5, 50, 0xFF); + ssd->drawText("Humidity: " + fToStr(hts->getHumidity(), 2) + " %HR", 5, 60, 0xFF); + ssd->drawText("Pressure: " + fToStr(pres->getPressure(), 2) + " kPa", 5, 70, 0xFF); + // ssd->drawText("Distance: " + fToStr(tof->getDistance(), 2) + " mm", 5, 80, 0xFF); + + ssd->show(); + } +} \ No newline at end of file diff --git a/samples/OOB/utils.h b/samples/OOB/utils.h new file mode 100644 index 0000000..2ee2bdb --- /dev/null +++ b/samples/OOB/utils.h @@ -0,0 +1,53 @@ +#pragma once + +#include +#include + +// constexpr uint8_t MCP_GPIO_1 = 0; +// constexpr uint8_t MCP_GPIO_2 = 1; +// constexpr uint8_t MCP_GPIO_3 = 2; +// constexpr uint8_t MCP_GPIO_4 = 3; +constexpr uint8_t MCP_GP_RIGHT = 4; +constexpr uint8_t MCP_GP_BOTTOM = 5; +constexpr uint8_t MCP_GP_LEFT = 6; +constexpr uint8_t MCP_GP_UP = 7; + +std::string fToStr(float value, unsigned pres) +{ + int ent = (int)value; + int dec = (int)((value - ent) * pow(10, pres)); + + return std::to_string(ent) + "." + to_string(abs(dec)); +} + +bool click_button(codal::STM32Pin* btn) +{ + if (btn->getDigitalValue() == 0) { + while (btn->getDigitalValue() == 0) + ; + + return true; + } + + return false; +} + +int wrap(int value, int min, int max) +{ + if (value < min) + return max - (min - value); + else if (value > max) + return min + (value - max); + else + return value; +} + +float clampf(float value, float min, float max) +{ + if (value < min) + return min; + else if (value > max) + return max; + else + return value; +} \ No newline at end of file diff --git a/samples/main.cpp b/samples/main.cpp index 9fd44d3..e96edb8 100644 --- a/samples/main.cpp +++ b/samples/main.cpp @@ -33,6 +33,8 @@ #include "FUS_WS_Operator.h" #elif defined(BLE_BROADCAST) #include "BLE_Broadcast_Sample.h" +#elif defined(OOB) +#include "oob.h" #else #include "BlinkSample.h" #endif From ec45689d20e42527bde27080596d93b712c9df0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20NEDJAR?= Date: Tue, 8 Oct 2024 14:52:05 +0000 Subject: [PATCH 2/2] fix(sample): update pin name after model changes (#13) --- samples/OOB/buzzer.h | 6 ++-- samples/OOB/compass.h | 32 ++++++++++---------- samples/OOB/oob.cpp | 68 +++++++++++++++++++++---------------------- samples/OOB/oob.h | 6 ++-- samples/OOB/utils.h | 3 +- samples/main.cpp | 36 +++++++++++------------ 6 files changed, 74 insertions(+), 77 deletions(-) diff --git a/samples/OOB/buzzer.h b/samples/OOB/buzzer.h index fa96f7e..2f48961 100644 --- a/samples/OOB/buzzer.h +++ b/samples/OOB/buzzer.h @@ -22,7 +22,7 @@ void buzzer_prog() } *freq -= p; - buzzer->setAnalogPeriodUs(1000000 / *freq); + buzzer->setAnalogPeriodUs(1'000'000 / *freq); buzzer->setAnalogValue(255); }); @@ -34,7 +34,7 @@ void buzzer_prog() } *freq += p; - buzzer->setAnalogPeriodUs(1000000 / *freq); + buzzer->setAnalogPeriodUs(1'000'000 / *freq); buzzer->setAnalogValue(255); }); @@ -50,7 +50,7 @@ void buzzer_prog() } }); - buzzer->setAnalogPeriodUs(1000000 / *freq); + buzzer->setAnalogPeriodUs(1'000'000 / *freq); buzzer->setAnalogValue(255); while (1) { diff --git a/samples/OOB/compass.h b/samples/OOB/compass.h index fa04596..ee916fb 100644 --- a/samples/OOB/compass.h +++ b/samples/OOB/compass.h @@ -38,9 +38,9 @@ Lis2Data average_measure(unsigned nb_measure) void compass_prog() { - float size = 32; - float cx = 64; - float cy = 64; + float size = 32; + float cx = 64; + float cy = 64; float calib_min_x = std::numeric_limits::max(); float calib_max_x = std::numeric_limits::min(); float calib_min_y = std::numeric_limits::max(); @@ -63,11 +63,11 @@ void compass_prog() Lis2Data magn = average_measure(20); - calib_max_x = std::max(calib_max_x, magn.x); - calib_min_x = std::min(calib_min_x, magn.x); + calib_max_x = std::max(calib_max_x, magn.x); + calib_min_x = std::min(calib_min_x, magn.x); - calib_max_y = std::max(calib_max_y, magn.y); - calib_min_y = std::min(calib_min_y, magn.y); + calib_max_y = std::max(calib_max_y, magn.y); + calib_min_y = std::min(calib_min_y, magn.y); } printf("Calibration:\n\tx: [%.2f, %.2f]\n\ty: [%.2f, %.2f]\n", calib_min_x, calib_max_x, calib_min_y, calib_max_y); @@ -81,16 +81,14 @@ void compass_prog() float x = mapf(magn.x, calib_min_x, calib_max_x, -1, 1); float y = -mapf(magn.y, calib_min_y, calib_max_y, -1, 1); - float angle = std::atan2(y, x); - - - double Acos = cos(angle); - double Asin = sin(angle); - double Bcos = cos(angle - TRI_ANGLE); - double Bsin = sin(angle - TRI_ANGLE); - double Ccos = cos(angle + TRI_ANGLE); - double Csin = sin(angle + TRI_ANGLE); - + float angle = std::atan2(y, x); + + double Acos = cos(angle); + double Asin = sin(angle); + double Bcos = cos(angle - TRI_ANGLE); + double Bsin = sin(angle - TRI_ANGLE); + double Ccos = cos(angle + TRI_ANGLE); + double Csin = sin(angle + TRI_ANGLE); ssd->fill(0x00); ssd->drawCircle(64, 64, 50, false, 0xFF); diff --git a/samples/OOB/oob.cpp b/samples/OOB/oob.cpp index 48fd406..60bbf9c 100644 --- a/samples/OOB/oob.cpp +++ b/samples/OOB/oob.cpp @@ -44,38 +44,38 @@ STM32Pin* led_green = nullptr; STM32Pin* led_blue = nullptr; SSD1327_SPI* ssd = nullptr; -STM32Pin* btnMenu = nullptr; -STM32Pin* btnA = nullptr; -STM32Pin* btnB = nullptr; -STM32Pin* buzzer = nullptr; - -MCP23009E* mcp = nullptr; -HTS221* hts = nullptr; -WSEN_PADS* pres = nullptr; -VL53L1X* tof = nullptr; -ISM330DL* ism = nullptr; -LIS2MDL* lis = nullptr; - -void Demo_OOB(codal::STM32STEAM32_WB55RG& steam32) +STM32Pin* btnMenu = nullptr; +STM32Pin* btnA = nullptr; +STM32Pin* btnB = nullptr; +STM32Pin* buzzer = nullptr; + +MCP23009E* mcp = nullptr; +HTS221* hts = nullptr; +WSEN_PADS* pres = nullptr; +VL53L1X* tof = nullptr; +ISM330DL* ism = nullptr; +LIS2MDL* lis = nullptr; + +void Demo_OOB(codal::STeaMi& steami) { - spi = &steam32.spi1; - cs = &steam32.io.PD_0; - dc = &steam32.io.PB_4; - rst = &steam32.io.PA_12; - ssd = new SSD1327_SPI(*spi, *cs, *dc, *rst, 128, 128); - btnMenu = &steam32.io.PA_0; - btnA = &steam32.io.PA_7; - btnB = &steam32.io.PA_8; - buzzer = &steam32.io.PA_11; - - led_red = &steam32.io.PC_12; - led_green = &steam32.io.PC_11; - led_blue = &steam32.io.PC_10; + spi = &steami.spiExt; + cs = &steami.io.csDisplay; + dc = &steami.io.misoDisplay; + rst = &steami.io.resetDisplay; + ssd = new SSD1327_SPI(*spi, *cs, *dc, *rst, 128, 128); + btnMenu = &steami.io.buttonMenu; + btnA = &steami.io.buttonA; + btnB = &steami.io.buttonB; + buzzer = &steami.io.speaker; + + led_red = &steami.io.ledRed; + led_green = &steami.io.ledGreen; + led_blue = &steami.io.ledBlue; buzzer->setAnalogValue(0); - steam32.serial.init(115200); - steam32.sleep(500); + steami.serial.init(115'200); + steami.sleep(500); printf("Init...\r\n"); @@ -85,33 +85,33 @@ void Demo_OOB(codal::STM32STEAM32_WB55RG& steam32) ssd->show(); printf("Init. MCP23009E...\n"); - mcp = new MCP23009E(steam32.i2c1, 0x40, steam32.io.PB_1, steam32.io.PB_0); + mcp = new MCP23009E(steami.i2cInt, 0x40, steami.io.resetExpander, steami.io.irqExpander); mcp->setup(MCP_GP_RIGHT, MCP_DIR::INPUT); mcp->setup(MCP_GP_BOTTOM, MCP_DIR::INPUT); mcp->setup(MCP_GP_LEFT, MCP_DIR::INPUT); mcp->setup(MCP_GP_UP, MCP_DIR::INPUT); printf("Init. HTS221...\n"); - hts = new HTS221(&steam32.i2c1, 0xBE); + hts = new HTS221(&steami.i2cInt, 0xBE); hts->init(); hts->setOutputRate(codal::HTS221_OUTPUT_RATE::RATE_7HZ); printf("Init. WSEN_PADS...\n"); - pres = new WSEN_PADS(steam32.i2c1, 0xBA); + pres = new WSEN_PADS(steami.i2cInt, 0xBA); pres->init(); printf("Init. VL53L1X...\n"); - tof = new VL53L1X(&steam32.i2c1); + tof = new VL53L1X(&steami.i2cInt); tof->init(); printf("Init. ISM330DL...\n"); - ism = new ISM330DL(&steam32.i2c1); + ism = new ISM330DL(&steami.i2cInt); ism->init(); ism->setAccelerometerODR(ISM_ODR::F_1_66_KHZ); ism->setGyroscopeODR(ISM_ODR::F_208_HZ); printf("Init. LIS2MDL...\n"); - lis = new LIS2MDL(&steam32.i2c1); + lis = new LIS2MDL(&steami.i2cInt); lis->init(); unsigned select_prog = 0; diff --git a/samples/OOB/oob.h b/samples/OOB/oob.h index 9f05865..fb0f788 100644 --- a/samples/OOB/oob.h +++ b/samples/OOB/oob.h @@ -1,8 +1,8 @@ #pragma once -#include "STM32STEAM32_WB55RG.h" +#include "STeaMi.h" #ifndef SAMPLE_MAIN -#define SAMPLE_MAIN Demo_OOB + #define SAMPLE_MAIN Demo_OOB #endif -void Demo_OOB(codal::STM32STEAM32_WB55RG& steam32); \ No newline at end of file +void Demo_OOB(codal::STeaMi& steami); \ No newline at end of file diff --git a/samples/OOB/utils.h b/samples/OOB/utils.h index 2ee2bdb..73db6e5 100644 --- a/samples/OOB/utils.h +++ b/samples/OOB/utils.h @@ -23,8 +23,7 @@ std::string fToStr(float value, unsigned pres) bool click_button(codal::STM32Pin* btn) { if (btn->getDigitalValue() == 0) { - while (btn->getDigitalValue() == 0) - ; + while (btn->getDigitalValue() == 0); return true; } diff --git a/samples/main.cpp b/samples/main.cpp index e96edb8..763af92 100644 --- a/samples/main.cpp +++ b/samples/main.cpp @@ -2,41 +2,41 @@ #include "STeaMi.h" #if defined(BUTTONS_SAMPLE) -#include "ButtonSample.h" + #include "ButtonSample.h" #elif defined(SERIAL_SAMPLE) -#include "SerialSample.h" + #include "SerialSample.h" #elif defined(SIGLE_WIRE_SERIAL_SAMPLE) -#include "SingleWireSerialSample.h" + #include "SingleWireSerialSample.h" #elif defined(SAI_SAMPLE) -#include "SAI_sample.h" + #include "SAI_sample.h" #elif defined(VL53L1X_SAMPLE) -#include "VL53L1X_sample.h" + #include "VL53L1X_sample.h" #elif defined(HTS221_SAMPLE) -#include "HTS221_sample.h" + #include "HTS221_sample.h" #elif defined(WSEN_PADS_SAMPLE) -#include "WSEN-PADS_sample.h" + #include "WSEN-PADS_sample.h" #elif defined(SCANNER_I2C) -#include "ScannerI2C.h" + #include "ScannerI2C.h" #elif defined(OLED_SSD1327) -#include "OLED_SSD1327.h" + #include "OLED_SSD1327.h" #elif defined(APDS9960) -#include "APDS9960_sample.h" + #include "APDS9960_sample.h" #elif defined(BQ27441) -#include "BQ27441_sample.h" + #include "BQ27441_sample.h" #elif defined(RTC_SAMPLE) -#include "RTC_sample.h" + #include "RTC_sample.h" #elif defined(DAPLINK_FLASH) -#include "DapLink_Flash_sample.h" + #include "DapLink_Flash_sample.h" #elif defined(DEMO) -#include "demo_sample.h" + #include "demo_sample.h" #elif defined(FUS_WS_OPERATOR) -#include "FUS_WS_Operator.h" + #include "FUS_WS_Operator.h" #elif defined(BLE_BROADCAST) -#include "BLE_Broadcast_Sample.h" + #include "BLE_Broadcast_Sample.h" #elif defined(OOB) -#include "oob.h" + #include "oob.h" #else -#include "BlinkSample.h" + #include "BlinkSample.h" #endif codal::STeaMi steami;