I have been attempting to make the notes changeable with an encoder. my encoder works perfectly but I cannot seem to change the value ¬e[row]. I have attempted making
//in global
uint8_t note[8] = {
midiNote[0], midiNote[1], midiNote[2], midiNote[3],
midiNote[4], midiNote[5], midiNote[6], midiNote[7] }
;
instead of:
static const uint8_t note[8] PROGMEM = {
midiNote[0], midiNote[1], midiNote[2], midiNote[3],
midiNote[4], midiNote[5], midiNote[6], midiNote[7] }
;
//in loop
//in midi message
¬e[row]
intead of
pgm_read_byte (¬e[row])
I am going about this the wrong way. If anyone has any tips, that would be awesome.
UNTZtrument Sequencer with changeable notes?
Moderators: adafruit_support_bill, adafruit
Please be positive and constructive with your questions and comments.
- pburgess
- Posts: 4161
- Joined: Sun Oct 26, 2008 2:29 am
Re: UNTZtrument Sequencer with changeable notes?
For a normal RAM-based array lookup, drop the & and just use:
pgm_read_byte expects the address of a value, hence the additional & operator there.
As long as your tables aren't huge, having them RAM-resident shouldn't be a problem. If it grows into the hundreds though, that's when PROGMEM really becomes vital, and the demo code is just trying to set a good example there.
Code: Select all
n = note[row];
As long as your tables aren't huge, having them RAM-resident shouldn't be a problem. If it grows into the hundreds though, that's when PROGMEM really becomes vital, and the demo code is just trying to set a good example there.
- pburgess
- Posts: 4161
- Joined: Sun Oct 26, 2008 2:29 am
Re: UNTZtrument Sequencer with changeable notes?
*squint* Sorry, just realized you're doing something slightly different...which code is this based on? Is it Collin's arpeggiator, or something else?
What you have here:
Is actually an array of arrays. Which is cool and fine, we just need to go about declaring and reading it in special ways. I'm not sure it'll actually compile as written that way.
I started to go off half-cocked on an answer here, but deleted it because it might not be answering the right thing. If you can post more/all of the sketch, or link to the example you're working from, then I can provide a better thought-out response.
What you have here:
Code: Select all
uint8_t note[8] = {
midiNote[0], midiNote[1], midiNote[2], midiNote[3],
midiNote[4], midiNote[5], midiNote[6], midiNote[7] };
I started to go off half-cocked on an answer here, but deleted it because it might not be answering the right thing. If you can post more/all of the sketch, or link to the example you're working from, then I can provide a better thought-out response.
- pranks
- Posts: 11
- Joined: Thu Mar 28, 2013 4:30 pm
Re: UNTZtrument Sequencer with changeable notes?
http://BANNED.com/sbgbXirD
Maybe this will clarify my question.
Thanks again for your help. It is very appreciated.
Maybe this will clarify my question.
Thanks again for your help. It is very appreciated.
- adafruit2
- Posts: 22148
- Joined: Fri Mar 11, 2005 7:36 pm
Re: UNTZtrument Sequencer with changeable notes?
hmm, you're not using a Leonardo like the UNTZ tutorial uses, so its not really USB MIDI - so much of the sketch has been rewritten :/ its going to be tougher to have us help you if you have a significantly different setup.
- pranks
- Posts: 11
- Joined: Thu Mar 28, 2013 4:30 pm
Re: UNTZtrument Sequencer with changeable notes?
The midi note structure is the same. The only difference is I am outputting through standard midi. The midi note byte is 0-127 just as the midi USB value is. I am only looking to figure out how to make the note variable with your library. If it will be easier on your end I can change the code back to the Leonardo, but it should make little difference as the code was working fine with standard midi out prior to changing the note to be variable.
- pranks
- Posts: 11
- Joined: Thu Mar 28, 2013 4:30 pm
Re: UNTZtrument Sequencer with changeable notes?
Here is the code with usbMIDI on the leo.
Notes and questions in //comments
Notes and questions in //comments
Code: Select all
// Simple UNTZtrument MIDI step sequencer.
// Requires an Arduino Leonardo w/TeeOnArdu config (or a PJRC Teensy),
// software on host computer for synth or to route to other devices.
#include <Wire.h>
#include <Adafruit_Trellis.h>
#include <Adafruit_UNTZtrument.h>
#define LED 13 // Pin for heartbeat LED (shows code is working)
#ifndef HELLA
// A standard UNTZtrument has four Trellises in a 2x2 arrangement
// (8x8 buttons total). addr[] is the I2C address of the upper left,
// upper right, lower left and lower right matrices, respectively,
// assuming an upright orientation, i.e. labels on board are in the
// normal reading direction.
Adafruit_Trellis T[4];
Adafruit_UNTZtrument untztrument(&T[0], &T[1], &T[2], &T[3]);
const uint8_t addr[] = {
0x70, 0x71, 0x72, 0x73 };
#else
// A HELLA UNTZtrument has eight Trellis boards...
Adafruit_Trellis T[8];
Adafruit_UNTZtrument untztrument(&T[0], &T[1], &T[2], &T[3],
&T[4], &T[5], &T[6], &T[7]);
const uint8_t addr[] = {
0x70, 0x71, 0x72, 0x73,
0x74, 0x75, 0x76, 0x77 };
#endif // HELLA
#define WIDTH ((sizeof(T) / sizeof(T[0])) * 2)
#define N_BUTTONS ((sizeof(T) / sizeof(T[0])) * 16)
// Encoder on pins 4,5 sets tempo. Optional, not present in
// standard UNTZtrument, but won't affect things if unconnected.
enc e[] = {
enc(4, 5), enc(8, 9) };
uint8_t grid[WIDTH]; // Sequencer state
uint8_t heart = 0, // Heartbeat LED counter
col = WIDTH-1; // Current column
unsigned int bpm = 240; // Tempo
unsigned long beatInterval = 60000L / bpm, // ms/beat
prevBeatTime = 0L, // Column step timer
prevReadTime = 0L; // Keypad polling timer
//Below used for encoder function
//and changing midiNote[]
uint8_t
encNoteValueStore[8] = {
0, 0, 0, 0, 0, 0, 0, 0 }
,
encNoteValue[8] = {
0, 0, 0, 0, 0, 0, 0, 0 }
,
encValue[8] = {
24, 24, 24, 24, 24, 24, 24, 24 }
,
newNote[8] = {
24, 24, 24, 24, 24, 24, 24, 24 }
,
midiNote[8] = {
24, 24, 24, 24, 24, 24, 24, 24 }
,
noteEncoderValue[8] = {
0, 0, 0, 0, 0, 0, 0, 0 }
,
noteButtonPin[] = {
A0, A1, A2, A3}
;
// The note[] and channel[] tables are the MIDI note and channel numbers
// for to each row (top to bottom); they're specific to this application.
// bitmask[] is for efficient reading/writing bits to the grid[] array.
//***There is now a selection type conflict***
//UNTZtrument_Step_Seq:84: error: bitmask causes a section type conflict
//UNTZtrument_Step_Seq:81: error: channel causes a section type conflict
static const uint8_t PROGMEM
note[8] = {
midiNote[0], midiNote[1], midiNote[2], midiNote[3],
midiNote[4], midiNote[5], midiNote[6], midiNote[7]}
,
channel[8] = {
1, 1, 1, 1, 1, 1, 1, 1 }
,
bitmask[8] = {
1, 2, 4, 8, 16, 32, 64, 128 };
void setup() {
pinMode(LED, OUTPUT);
#ifndef HELLA
untztrument.begin(addr[0], addr[1], addr[2], addr[3]);
#else
untztrument.begin(addr[0], addr[1], addr[2], addr[3],
addr[4], addr[5], addr[6], addr[7]);
#endif // HELLA
#ifdef __AVR__
// Default Arduino I2C speed is 100 KHz, but the HT16K33 supports
// 400 KHz. We can force this for faster read & refresh, but may
// break compatibility with other I2C devices...so be prepared to
// comment this out, or save & restore value as needed.
TWBR = 12;
#endif
untztrument.clear();
untztrument.writeDisplay();
memset(grid, 0, sizeof(grid));
e[0].setBounds(60 * 4, 480 * 4 + 3); // Set tempo limits
e[0].setValue(bpm * 4); // *4's for encoder detents
}
// Turn on (or off) one column of the display
void line(uint8_t x, boolean set) {
for(uint8_t mask=1, y=0; y<8; y++, mask <<= 1) {
uint8_t i = untztrument.xy2i(x, y);
if(set || (grid[x] & mask)) untztrument.setLED(i);
else untztrument.clrLED(i);
}
pinMode(noteButtonPin[0], INPUT); //assigns button for midiNote[0]
}
void loop() {
uint8_t mask;
boolean refresh = false;
unsigned long t = millis();
enc::poll(); // Read encoder(s)
//-------------------------------------------------------------------------------------
// Changes midiNote[] when corresponding button is pressed
// and ecoder is turned. This is only for midiNote[0]
//which is replacing what was previously note[0]
//I did not add the other encoder/button functions for simplicity
int noteButtonState0 = digitalRead(noteButtonPin[0]); //Read if button pressed
encNoteValue[0] = (e[1].getValue() / 4);
if(encNoteValue[0] > encNoteValueStore[0]) {
if(noteButtonState0 == LOW) { //Note encoder changes if button 1 pressed
encValue[0]++;
encNoteValueStore[0] = encNoteValue[0];
}
}
if(encNoteValue[0] < encNoteValueStore[0]) {
if(noteButtonState0 == LOW) { //Note encoder changes if button 1 pressed
encValue[0]--;
encNoteValueStore[0] = encNoteValue[0];
}
}
newNote[0] = encValue[0];
midiNote[0] = newNote[0] ; //Set midiNote[]
//-------------------------------------------------------------------------------------
if((t - prevReadTime) >= 20L) { // 20ms = min Trellis poll time
if(untztrument.readSwitches()) { // Button state change?
for(uint8_t i=0; i<N_BUTTONS; i++) { // For each button...
uint8_t x, y;
untztrument.i2xy(i, &x, &y);
mask = pgm_read_byte(&bitmask[y]);
if(untztrument.justPressed(i)) {
if(grid[x] & mask) { // Already set? Turn off...
grid[x] &= ~mask;
untztrument.clrLED(i);
usbMIDI.sendNoteOff(pgm_read_byte(¬e[y]),
127, pgm_read_byte(&channel[y]));
}
else { // Turn on
grid[x] |= mask;
untztrument.setLED(i);
}
refresh = true;
}
}
}
prevReadTime = t;
digitalWrite(LED, ++heart & 32); // Blink = alive
}
if((t - prevBeatTime) >= beatInterval) { // Next beat?
// Turn off old column
line(col, false);
for(uint8_t row=0, mask=1; row<8; row++, mask <<= 1) {
if(grid[col] & mask) {
usbMIDI.sendNoteOff(pgm_read_byte(¬e[row]), 127,
pgm_read_byte(&channel[row]));
}
}
// Advance column counter, wrap around
if(++col >= WIDTH) col = 0;
// Turn on new column
line(col, true);
for(uint8_t row=0, mask=1; row<8; row++, mask <<= 1) {
if(grid[col] & mask) {
usbMIDI.sendNoteOn(pgm_read_byte(¬e[row]), 127, //I want to make ¬e[row] Variable
pgm_read_byte(&channel[row])); //with the turn of encoder knob
} //while button pushed code for that function
} //works, pgm_read_byte(¬e[row]
prevBeatTime = t; //does not for this application
refresh = true; //please help. THANKS PRANKS
bpm = e[0].getValue() / 4; // Div for encoder detents
beatInterval = 60000L / bpm;
}
if(refresh) untztrument.writeDisplay();
while(usbMIDI.read()); // Discard incoming MIDI messages
}
- pburgess
- Posts: 4161
- Joined: Sun Oct 26, 2008 2:29 am
Re: UNTZtrument Sequencer with changeable notes?
Problem begins here, though the compiler has a crappy way of reporting it:
note[], as declared here, is a PROGMEM (flash-resident) array. But inside you're referencing elements of the midiNote[] array, which is RAM-resident and thus non-constant and can't be PROGMEM'd.
Need to determine, first of all, what values and tables are completely invariant during the program's entire run and PROGMEM only those (and remember to always use pgm_read_byte (or word, etc.) when accessing elements of those tables -- using their address, e.g. foo = pgm_read_byte(&array[n])). Changeable things need to be declared non-const, non-PROGMEM, and are read directly, e.g. foo = array[n].
Since it looks like the note[] array is a direct copy of the midiNote[] array, I'd just do away with one or the other and access the singular copy...maybe keep just the midiNote[] array (as a non-const, non-PROGMEM variable array), remove note[] entirely and make sure any references to it just read the array directly, no pgm_read stuff on that.
Code: Select all
static const uint8_t PROGMEM
note[8] = {
midiNote[0], midiNote[1], midiNote[2], midiNote[3],
midiNote[4], midiNote[5], midiNote[6], midiNote[7]};
Need to determine, first of all, what values and tables are completely invariant during the program's entire run and PROGMEM only those (and remember to always use pgm_read_byte (or word, etc.) when accessing elements of those tables -- using their address, e.g. foo = pgm_read_byte(&array[n])). Changeable things need to be declared non-const, non-PROGMEM, and are read directly, e.g. foo = array[n].
Since it looks like the note[] array is a direct copy of the midiNote[] array, I'd just do away with one or the other and access the singular copy...maybe keep just the midiNote[] array (as a non-const, non-PROGMEM variable array), remove note[] entirely and make sure any references to it just read the array directly, no pgm_read stuff on that.
- pranks
- Posts: 11
- Joined: Thu Mar 28, 2013 4:30 pm
Re: UNTZtrument Sequencer with changeable notes?
You guys are the best. Thanks again pburgess.
I <3 adafruit!
I <3 adafruit!
Please be positive and constructive with your questions and comments.