Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 110 additions & 13 deletions src/apps/tests/scan_i2c/scan_i2c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,33 +5,135 @@

#include "keira/utils/string.h"

#if LILKA_VERSION >= 2
static constexpr uint32_t I2C_FREQUENCIES[] = {100000, 400000, 1000000};
static constexpr uint8_t I2C_FREQUENCY_COUNT = sizeof(I2C_FREQUENCIES) / sizeof(I2C_FREQUENCIES[0]);

struct ScanI2CPin {
const char* name;
uint8_t gpio;
};

// Extension header pins usable for I2C (TX/RX are free: console runs over USB CDC)
static const ScanI2CPin I2C_PINS[] = {
{"P3", LILKA_P3},
{"P4", LILKA_P4},
{"P5", LILKA_P5},
{"P6", LILKA_P6},
{"P7", LILKA_P7},
{"P8", LILKA_P8},
{"TX", TX},
{"RX", RX},
};
static constexpr uint8_t I2C_PIN_COUNT = sizeof(I2C_PINS) / sizeof(I2C_PINS[0]);

enum ScanI2CMenuItem {
SCAN_I2C_MENU_SDA,
SCAN_I2C_MENU_SCL,
SCAN_I2C_MENU_FREQUENCY,
SCAN_I2C_MENU_SCAN,
SCAN_I2C_MENU_BACK,
};
#endif

ScanI2CApp::ScanI2CApp() : App("I2C Scanner") {
}

void ScanI2CApp::run() {
#if LILKA_VERSION >= 2
lilka::Menu menu("I2C");
menu.addActivationButton(K_BTN_BACK);

while (true) {
int16_t cursor = menu.getCursor();
menu.clearItems();
menu.addItem(
K_S_I2C_SCANNER_SDA,
0,
lilka::colors::White,
StringFormat("%s (GPIO %d)", I2C_PINS[sdaIndex].name, I2C_PINS[sdaIndex].gpio)
);
menu.addItem(
K_S_I2C_SCANNER_SCL,
0,
lilka::colors::White,
StringFormat("%s (GPIO %d)", I2C_PINS[sclIndex].name, I2C_PINS[sclIndex].gpio)
);
menu.addItem(
K_S_I2C_SCANNER_FREQUENCY,
0,
lilka::colors::White,
StringFormat("%d kHz", static_cast<int>(I2C_FREQUENCIES[freqIndex] / 1000))
);
menu.addItem(K_S_I2C_SCANNER_SCAN);
menu.addItem(K_S_MENU_BACK);
menu.setCursor(cursor);

while (!menu.isFinished()) {
menu.update();
menu.draw(canvas);
queueDraw();
}

if (menu.getButton() == K_BTN_BACK) return;

switch (menu.getCursor()) {
case SCAN_I2C_MENU_SDA:
sdaIndex = nextPinIndex(sdaIndex, sclIndex);
break;
case SCAN_I2C_MENU_SCL:
sclIndex = nextPinIndex(sclIndex, sdaIndex);
break;
case SCAN_I2C_MENU_FREQUENCY:
freqIndex = (freqIndex + 1) % I2C_FREQUENCY_COUNT;
break;
case SCAN_I2C_MENU_SCAN:
scan();
break;
default:
return;
}
}
#else
alert(K_S_ERROR, K_S_LILKA_V2_OR_HIGHER_REQUIRED);
#endif
}

uint8_t ScanI2CApp::nextPinIndex(uint8_t current, uint8_t other) const {
#if LILKA_VERSION >= 2
uint8_t next = (current + 1) % I2C_PIN_COUNT;
if (next == other) next = (next + 1) % I2C_PIN_COUNT;
return next;
#else
return current;
#endif
}

