137 lines
3.8 KiB
C++
137 lines
3.8 KiB
C++
|
|
#include "pico/stdlib.h"
|
||
|
|
#include "pico/util/queue.h"
|
||
|
|
#include "hardware/pwm.h"
|
||
|
|
#include "DmxOutput.h"
|
||
|
|
|
||
|
|
DmxOutput dmx_out;
|
||
|
|
|
||
|
|
/* Tell C++ to treat these as C libraries */
|
||
|
|
extern "C" {
|
||
|
|
#include "tusb.h"
|
||
|
|
}
|
||
|
|
|
||
|
|
#define LED_PIN 25
|
||
|
|
#define RS485_DE_RE_PIN 6
|
||
|
|
#define DMX_TX_PIN 4
|
||
|
|
#define FIFO_SIZE 64
|
||
|
|
#define DMX_UNIVERSE_SIZE 512
|
||
|
|
|
||
|
|
typedef struct {
|
||
|
|
uint8_t channel;
|
||
|
|
uint8_t note;
|
||
|
|
uint8_t velocity;
|
||
|
|
} midi_note_msg_t;
|
||
|
|
|
||
|
|
queue_t midi_fifo;
|
||
|
|
uint8_t dmx_buffer[DMX_UNIVERSE_SIZE + 1]; /* +1 for the Start Code (0x00) */
|
||
|
|
|
||
|
|
void setup_hardware() {
|
||
|
|
/* Initial GPIO Setup */
|
||
|
|
gpio_init(LED_PIN);
|
||
|
|
gpio_set_dir(LED_PIN, GPIO_OUT);
|
||
|
|
gpio_init(RS485_DE_RE_PIN);
|
||
|
|
gpio_set_dir(RS485_DE_RE_PIN, GPIO_OUT);
|
||
|
|
|
||
|
|
/* Set GPIO6 - RS485 DE/RE pin high */
|
||
|
|
gpio_put(RS485_DE_RE_PIN, 1);
|
||
|
|
|
||
|
|
/* Perform 3 rapid blinks to signal a fresh boot */
|
||
|
|
for (int i = 0; i < 3; i++) {
|
||
|
|
gpio_put(LED_PIN, 1);
|
||
|
|
sleep_ms(50);
|
||
|
|
gpio_put(LED_PIN, 0);
|
||
|
|
sleep_ms(50);
|
||
|
|
}
|
||
|
|
|
||
|
|
sleep_ms(200);
|
||
|
|
|
||
|
|
/* PWM Setup for MIDI Dimming */
|
||
|
|
gpio_set_function(LED_PIN, GPIO_FUNC_PWM);
|
||
|
|
uint slice_num = pwm_gpio_to_slice_num(LED_PIN);
|
||
|
|
pwm_set_wrap(slice_num, 127);
|
||
|
|
pwm_set_enabled(slice_num, true);
|
||
|
|
|
||
|
|
/* Smooth "Welcome" fade-in and out */
|
||
|
|
for (int i = 0; i <= 127; i++) {
|
||
|
|
pwm_set_gpio_level(LED_PIN, i);
|
||
|
|
sleep_ms(3);
|
||
|
|
}
|
||
|
|
for (int i = 127; i >= 0; i--) {
|
||
|
|
pwm_set_gpio_level(LED_PIN, i);
|
||
|
|
sleep_ms(3);
|
||
|
|
}
|
||
|
|
|
||
|
|
dmx_out.begin(DMX_TX_PIN); // Initialize DMX on GP6 using PIO
|
||
|
|
for(int i=0; i<=DMX_UNIVERSE_SIZE; i++) dmx_buffer[i] = 0;
|
||
|
|
|
||
|
|
/* Initialise FIFO */
|
||
|
|
queue_init(&midi_fifo, sizeof(midi_note_msg_t), FIFO_SIZE);
|
||
|
|
|
||
|
|
/* Reset DMX */
|
||
|
|
dmx_buffer[0x01] = 0x00;
|
||
|
|
dmx_buffer[0x02] = 0x00;
|
||
|
|
dmx_buffer[0x03] = 0x00;
|
||
|
|
dmx_buffer[0x04] = 0x00;
|
||
|
|
dmx_out.write(dmx_buffer, DMX_UNIVERSE_SIZE + 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
int main() {
|
||
|
|
/* Call hardware setup (including splash) before USB init */
|
||
|
|
setup_hardware();
|
||
|
|
tusb_init();
|
||
|
|
|
||
|
|
while (1) {
|
||
|
|
tud_task();
|
||
|
|
|
||
|
|
/* Capture (USB -> PWM LED -> FIFO) */
|
||
|
|
if (tud_midi_available()) {
|
||
|
|
uint8_t packet[4];
|
||
|
|
if (tud_midi_packet_read(packet)) {
|
||
|
|
uint8_t note_on_off = packet[1];
|
||
|
|
uint8_t note = packet[2];
|
||
|
|
uint8_t velocity = packet[3];
|
||
|
|
|
||
|
|
/*If note on... */
|
||
|
|
if ((note_on_off & 0xF0) == 0x90) {
|
||
|
|
/* Add to FIFO for DMX processing */
|
||
|
|
midi_note_msg_t msg = {
|
||
|
|
.channel = (uint8_t)((note_on_off & 0x0F) + 1),
|
||
|
|
.note = note,
|
||
|
|
.velocity = velocity
|
||
|
|
};
|
||
|
|
queue_try_add(&midi_fifo, &msg);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*If note off... */
|
||
|
|
if ((note_on_off & 0xF0) == 0x80) {
|
||
|
|
/* Add to FIFO for DMX processing */
|
||
|
|
midi_note_msg_t msg = {
|
||
|
|
.channel = (uint8_t)((note_on_off & 0x0F) + 1),
|
||
|
|
.note = note,
|
||
|
|
.velocity = 0x00
|
||
|
|
};
|
||
|
|
queue_try_add(&midi_fifo, &msg);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
midi_note_msg_t next_msg;
|
||
|
|
if (queue_try_remove(&midi_fifo, &next_msg)) {
|
||
|
|
/* Map MIDI note Number to DMX Channel */
|
||
|
|
/* Centred around middle C (0x3C) */
|
||
|
|
next_msg.note = next_msg.note - 0x3C;
|
||
|
|
|
||
|
|
if (next_msg.note < DMX_UNIVERSE_SIZE) {
|
||
|
|
/* MIDI values are 0-127, DMX values are 0-255 */
|
||
|
|
/* Shift to scale the brightness */
|
||
|
|
dmx_buffer[next_msg.note] = next_msg.velocity << 1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!dmx_out.busy()) {
|
||
|
|
dmx_out.write(dmx_buffer, DMX_UNIVERSE_SIZE + 1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
}
|