69 lines
2.2 KiB
C++
69 lines
2.2 KiB
C++
|
|
// uSEQ-CV expander firmware (protocol v2).
|
|||
|
|
//
|
|||
|
|
// Target: uSEQ USEQHARDWARE_EXPANDER_OUT_0_1 — Raspberry Pi Pico (RP2040),
|
|||
|
|
// Arduino-Pico core. I2C slave at USEQ_I2C_ADDR; receives 8 × 11-bit CV values
|
|||
|
|
// from the main board and writes them to PWM. See ../../shared/protocol.h.
|
|||
|
|
#include <Arduino.h>
|
|||
|
|
#include <Wire.h>
|
|||
|
|
#include "protocol.h"
|
|||
|
|
|
|||
|
|
// ─── Pin map (USEQHARDWARE_EXPANDER_OUT_0_1) ────────────────────────────────
|
|||
|
|
constexpr uint8_t PIN_E[USEQ_NUM_EXP_CV] = { 13, 14, 10, 11, 8, 7, 5, 3 };
|
|||
|
|
constexpr uint8_t PIN_E_LED[USEQ_NUM_EXP_CV] = { 15, 20, 17, 12, 9, 6, 2, 0 };
|
|||
|
|
constexpr uint8_t PIN_SDA = 4, PIN_SCL = 1;
|
|||
|
|
|
|||
|
|
volatile uint16_t cvValues[USEQ_NUM_EXP_CV] = {};
|
|||
|
|
volatile bool newFrame = false;
|
|||
|
|
volatile bool doSweep = false;
|
|||
|
|
|
|||
|
|
void onI2CReceive(int numBytes) {
|
|||
|
|
if (numBytes == 1) {
|
|||
|
|
if (Wire.read() == USEQ_SYNC_I2C_IDENTIFY) doSweep = true;
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if (numBytes != USEQ_FRAME_I2C_LEN) {
|
|||
|
|
while (Wire.available()) Wire.read();
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
uint8_t buf[USEQ_FRAME_I2C_LEN];
|
|||
|
|
for (uint8_t i = 0; i < USEQ_FRAME_I2C_LEN; i++) buf[i] = Wire.read();
|
|||
|
|
if (buf[0] != USEQ_SYNC_I2C) return;
|
|||
|
|
if (useq_xor(buf, 0, USEQ_FRAME_I2C_LEN - 2) != buf[USEQ_FRAME_I2C_LEN - 1]) return;
|
|||
|
|
for (uint8_t i = 0; i < USEQ_NUM_EXP_CV; i++) {
|
|||
|
|
uint16_t v = useq_read_u16le(&buf[1 + i * 2]);
|
|||
|
|
cvValues[i] = (v > USEQ_PWM_MAX) ? USEQ_PWM_MAX : v;
|
|||
|
|
}
|
|||
|
|
newFrame = true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void ledSweep() {
|
|||
|
|
for (int i = 0; i < USEQ_NUM_EXP_CV; i++) { analogWrite(PIN_E_LED[i], USEQ_PWM_MAX); delay(40); }
|
|||
|
|
delay(80);
|
|||
|
|
for (int i = USEQ_NUM_EXP_CV - 1; i >= 0; i--) { analogWrite(PIN_E_LED[i], 0); delay(40); }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void setup() {
|
|||
|
|
for (uint8_t i = 0; i < USEQ_NUM_EXP_CV; i++) {
|
|||
|
|
pinMode(PIN_E[i], OUTPUT);
|
|||
|
|
pinMode(PIN_E_LED[i], OUTPUT);
|
|||
|
|
}
|
|||
|
|
analogWriteFreq(100000);
|
|||
|
|
analogWriteRange(USEQ_PWM_MAX);
|
|||
|
|
Wire.setSDA(PIN_SDA);
|
|||
|
|
Wire.setSCL(PIN_SCL);
|
|||
|
|
Wire.begin(USEQ_I2C_ADDR);
|
|||
|
|
Wire.onReceive(onI2CReceive);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void loop() {
|
|||
|
|
if (doSweep) { doSweep = false; ledSweep(); }
|
|||
|
|
if (newFrame) {
|
|||
|
|
newFrame = false;
|
|||
|
|
for (uint8_t i = 0; i < USEQ_NUM_EXP_CV; i++) {
|
|||
|
|
uint16_t v = cvValues[i];
|
|||
|
|
analogWrite(PIN_E[i], v);
|
|||
|
|
analogWrite(PIN_E_LED[i], (uint16_t)(((uint32_t)v * v) >> 11));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|