Skip to content
Permalink
721ebf5d3f
Go to file
 
 
Cannot retrieve contributors at this time
402 lines (330 sloc) 9.94 KB
#include "Adafruit_Trellis.h"
#define NUM_TRELLIS (4)
#define NUM_KEYS (NUM_TRELLIS * 16)
Adafruit_Trellis matrixes[] = {
Adafruit_Trellis(),
Adafruit_Trellis(),
Adafruit_Trellis(),
Adafruit_Trellis()
};
Adafruit_TrellisSet trellis = Adafruit_TrellisSet(&matrixes[0], &matrixes[1], &matrixes[2], &matrixes[3]);
String deviceID = "monome";
String serialNum = "m1000000";
unsigned long prevReadTime = 0;
unsigned long prevWriteTime = 0;
static bool ledBuffer[8][8];
// these functions are from Adafruit_UNTZtrument.h
static const uint8_t PROGMEM
i2xy64[] = {
0x00, 0x10, 0x20, 0x30, 0x01, 0x11, 0x21, 0x31,
0x02, 0x12, 0x22, 0x32, 0x03, 0x13, 0x23, 0x33,
0x40, 0x50, 0x60, 0x70, 0x41, 0x51, 0x61, 0x71,
0x42, 0x52, 0x62, 0x72, 0x43, 0x53, 0x63, 0x73,
0x04, 0x14, 0x24, 0x34, 0x05, 0x15, 0x25, 0x35,
0x06, 0x16, 0x26, 0x36, 0x07, 0x17, 0x27, 0x37,
0x44, 0x54, 0x64, 0x74, 0x45, 0x55, 0x65, 0x75,
0x46, 0x56, 0x66, 0x76, 0x47, 0x57, 0x67, 0x77
},
xy2i64[8][8] = {
{ 0, 1, 2, 3, 16, 17, 18, 19 },
{ 4, 5, 6, 7, 20, 21, 22, 23 },
{ 8, 9, 10, 11, 24, 25, 26, 27 },
{ 12, 13, 14, 15, 28, 29, 30, 31 },
{ 32, 33, 34, 35, 48, 49, 50, 51 },
{ 36, 37, 38, 39, 52, 53, 54, 55 },
{ 40, 41, 42, 43, 56, 57, 58, 59 },
{ 44, 45, 46, 47, 60, 61, 62, 63 }
};
uint8_t xy2i(uint8_t x, uint8_t y) {
if (x > 7 || y > 7) {
return 255;
}
return pgm_read_byte(&xy2i64[y][x]);
}
void i2xy(uint8_t i, uint8_t *x, uint8_t *y) {
if (i > NUM_KEYS) {
*x = *y = 255;
return;
}
uint8_t xy = pgm_read_byte(&i2xy64[i]);
*x = xy >> 4;
*y = xy & 15;
}
void setLED(int x, int y, int v) {
if (x >= 0 && x < 8 && y >= 0 && y < 8) {
ledBuffer[x][y] = v;
}
}
void setAllLEDs(int value) {
uint8_t i, j;
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
ledBuffer[i][j] = value;
}
}
}
void turnOffLEDs() {
setAllLEDs(0);
}
void turnOnLEDs() {
setAllLEDs(1);
}
void setup() {
Serial.begin(115200);
// adjust this if x/y makes no sense on your grid
trellis.begin(0x71, 0x70, 0x73, 0x72);
setAllLEDs(0);
}
uint8_t readInt() {
return Serial.read();
}
void writeInt(uint8_t value) {
Serial.write(value);
}
void processSerial() {
uint8_t identifierSent; // command byte sent from controller to matrix
uint8_t deviceAddress; // device address sent from controller
uint8_t dummy; // for reading in data not used by the matrix
uint8_t intensity = 255; // led intensity, ignored
uint8_t readX, readY; // x and y values read from driver
uint8_t i, x, y;
identifierSent = Serial.read(); // get command identifier: first byte of packet is identifier in the form: [(a << 4) + b]
// a = section (ie. system, key-grid, digital, encoder, led grid, tilt)
// b = command (ie. query, enable, led, key, frame)
switch (identifierSent) {
case 0x00:
writeInt((uint8_t)0x00); // system/query response 0x00 -> 0x00
writeInt((uint8_t)0x01); // grids
writeInt((uint8_t)0x01); // one grid
break;
case 0x01:
writeInt((uint8_t)0x01);
for (i = 0; i < 32; i++) { // has to be 32
if (i < deviceID.length()) {
Serial.print(deviceID[i]);
}
else {
Serial.print('\0');
}
}
break;
case 0x02:
for (i = 0; i < 32; i++) {
deviceID[i] = Serial.read();
}
break;
case 0x03:
writeInt((uint8_t)0x02); // system / request grid offsets
// writeInt(0); // n grid?
writeInt((uint8_t)0x00); // x offset
writeInt((uint8_t)0x00); // y offset
break;
case 0x04:
dummy = readInt(); // system / set grid offset
readX = readInt(); // an offset of 8 is valid only for 16 x 8 monome
readY = readInt(); // an offset is invalid for y as it's only 8
break;
case 0x05:
writeInt((uint8_t)0x03); // system / request grid size
writeInt((uint8_t)8);
writeInt((uint8_t)8);
break;
case 0x06:
readX = readInt(); // system / set grid size - ignored
readY = readInt();
break;
case 0x07:
break; // I2C stuff - ignored
case 0x08:
deviceAddress = readInt(); // set addr - ignored
dummy = readInt();
break;
case 0x0F:
writeInt((uint8_t)0x0F); // send serial number
Serial.print(serialNum);
break;
case 0x10:
readX = readInt();
readY = readInt();
setLED(readX, readY, 0);
break;
case 0x11:
readX = readInt();
readY = readInt();
setLED(readX, readY, 1);
break;
case 0x12:
turnOffLEDs();
break;
case 0x13:
turnOnLEDs();
break;
case 0x14:
readX = readInt();
readY = readInt();
if (readY != 0) break; // since we only have 8 LEDs in a column, no offset
for (y = 0; y < 8; y++) { // each i will be a row
intensity = readInt(); // read one byte of 8 bits on/off
for (x = 0; x < 8; x++) { // for 8 LEDs on a row
if ((intensity >> x) & 0x01) { // set LED if the intensity bit is set
setLED(readX + x, y, 1);
}
else {
setLED(readX + x, y, 0);
}
}
}
break;
case 0x15:
readX = readInt(); // led-grid / set row
readY = readInt(); // may be any value
intensity = readInt(); // read one byte of 8 bits on/off
for (i = 0; i < 8; i++) { // for the next 8 lights in row
if ((intensity >> i) & 0x01) { // if intensity bit set, light
setLED(readX + i, readY, 1);
}
else {
setLED(readX + i, readY, 0);
}
}
break;
case 0x16:
readX = readInt(); // led-grid / column set
readY = readInt();
intensity = readInt(); // read one byte of 8 bits on/off
if (readY != 0) break; // we only have 8 lights in a column
for (i = 0; i < 8; i++) { // for the next 8 lights in column
if ((intensity >> i) & 0x01) { // if intensity bit set, light
setLED(readX, i, 1);
}
else {
setLED(readX, i, 0);
}
}
break;
case 0x17:
intensity = readInt(); // intensity stuff - ignored
break;
case 0x18:
readX = readInt(); // led-grid / set LED intensity
readY = readInt(); // read the x and y coordinates
intensity = readInt(); // read the intensity value (0-255, 0x00-0xFF)
if (intensity > 0) {
setLED(readX, readY, 1);
}
else {
setLED(readX, readY, 0);
}
break;
case 0x19: // set all leds
intensity = readInt();
if (intensity > 0) {
turnOnLEDs();
}
else {
turnOffLEDs();
}
case 0x1A: // set 8x8 block
readX = readInt();
readY = readInt();
for (y = 0; y < 8; y++) {
for (x = 0; x < 8; x++) {
if ((x + y) % 2 == 0) { // even bytes, use upper nybble
intensity = readInt();
if (intensity >> 4 & 0x0F) {
setLED(readX + x, y, 1);
}
else {
setLED(readX + x, y, 0);
}
}
else { // odd bytes, use lower nybble
if (intensity & 0x0F) {
setLED(readX + x, y, 1);
}
else {
setLED(readX + x, y, 0);
}
}
}
}
break;
case 0x1B: // set 8x1 row by intensity
readX = readInt();
readY = readInt();
for (x = 0; x < 8; x++) {
intensity = readInt();
if (intensity) {
setLED(readX + x, readY, 1);
}
else {
setLED(readX + x, readY, 0);
}
}
break;
case 0x1C: // set 1x8 column by intensity
readX = readInt();
readY = readInt();
for (y = 0; y < 8; y++) {
intensity = readInt();
if (intensity) {
setLED(readX, readY + y, 1);
}
else {
setLED(readX, readY + y, 0);
}
}
break;
default:
break;
}
return;
}
void readKeys() {
uint8_t x, y;
for (uint8_t i = 0; i < NUM_KEYS; i++) {
if (trellis.justPressed(i)) {
i2xy(i, &x, &y);
writeInt(0x21);
writeInt(x);
writeInt(y);
}
else if (trellis.justReleased(i)) {
i2xy(i, &x, &y);
writeInt(0x20);
writeInt(x);
writeInt(y);
}
}
}
void loop() {
unsigned long now = millis();
if (Serial.available() > 0) {
do {
processSerial();
} while (Serial.available() > 16);
}
else if (now - prevWriteTime >= 10) {
// set trellis internal matrix from ledBuffer
for (uint8_t x = 0; x < 8; x++) {
for (uint8_t y = 0; y < 8; y++) {
if (ledBuffer[x][y]) {
trellis.setLED(xy2i(x, y));
}
else {
trellis.clrLED(xy2i(x, y));
}
}
}
// update display every ~10ms
trellis.writeDisplay();
prevWriteTime = now;
}
else if (now - prevReadTime >= 30) {
// read switches not more often than every ~30ms - hardware requirement
if (trellis.readSwitches()) {
readKeys();
}
prevReadTime = now;
}
}