void ScanI2CApp::scan() {
#if LILKA_VERSION >= 2
const uint8_t sda = I2C_PINS[sdaIndex].gpio;
const uint8_t scl = I2C_PINS[sclIndex].gpio;
const uint32_t freq = I2C_FREQUENCIES[freqIndex];

lilka::Canvas buffer(canvas->width(), canvas->height());
buffer.begin();
buffer.fillScreen(0);
buffer.setFont(FONT_9x15);

buffer.fillScreen(lilka::colors::Black);
buffer.setTextBound(4, 0, canvas->width() - 8, canvas->height());
buffer.setCursor(4, 20);

buffer.println(StringFormat(K_S_I2C_INIT_ABOUT, LILKA_P3, LILKA_P4));
Wire.begin(LILKA_P3, LILKA_P4, 100000);
buffer.println(StringFormat(K_S_I2C_INIT_ABOUT, sda, scl));
Wire.begin(sda, scl, freq);
buffer.println(K_S_I2C_SCANNER_SCAN_START);
canvas->drawCanvas(&buffer);
queueDraw();

uint8_t found = 0;
for (uint16_t address = 1; address <= 127; address++) {
// Wire.requestFrom(addr, 0, true);
Wire.beginTransmission(address);
if (Wire.endTransmission() == 0) {
buffer.printf("%02X", address);
// lilka::display
found++;
} else {
buffer.print(".");
Expand All @@ -48,15 +150,10 @@ void ScanI2CApp::run() {

Wire.end();

while (!lilka::controller.getState().a.justPressed) {
while (true) {
lilka::State state = lilka::controller.getState();
if (state.a.justPressed || state.b.justPressed) break;
taskYIELD();
}
#else
lilka::Alert alert(K_S_ERROR, K_S_LILKA_V2_OR_HIGHER_REQUIRED);
alert.draw(canvas);
queueDraw();
while (!alert.isFinished()) {
alert.update();
}
#endif
}
7 changes: 7 additions & 0 deletions src/apps/tests/scan_i2c/scan_i2c.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,12 @@ class ScanI2CApp : public App {
ScanI2CApp();

private:
// Indices into I2C_PINS / I2C_FREQUENCIES
uint8_t sdaIndex = 0; // LILKA_P3
uint8_t sclIndex = 1; // LILKA_P4
uint8_t freqIndex = 0;

void run() override;
void scan();
uint8_t nextPinIndex(uint8_t current, uint8_t other) const;
};
4 changes: 4 additions & 0 deletions src/keira/localizations/lang_en.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,10 @@
#define K_S_I2C_SCANNER_SCAN_START "Starting I2C scan..."
#define K_S_I2C_SCANNER_SCAN_DONE "I2C scan done."
#define K_S_I2C_SCANNER_DEVICES_FOUND "Found %d devices."
#define K_S_I2C_SCANNER_SDA "SDA"
#define K_S_I2C_SCANNER_SCL "SCL"
#define K_S_I2C_SCANNER_FREQUENCY "Frequency"
#define K_S_I2C_SCANNER_SCAN "Scan"
///////////////////////////////////////////////////////////////////////////////////////////////////////

// apps/demos/transform.cpp ///////////////////////////////////////////////////////////////////////////
Expand Down
4 changes: 4 additions & 0 deletions src/keira/localizations/lang_uk.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,10 @@
#define K_S_I2C_SCANNER_SCAN_START "Starting I2C scan..."
#define K_S_I2C_SCANNER_SCAN_DONE "I2C scan done."
#define K_S_I2C_SCANNER_DEVICES_FOUND "Found %d devices."
#define K_S_I2C_SCANNER_SDA "SDA"
#define K_S_I2C_SCANNER_SCL "SCL"
#define K_S_I2C_SCANNER_FREQUENCY "Частота"
#define K_S_I2C_SCANNER_SCAN "Сканувати"
///////////////////////////////////////////////////////////////////////////////////////////////////////

// apps/demos/transform.cpp ///////////////////////////////////////////////////////////////////////////
Expand Down
Loading