Due to high demand, expect some shipping delays at this time - orders may not ship for up to 2-3 business days.
0

Trellis 40h protocol
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Trellis 40h protocol

by brianlight on Fri Dec 27, 2013 1:47 am

Has anyone started working on implementing the Monome 40h protocol for trellis + Arduino?

brianlight
 
Posts: 38
Joined: Mon Dec 23, 2013 9:52 pm

Re: Trellis 40h protocol

by brian2000 on Fri Dec 27, 2013 10:53 am

Sounds like a superb use of Trellis and Arduino.

I think most of the hard stuff has already been solved with the Arduinome project (http://sourceforge.net/projects/arduinome/)
Anything you would need to do probably revolves around forking the arduinome code to work with trellis - at least that's where I would start.

This page has a bunch of monome & arduinome links:
http://monome.org/docs/tech:ports:arduino

brian2000
 
Posts: 1
Joined: Fri Dec 27, 2013 10:45 am

Re: Trellis 40h protocol

by brianlight on Fri Dec 27, 2013 6:06 pm

Yes I've been looking at the arduinome firmware as a starting point I do not have a windows based machine so I'm attempting to write a program to send some test button presses to serial-pyio http://monome.org/docs/app:serial-pyio Using my Arduino Micro I'm not able establish serial communication between this application an my Arduino micro I believe I need to change the Device ID or serial for the micro so that it's seen as a monome or arduinome http://flipmu.com/work/arduinome/instru ... al-number/ I'm hesitant to try these steps because I do not have a mac or windows based machine. I do have a pc running ubuntu an a Raspberry Pi.

brianlight
 
Posts: 38
Joined: Mon Dec 23, 2013 9:52 pm

Re: Trellis 40h protocol

by brianlight on Sat Jan 25, 2014 5:17 am

I was able to get serial-pyio svn up and running on my raspberry pi and was able to detect my Arduino Micro as a monome over serial by editing the device detector file so it looks for a serial connection over ttyACM. I was also able to get presses working, having serial-pyio control the trellis LEDs is still a work in progress.

Code: Select all | TOGGLE FULL SIZE
void checkButtons() {
  if (trellis.readSwitches()) {
    for (uint8_t i=0; i<numKeys; i++) {
      if (trellis.justPressed(i)) {
        int s = 1;
        TrellisToXY(i, TileOffsets, &xVal, &yVal);
        Serial.write((0 << 4) | (s & 15));
        Serial.write((yVal << 4) | (xVal & 15));
      }
      if (trellis.justReleased(i)) {
        int s = 0;
        TrellisToXY(i, TileOffsets, &xVal, &yVal);
        Serial.write((0 << 4) | (s & 15));
        Serial.write((yVal << 4) | (xVal & 15));

      }
    }
  }
}
Last edited by brianlight on Sat Apr 12, 2014 12:47 am, edited 1 time in total.

brianlight
 
Posts: 38
Joined: Mon Dec 23, 2013 9:52 pm

Re: Trellis 40h protocol

by brianlight on Mon Jan 27, 2014 3:55 am

I had come across a unique monome clone while browsing monome projects between phone calls at work(Technical Support) Mikes Econo Monome http://www.thebox.myzen.co.uk/Hardware/Econo_Monome.htmlI had been looking over various firmware this one was commented very well.. & I stumble around with programming, but with just a few changes to mikes firmware I was able to have my Raspi sending serial data using serial-pyio to my Arduino Micro & displaying serial-pyio example animation programs to light things up its late and I've been staring at a computer screen long enough so I didn't edit the keypress functionality in Mikes firmware so it's appropriate for the Trellis I'll most likely get that rolling tomorrow. 01.27.14
Code: Select all | TOGGLE FULL SIZE
#include <Wire.h>
#include "Adafruit_Trellis.h"

Adafruit_Trellis matrix0 = Adafruit_Trellis();
Adafruit_Trellis matrix1 = Adafruit_Trellis();
Adafruit_Trellis matrix2 = Adafruit_Trellis();
Adafruit_Trellis matrix3 = Adafruit_Trellis();

Adafruit_TrellisSet trellis =  Adafruit_TrellisSet(&matrix0, &matrix1, &matrix2, &matrix3);

#define NUMTRELLIS 4

#define numKeys (NUMTRELLIS * 16)
int  ShutdownModeVal, address, command=0 ;
boolean ShutdownModeChange = false, WaitingCommand = true;
byte byte0, byte1, row = 0;
byte keyState[8];
long nextRefresh;

int chessboard[8][8] = {
  {16, 17, 18, 19, 0, 1, 2, 3},
  {20, 21, 22, 23, 4, 5, 6, 7},
  {24, 25, 26, 27, 8, 9, 10, 11},
  {28, 29, 30, 31, 12, 13, 14, 15},
  {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}
};

#define INTPIN 5

void setup() {
  Serial.begin(9600);
  Serial.println("Trellis Hello World :-)");
 
    pinMode(INTPIN, INPUT);
  digitalWrite(INTPIN, HIGH);
 
   trellis.begin(0x70, 0x71, 0x72, 0x73);
 
  for (uint8_t i=0; i<8; i++) {
    for (uint8_t j=0; j<8; j++) {
      trellis.setLED(chessboard[i][j]);
      trellis.writeDisplay();
      delay(50);
    }
  } 

 
  for (uint8_t i=0; i<numKeys; i++) {
    trellis.clrLED(i);
  }
  trellis.writeDisplay();
}
void onLED( byte x, byte y) {
   x = 7 - x;  // swap x axis to componsate for the position of the USB connector
   y = 7 - y;  // swap y axis to componsate for the position of the USB connector
   byte xMask = 1 << x;
   trellis.setLED(chessboard[x][y]);
   trellis.writeDisplay();
 }
 
 void offLED( byte x, byte y) {
   x = 7 - x;  // swap x axis to componsate for the position of the USB connector
   y = 7 - y;  // swap y axis to componsate for the position of the USB connector
   byte xMask = (1 << x) ^ 0xff;
   trellis.clrLED(chessboard[x][y]);
   trellis.writeDisplay();
 }
 void clearRows() {
  for(byte y=0; y<8; y++) chessboard[8][y] =  0;
}

void setRows() {
   for(byte y=0; y<8; y++) chessboard[8][y] =  0xff;
}

void checkSerial() {
  byte x,y,state;
  do
  {
    if (Serial.available()){
      if (WaitingCommand){       // command is the first byte of the two byte command
        byte0 = Serial.read();
        command = byte0 >> 4;
        WaitingCommand = false;

        switch(command)  // do one byte commands
        {
         case 9: // clear command
         if((byte0 & 1) ==0) clearRows(); else setRows();
        WaitingCommand = true; // next byte is a new command
        break;
        }
       
       if((command > 9) || (command < 2))  WaitingCommand = true; // command outside range so must be an error     
      }

      else
      {
        WaitingCommand = true;    // the next byte is the first byte of the next command
        byte1 = Serial.read();    // read the second byte of this command

        switch(command){

        case 2:  // LED command
          state = byte0 & 0x0f;   // is the command for on or off
           x =  ((byte1 >> 4) & 0x07);  // mask so we don't go over the 8 by 8 grid
           y =  ((byte1 & 15) & 0x07);

          if (state == 0){
            offLED(x,y);
          }
          else {
          onLED(x,y);
          }
         break;
         
        case 3:   // led intensity command
           break;
        case 4:  // led test command
          if( (byte1 & 1) == 0) { setRows(); } else { clearRows(); }       
          break;
        case 5:  // enable ADC command - but we don't do this
          break;
        case 6: // shutdown command - not sure what the monome is expected to do here
          ShutdownModeChange = true;
          ShutdownModeVal= byte1 & 15;
          break;
        case 7:  // led row command
          y = byte0 & 0x07; // mask this value so we don't write to an invalid address.
          x = 0;
          for(byte i = 0x1; i !=0x0; i <<= 1 ){
          if( (i & byte1) != 0) { onLED(x,y);} else  { offLED(x,y);}
          x++;
          }
          break;
         
        case 8:  // coloum command
          x = byte0 & 0x07; // mask this value so we don't write to an invalid address.
          y = 0;
           for(byte i = 0x1; i !=0x0; i <<= 1 ){
          if( (i & byte1) != 0) { onLED(x,y); } else  { offLED(x,y);}
          y++;
          }
          break;
          default:
          onLED(7,7);
          break;
                   
        } // end switch(command)
      } // end of else in if(WaitingCommand)
    } // end of if(Serial.available();
  } // end of do
  while (Serial.available() > 8);  // keep on going if we have a lot of commands stacked up
}
 
void loop() {
checkSerial();
}

brianlight
 
Posts: 38
Joined: Mon Dec 23, 2013 9:52 pm

Re: Trellis 40h protocol

by tmpo on Tue Feb 04, 2014 6:18 am

Hey brainlight,
have you made any progress? I'm trying to do the same as you, but I can't get the buttons to work with Mikes Econo Monome Code. LEDs works fine though...
tmpo
 
Posts: 1
Joined: Wed Jan 29, 2014 10:24 pm

Re: Trellis 40h protocol

by brianlight on Tue Feb 04, 2014 10:03 pm

I have not... I started experimenting with the arduino switch statement. it's going to look ugly though I'm not sure if this is the best way to handle button presses..
Code: Select all | TOGGLE FULL SIZE
if (trellis.readSwitches()) {
      // go through every button
      for (uint8_t i=0; i<numKeys; i++) {
        // if it was pressed...
if (trellis.justPressed(i)) {
switch(i);
case 16:
      x=0; y=0;
      break;
    case 17:
     x=0; y=1;
     break;
*// create a case statment 64 times??? going to look ugly.

  }
//Serial x y press goes here       

 }
      }

brianlight
 
Posts: 38
Joined: Mon Dec 23, 2013 9:52 pm

Re: Trellis 40h protocol

by kirkwoodwest on Mon Feb 10, 2014 1:28 am

You should be able to calculate x and y position easily if you know the column count of your trellis.

Code: Select all | TOGGLE FULL SIZE
column_count = 4;
if (trellis.justPressed(i)) {
x = i % column_count;
y = floor( i / column_count);


I'm curious where you are at with making the 40h protocol to work? what are you working with as your base code?
---------------------------------------------------------
bling it.
kirkwoodwest
 
Posts: 9
Joined: Thu Jan 02, 2014 8:18 pm

Re: Trellis 40h protocol

by brianlight on Wed Feb 12, 2014 5:02 pm

The above posted code will only work with one Trellis. When you link multiple Trellis and individually address each board.
you get button press matrix that looks like the following:

Trellis 1: Trellis 2:
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
Trellis 3: Trellis 4:
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

brianlight
 
Posts: 38
Joined: Mon Dec 23, 2013 9:52 pm

Re: Trellis 40h protocol

by brianlight on Thu Feb 13, 2014 1:20 am

Thought that I should post a video of what I have working so far.
https://www.youtube.com/watch?v=w9Z4UQhn0vQ&feature=youtube_gdata_player

brianlight
 
Posts: 38
Joined: Mon Dec 23, 2013 9:52 pm

Re: Trellis 40h protocol

by brianlight on Mon Mar 31, 2014 1:26 am

Here we go button presses work at this point. but................ not very nicely need debouncing. only known Monome Serial Bridge that is working at this time is Serial-Pyio on windows and tested also in Linux on my raspberry pi device detector source for Serial-Pyio was modified to look for devices under ttyACM. On a windows based machine it should be as simple as adding an Arduinome device in Serial-Pyio under whatever COM port it's located on in my case COM5 this sketch also requires the Trellis X/Y Library located here This Sketch needs Trellis X/Y library to compile -----> http://forums.adafruit.com/viewtopic.php?f=47&t=51444&p=259870&hilit=Trellis#p259870

A short video running Monome Tetris MAX/MSP runtime required
http://youtu.be/2jahDJ9xjj8


Code: Select all | TOGGLE FULL SIZE
/***************************************************
 * This is an implementation of the 40h Protocol used by the Monome
 * ----> http://monome.org
 * Large portions of this sketch were taken from www.thebox.myzen.co.uk Econome Arduinome 8x8
 *-->http://www.thebox.myzen.co.uk
 * Brian Lightfoot
 * 03.21.2014
 * brianlightfoot at gmail dot com
 * www.thebox.myzen.co.uk
 *
 *
 * Designed specifically to work with the Adafruit Trellis
 * ----> https://www.adafruit.com/products/1616
 * ----> https://www.adafruit.com/products/1611
 * This Sketch needs Trellis X/Y library to compile -----> http://forums.adafruit.com/viewtopic.php?f=47&t=51444&p=259870 hilit=Trellis#p259870
 *
 *
 * Currently only works with Serial-pyio http://sourceforge.net/p/serial-pyio/git/ci/master/tree/ 
 * Has been tested on the Raspberry Pi running Raspbian & on the a windows based machine running Windows XP
 *
 * TODO:
 *
 * Button's need debouncing ***Priority #1***
 * Add accelerometer support for tilt control.
 * serialosc support ----> http://monome.org/docs/app:serialosc
 ****************************************************/



#include <Wire.h>
#include <Adafruit_Trellis.h>
#include <Adafruit_Trellis_XY.h>


Adafruit_Trellis matrix0 = Adafruit_Trellis();
Adafruit_Trellis matrix1 = Adafruit_Trellis();
Adafruit_Trellis matrix2 = Adafruit_Trellis();
Adafruit_Trellis matrix3 = Adafruit_Trellis();

Adafruit_TrellisSet trellis =  Adafruit_TrellisSet(&matrix0, &matrix1, &matrix2, &matrix3);

#define NUMTRELLIS 4

#define numKeys (NUMTRELLIS * 16)

#define INTPIN A2

//-----------------------------------------------------------
// define offsets for 4X4 Tiles
struct TileOffsets TileOffsets = {
  {
    0, 4, 0, 4, 0, 0, 0, 0               }
  ,
  {
    0, 0, 4, 4, 0 ,0, 0, 0               }
};

uint8_t xVal;
uint8_t yVal;
uint8_t xyTrellisID;


int  ShutdownModeVal, address, command=0 ;
boolean ShutdownModeChange = false, WaitingCommand = true;
byte byte0, byte1, row = 0;
byte keyState[8];
byte x;
byte y;
long nextRefresh;

int chessboard[8][8] = {
  {
    12, 8, 4, 0, 44, 40, 36, 32              }
  ,
  {
    13, 9, 5, 1, 45, 41, 37, 33              }
  ,
  {
    14, 10, 6, 2, 46, 42, 38, 34              }
  ,
  {
    15, 11, 7, 3, 47, 43, 39, 35              }
  ,
  {
    28, 24, 20, 16, 60, 56, 52, 48              }
  ,
  {
    29, 25, 21, 17, 61, 57, 53, 49              }
  ,
  {
    30, 26, 22, 18, 62, 58, 54, 50              }
  ,
  {
    31, 27, 23, 19, 63, 59, 55, 51              }
};

void setup() {
  Serial.begin(115200);

  pinMode(INTPIN, INPUT);
  digitalWrite(INTPIN, HIGH);

  trellis.begin(0x72, 0x73, 0x70, 0x71);

  for (uint8_t i=0; i<8; i++) {
    for (uint8_t j=0; j<8; j++) {
      trellis.setBrightness(j);
      trellis.setLED(chessboard[i][j]);
      trellis.writeDisplay();
      delay(50);
    }
    trellis.setBrightness(1);
  } 


  for (uint8_t i=0; i<numKeys; i++) {
    trellis.clrLED(i);
  }
  trellis.writeDisplay();
}
void onLED( byte x, byte y) {
  byte xMask = 1 << x;
  trellis.setLED(chessboard[y][x]);
}

void offLED( byte x, byte y) {
  byte xMask = (1 << x) ^ 0xff;
  trellis.clrLED(chessboard[y][x]);
}
void clearRows() {
  for(byte y=0; y<8; y++) chessboard[8][y] =  0;
}

void setRows() {
  for(byte y=0; y<8; y++) chessboard[8][y] =  0xff;
}

void checkSerial() {
  byte x,y,state;
  do
  {
    if (Serial.available()){
      if (WaitingCommand){       // command is the first byte of the two byte command
        byte0 = Serial.read();
        command = byte0 >> 4;
        WaitingCommand = false;

        switch(command)  // do one byte commands
        {
        case 9: // clear command
          if((byte0 & 1) ==0) clearRows();
          else setRows();
          WaitingCommand = true; // next byte is a new command
          break;
        }

        if((command > 9) || (command < 2))  WaitingCommand = true; // command outside range so must be an error     
      }

      else
      {
        WaitingCommand = true;    // the next byte is the first byte of the next command
        byte1 = Serial.read();    // read the second byte of this command

          switch(command){

        case 2:  // LED command
          state = byte0 & 0x0f;   // is the command for on or off
          x =  ((byte1 >> 4) & 0x07);  // mask so we don't go over the 8 by 8 grid
          y =  ((byte1 & 15) & 0x07);

          if (state == 0){
            offLED(x,y);
          }
          else {
            onLED(x,y);
          }
          break;

        case 3:   // led intensity command
          break;
        case 4:  // led test command
          if( (byte1 & 1) == 0) {
            setRows();
          }
          else {
            clearRows();
          }       
          break;
        case 5:  // enable ADC command - but we don't do this
          break;
        case 6: // shutdown command - not sure what the monome is expected to do here
          ShutdownModeChange = true;
          ShutdownModeVal= byte1 & 15;
          break;
        case 7:  // led row command
          y = byte0 & 0x07; // mask this value so we don't write to an invalid address.
          x = 0;
          for(byte i = 0x1; i !=0x0; i <<= 1 ){
            if( (i & byte1) != 0) {
              onLED(x,y);
            }
            else  {
              offLED(x,y);
            }
            x++;
          }
          break;

        case 8:  // coloum command
          x = byte0 & 0x07; // mask this value so we don't write to an invalid address.
          y = 0;
          for(byte i = 0x1; i !=0x0; i <<= 1 ){
            if( (i & byte1) != 0) {
              onLED(x,y);
            }
            else  {
              offLED(x,y);
            }
            y++;
          }
          break;
        default:
          onLED(7,7);
          break;

        } // end switch(command)
      } // end of else in if(WaitingCommand)
    } // end of if(Serial.available();
  } // end of do
  while (Serial.available() > 8);  // keep on going if we have a lot of commands stacked up
}

void checkButtons() {
  if (trellis.readSwitches()) {
    for (uint8_t i=0; i<numKeys; i++) {
      if (trellis.justPressed(i)) {
        int s = 1;
        TrellisToXY(i, TileOffsets, &xVal, &yVal);
        Serial.write((0 << 4) | (s & 15));
        Serial.write((yVal << 4) | (xVal & 15));
      }
      if (trellis.justReleased(i)) {
        int s = 0;
        TrellisToXY(i, TileOffsets, &xVal, &yVal);
        Serial.write((0 << 4) | (s & 15));
        Serial.write((yVal << 4) | (xVal & 15));

      }
    }
  }
}

void loop() {
  delay(30);
  checkButtons();
  checkSerial();
  trellis.writeDisplay();
}


ADC Support added current Sketch can be found here
https://codebender.cc/sketch:32798

brianlight
 
Posts: 38
Joined: Mon Dec 23, 2013 9:52 pm

Re: Trellis 40h protocol

by brianlight on Sat Apr 12, 2014 2:50 am

I've been using serial-pyio to handle serial communications from: and to: the teensy & have been able to use this on both Linux on windows. On windows by just selecting the correct teensy com port & on linux by slightly modifying the python code to look for my device in the right place ttyACM0



but... I would like to utilize serialosc mostly because all modern monome apps are now designed to work with this newish serial to osc bridge. I've also noticed that both serialosc and an application that used libmonome with the functionality of MLR called Rove seem to compile & run on my Raspberry Pi

The Goal of my project is to make a self contained Monome/Arduinome with the only computer needed neatly tucked away in it's enclosure & eliminate the need to lug around a laptop computer or any other mobile computing platform netbook or tablet.



Question: Apparently you can get serialosc to recognize an Arduino Uno by flashing the ATmega chip with a Monome or arduino serial number along with changing other items. Following the instructions here.

I've changed what felt appropriate in my teensy's 'usb_desc.h' but serialosc daemon does not detect my device as a monome when I connect
Here are the changes I've made am I missing something??? Has someone accomplished something along the lines of what I'm doing?

Here are my modifications I've made to my teensys usb_desc.h that seemed appropriate but do not seem to work with serialosc
Code: Select all | TOGGLE FULL SIZE
#if defined(USB_SERIAL)
  #define VENDOR_ID      0x03eb
  #define PRODUCT_ID      0x2ff7
  #define DEVICE_CLASS      2   // 2 = Communication Class
  #define MANUFACTURER_NAME   {'A','r','d','u','i','n','o','m','e'}
  #define MANUFACTURER_NAME_LEN   7
  #define PRODUCT_NAME      {'a','4','0','h','-','0','0','1'}
  #define PRODUCT_NAME_LEN   8
  #define EP0_SIZE      64
  #define NUM_ENDPOINTS      4
  #define NUM_USB_BUFFERS   12
  #define NUM_INTERFACE      2
  #define CDC_STATUS_INTERFACE   0
  #define CDC_DATA_INTERFACE   1
  #define CDC_ACM_ENDPOINT   2
  #define CDC_RX_ENDPOINT       3
  #define CDC_TX_ENDPOINT       4
  #define CDC_ACM_SIZE          16
  #define CDC_RX_SIZE           64
  #define CDC_TX_SIZE           64
  #define CONFIG_DESC_SIZE   (9+9+5+5+4+5+7+9+7+7)
  #define ENDPOINT2_CONFIG   ENDPOINT_TRANSIMIT_ONLY
  #define ENDPOINT3_CONFIG   ENDPOINT_RECEIVE_ONLY
  #define ENDPOINT4_CONFIG   ENDPOINT_TRANSIMIT_ONLY

brianlight
 
Posts: 38
Joined: Mon Dec 23, 2013 9:52 pm

Re: Trellis 40h protocol

by racs on Thu Apr 17, 2014 5:53 pm

Hey Brian, I should have checked here before posting to the monome forum. I have been working on this same problem, but my solution was to skip serialOSC and libmonome, and update the monomecereal.maxpat instead. It is working perfectly with all the new serialOSC monome apps, all that needs to be added is are simple udpsend and udprecieve objects in the place of the existing serialosc.maxpat bpatcher.
Anyway, all the files I've been using are here: http://goo.gl/ByiEU6 , and my more in depth post is here: http://monome.org/community/discussion/comment/203662
Let me know if you have any luck

racs
 
Posts: 17
Joined: Thu Apr 03, 2014 2:43 pm

Re: Trellis 40h protocol

by racs on Thu Apr 17, 2014 6:03 pm

also, if you're set on using serial-pyio I got it to recognize my Uno by modifying the file DeviceDetector.py in the src folder

racs
 
Posts: 17
Joined: Thu Apr 03, 2014 2:43 pm

Re: Trellis 40h protocol

by brianlight on Thu Apr 17, 2014 8:08 pm

Awesome Racs I did not know about this method of using serialosc max/msp apps with the older serial protocol I check this out first thing when I get of work.

Yes, I also had to modify DeviceDetector.py to look for my Arduino Micro & Teensy 3.1 (I've been Developing on both)

I'm curious though do you have access to a Macintosh Computer. I have not personally tested this but I would imagine that these instructions for the Arduinome might just work for getting our trellis 8X8 grids working with serialosc. I do not have a Arduino uno or OSX based computer to try these steps---->

http://flipmu.com/work/arduinome/instru ... al-number/

brianlight
 
Posts: 38
Joined: Mon Dec 23, 2013 9:52 pm

Please be positive and constructive with your questions and comments.