Fixes and new apps (#30)
- M5 Unit Modules library + M5 Unit Test app - Minor fixes for TodoList, TwoEleven, Snake, Brainfuck and Breakout - Fixed SerialConsole to use the uart controller as it was broken in one of the many updates - Fixed keyboard input in TwoEleven, Breakout, Magic8Ball and Snake - Bluetooth Media Keys app, supports pressing physical keys to trigger the corresponding buttonmatrix button - Epub Reader app
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
#include <UnitMidi.h>
|
||||
#include <tactility/drivers/uart_controller.h>
|
||||
#include <esp_log.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
|
||||
static constexpr auto* TAG = "UnitMidi";
|
||||
static constexpr uint32_t BAUD = 31250;
|
||||
static constexpr uint32_t SEND_TIMEOUT_MS = 20;
|
||||
|
||||
bool UnitMidi::begin(Device* dev) {
|
||||
if (!dev) return false;
|
||||
UartConfig cfg = {
|
||||
BAUD,
|
||||
UART_CONTROLLER_DATA_8_BITS,
|
||||
UART_CONTROLLER_PARITY_DISABLE,
|
||||
UART_CONTROLLER_STOP_BITS_1,
|
||||
};
|
||||
if (uart_controller_set_config(dev, &cfg) != ERROR_NONE) {
|
||||
ESP_LOGW(TAG, "uart_controller_set_config failed");
|
||||
return false;
|
||||
}
|
||||
if (uart_controller_open(dev) != ERROR_NONE) {
|
||||
ESP_LOGW(TAG, "uart_controller_open failed");
|
||||
return false;
|
||||
}
|
||||
dev_ = dev;
|
||||
ready_ = true;
|
||||
// Give SAM2695 time to power up, then reset to known state
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
reset();
|
||||
ESP_LOGI(TAG, "UnitMidi ready at %" PRIu32 " bps", BAUD);
|
||||
return true;
|
||||
}
|
||||
|
||||
void UnitMidi::end() {
|
||||
if (dev_ && ready_) {
|
||||
allNotesOff(0xFF);
|
||||
uart_controller_close(dev_);
|
||||
}
|
||||
ready_ = false;
|
||||
dev_ = nullptr;
|
||||
}
|
||||
|
||||
void UnitMidi::send(const uint8_t* data, size_t len) {
|
||||
if (!ready_ || !dev_) return;
|
||||
uart_controller_write_bytes(dev_, data, len, pdMS_TO_TICKS(SEND_TIMEOUT_MS));
|
||||
}
|
||||
|
||||
void UnitMidi::reset() {
|
||||
uint8_t msg[] = { 0xFF };
|
||||
send(msg, 1);
|
||||
}
|
||||
|
||||
void UnitMidi::noteOn(uint8_t channel, uint8_t note, uint8_t velocity) {
|
||||
uint8_t msg[] = { (uint8_t)(0x90 | (channel & 0x0F)), (uint8_t)(note & 0x7F), (uint8_t)(velocity & 0x7F) };
|
||||
send(msg, 3);
|
||||
}
|
||||
|
||||
void UnitMidi::noteOff(uint8_t channel, uint8_t note) {
|
||||
uint8_t msg[] = { (uint8_t)(0x80 | (channel & 0x0F)), (uint8_t)(note & 0x7F), 0x00 };
|
||||
send(msg, 3);
|
||||
}
|
||||
|
||||
void UnitMidi::programChange(uint8_t channel, uint8_t program) {
|
||||
uint8_t msg[] = { (uint8_t)(0xC0 | (channel & 0x0F)), (uint8_t)(program & 0x7F) };
|
||||
send(msg, 2);
|
||||
}
|
||||
|
||||
void UnitMidi::controlChange(uint8_t channel, uint8_t controller, uint8_t value) {
|
||||
uint8_t msg[] = { (uint8_t)(0xB0 | (channel & 0x0F)), (uint8_t)(controller & 0x7F), (uint8_t)(value & 0x7F) };
|
||||
send(msg, 3);
|
||||
}
|
||||
|
||||
void UnitMidi::pitchBend(uint8_t channel, int16_t value) {
|
||||
// value range -8192..+8191 → offset by 8192, split into 7-bit LSB/MSB
|
||||
uint16_t v = (uint16_t)(value + 8192);
|
||||
uint8_t msg[] = {
|
||||
(uint8_t)(0xE0 | (channel & 0x0F)),
|
||||
(uint8_t)(v & 0x7F),
|
||||
(uint8_t)((v >> 7) & 0x7F),
|
||||
};
|
||||
send(msg, 3);
|
||||
}
|
||||
|
||||
void UnitMidi::allNotesOff(uint8_t channel) {
|
||||
if (channel == 0xFF) {
|
||||
for (uint8_t ch = 0; ch < 16; ch++)
|
||||
controlChange(ch, 123, 0);
|
||||
} else {
|
||||
controlChange(channel, 123, 0);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user