hello,
fortunately, I built my common anode matrix rgb led driver (THANKS TO LUCEM who detailed me all the process, and made me understand!)
-
row (anodes) driver is SR + resistor 1k + transistor BC547 used as a switch to source 5V to rows..
-
column (cathodes) driver is 3 ULN to sink current + 3 SR. (3 = one for each color)
I have a little problem now with the code (only the code, I guess)
When I basically turn pins high in Init(), it works very fine !
But the process has to be done in ISR via SR_Service_Prepare()
when I do that, no led are up…
1st SR is for ROW driver
2, 3, 4th are for RBG color COLUMN driver
here are the code involved:
/////////////////////////////////////////////////////////////////////////////
// Include files
/////////////////////////////////////////////////////////////////////////////
#include <cmios.h>
#include <pic18fregs.h>
#include <protodeck.h>
#include "main.h"
/////////////////////////////////////////////////////////////////////////////
// Global variables
/////////////////////////////////////////////////////////////////////////////
// status of application (see bitfield declaration in main.h)
app_flags_t app_flags;
/////////////////////////////////////////////////////////////////////////////
// Local variables
/////////////////////////////////////////////////////////////////////////////
// last ain/din/dout
unsigned char last_ain_pin;
unsigned char last_din_pin;
unsigned char last_dout_pin;
// we create a 2-dimensional array with 23 entries for mapping between potentiometers movements & events associated
// each entry consists of two bytes:
// o one for the first MIDI byte (MIDI status) => 0xb* means CC message for Channel *
// o a second for the second MIDI byte (=> CC number)
// The meaning of the bytes can be found in the MIDI spec
// (-> http://www.harmony-central.com/MIDI/Doc/table1.html)
// (-> http://www.harmony-central.com/MIDI/Doc/table2.html)
// (-> http://www.harmony-central.com/MIDI/Doc/table3.html)
const unsigned char pot_event_map[23][2] = {
//AIN 11
// Pots 1-12 = drums controls pots => channel 10
{0xb9, 0x01}, {0xb9, 0x02}, {0xb9, 0x03}, {0xb9, 0x04}, {0xb9, 0x05}, {0xb9, 0x06},
{0xb9, 0x07}, {0xb9, 0x08}, {0xb9, 0x09}, {0xb9, 0x0A}, {0xb9, 0x0B}, {0xb9, 0x0C},
// Pots 13-18 = EQ = channel 16
{0xbF, 0x01}, {0xbF, 0x02}, {0xbF, 0x03}, {0xbF, 0x04}, {0xbF, 0x05}, {0xbF, 0x06},
// Pot 19 = Master Volume = channel 16
{0xbF, 0x07},
// Pots 20-23 = multifunctionnal purpose pots = channel 16
{0xbF, 0x08}, {0xbF, 0x09}, {0xbF, 0x10}, {0xbF, 0x0A},
};
// we create a 2-dimensional array with 64 entries for mapping between switches push & events associated
// each entry consists of two bytes:
// o one for the first MIDI byte (MIDI status) => 0x9* means Note message for Channel *
// o a second for the second MIDI byte (=> Note number)
// This const is parsed lower by void DIN_NotifyToggle()
// The meaning of the bytes can be found in the MIDI spec
// (-> http://www.harmony-central.com/MIDI/Doc/table1.html)
// (-> http://www.harmony-central.com/MIDI/Doc/table2.html)
// (-> http://www.harmony-central.com/MIDI/Doc/table3.html)
const unsigned char button_event_map[64][2] = { //------- clip matrix control
//-------- DIN11
// Buttons 1-8 = tracks mute = channel 1-8
{0x90, 0x01}, {0x91, 0x01}, {0x92, 0x01}, {0x93, 0x01},
{0x94, 0x01}, {0x95, 0x01}, {0x96, 0x01}, {0x97, 0x01},
// Buttons scenes 1 = 9-16 = channel 1-8
{0x90, 0x02}, {0x91, 0x02}, {0x92, 0x02}, {0x93, 0x02},
{0x94, 0x02}, {0x95, 0x02}, {0x96, 0x02}, {0x97, 0x02},
// Buttons scenes 2 = 17-24 = channel 1-8
{0x90, 0x03}, {0x91, 0x03}, {0x92, 0x03}, {0x93, 0x03},
{0x94, 0x03}, {0x95, 0x03}, {0x96, 0x03}, {0x97, 0x03},
// Buttons scenes 3 = 25-32 = channel 1-8
{0x90, 0x04}, {0x91, 0x04}, {0x92, 0x04}, {0x93, 0x04},
{0x94, 0x04}, {0x95, 0x04}, {0x96, 0x04}, {0x97, 0x04},
//-------- DIN12
// Buttons scenes 4 = 33-40 = channel 1-8
{0x90, 0x05}, {0x91, 0x05}, {0x92, 0x05}, {0x93, 0x05},
{0x94, 0x05}, {0x95, 0x05}, {0x96, 0x05}, {0x97, 0x05},
// Buttons scenes 5 = 41-48 = channel 1-8
{0x90, 0x06}, {0x91, 0x06}, {0x92, 0x06}, {0x93, 0x06},
{0x94, 0x06}, {0x95, 0x06}, {0x96, 0x06}, {0x97, 0x06},
// Buttons scenes 6 = 49-56 = channel 1-8
{0x90, 0x07}, {0x91, 0x07}, {0x92, 0x07}, {0x93, 0x07},
{0x94, 0x07}, {0x95, 0x07}, {0x96, 0x07}, {0x97, 0x07},
// Buttons scenes control = 57-62 = CHANNEL 16
{0x9F, 0x01}, {0x9F, 0x02}, {0x9F, 0x03}, {0x9F, 0x04},
{0x9F, 0x05}, {0x9F, 0x06},
// Buttons offset control = 63,64 = CHANNEL 16
{0x9F, 0x07}, {0x9F, 0x08}
};
static unsigned int clipButtons[8] = { 0,0,0,0,0,0,0,0 };
// we create a 2-dimensional array with 64 entries for led color storage for the clip matrix controller part
// each entry consists of 1 byte coded like that:
// 0x00 = OFF
// 0x10 = RED
// 0x20 = GREEN
// 0x40 = BLUE
// 0x30 = RED + GREEN = YELLOW
// 0x60= GREEN + BLUE = CYAN
// 0x50 = RED + BLUE = MAGENTA
// 0x70 = WHITE
// The meaning of the bytes can be found in the MIDI spec
// (-> http://www.harmony-central.com/MIDI/Doc/table1.html)
// (-> http://www.harmony-central.com/MIDI/Doc/table2.html)
// (-> http://www.harmony-central.com/MIDI/Doc/table3.html)
//
// structure is matrix[ROW][COLUMN]=COLOR
static unsigned char matrix[8][8] = {
{0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10},
{0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20},
{0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30},
{0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40},
{0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50},
{0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60},
{0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70},
{0x00,0x30,0x00,0x50,0x00,0x70,0x00,0x00}
};
/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS after startup to initialize the
// application
/////////////////////////////////////////////////////////////////////////////
void Init(void) __wparam
{
// configure the core1 as midibox-link FORWARD Point
// see infos about midibox-link here: http://www.ucapps.de/midibox_link.html
MIOS_MIDI_MergerSet(MIOS_MIDI_MERGER_MBLINK_EP);
// set shift register update frequency
MIOS_SRIO_UpdateFrqSet(1); // ms
// we need to set at least one IO shift register pair
MIOS_SRIO_NumberSet(NUMBER_OF_SRIO);
// debouncing value for DINs
MIOS_SRIO_DebounceSet(DIN_DEBOUNCE_VALUE);
MIOS_SRIO_TS_SensitivitySet(DIN_TS_SENSITIVITY);
// initialize the AIN driver
MIOS_AIN_NumberSet(AIN_NUMBER_INPUTS);
#if AIN_MUXED_MODE
MIOS_AIN_Muxed();
#else
MIOS_AIN_UnMuxed();
#endif
MIOS_AIN_DeadbandSet(AIN_DEADBAND);
// all pin of row driver low
MIOS_DOUT_SRSet(0, 0);
}
/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS in the mainloop when nothing else is to do
/////////////////////////////////////////////////////////////////////////////
void Tick(void) __wparam
{
}
/////////////////////////////////////////////////////////////////////////////
// This function is periodically called by MIOS. The frequency has to be
// initialized with MIOS_Timer_Set
/////////////////////////////////////////////////////////////////////////////
void Timer(void) __wparam
{
}
//////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS when the display content should be
// initialized. Thats the case during startup and after a temporary message
// has been printed on the screen
/////////////////////////////////////////////////////////////////////////////
void DISPLAY_Init(void) __wparam
{
// clear screen
MIOS_LCD_Clear();
// print static messages
MIOS_LCD_CursorSet(0x00); // first line
MIOS_LCD_PrintCString("1AIN DIN DOUT");
MIOS_LCD_CursorSet(0x40); // second line
MIOS_LCD_PrintCString("xx:xxx xxxx xxxx");
// request display update
app_flags.DISPLAY_UPDATE_REQ = 1;
}
/////////////////////////////////////////////////////////////////////////////
// This function is called in the mainloop when no temporary message is shown
// on screen. Print the realtime messages here
/////////////////////////////////////////////////////////////////////////////
void DISPLAY_Tick(void) __wparam
{
// do nothing if no update has been requested
if( !app_flags.DISPLAY_UPDATE_REQ )
return;
// clear request
app_flags.DISPLAY_UPDATE_REQ = 0;
// print status of AIN
MIOS_LCD_CursorSet(0x40 + 0);
MIOS_LCD_PrintBCD2(last_ain_pin + 1);
MIOS_LCD_PrintChar(':');
MIOS_LCD_PrintBCD3(MIOS_AIN_Pin7bitGet(last_ain_pin));
// print status of DIN
MIOS_LCD_CursorSet(0x40 + 7);
MIOS_LCD_PrintBCD3(last_din_pin + 1);
MIOS_LCD_PrintChar(MIOS_DIN_PinGet(last_din_pin) ? 'o' : '*');
// print status of DOUT
MIOS_LCD_CursorSet(0x40 + 12);
MIOS_LCD_PrintBCD3(last_dout_pin + 1);
MIOS_LCD_PrintChar(MIOS_DOUT_PinGet(last_dout_pin) ? '*' : 'o');
}
/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS when a MIDI byte has been received
/////////////////////////////////////////////////////////////////////////////
void MPROC_NotifyReceivedByte(unsigned char byte) __wparam
{
}
/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS when a complete MIDI event has been received
/////////////////////////////////////////////////////////////////////////////
void MPROC_NotifyReceivedEvnt(unsigned char evnt0, unsigned char evnt1, unsigned char evnt2) __wparam
{
int channelIndex = evnt0;
int noteIndex = evnt1;
unsigned char value = evnt2;
// _COLOR_OFF 0x00 00000000
// _COLOR_RED 0x10 00010000
// _COLOR_GREEN 0x20 00100000
// _COLOR_BLUE 0x40 01000000
// _COLOR_CYAN 0x60 01100000
// _COLOR_MAGENTA 0x50 01010000
// _COLOR_YELLOW 0x30 00110000
// _COLOR_WHITE 0x70 01110000
/*if (channelIndex >= 0 && channelIndex < 8)
{
if ( noteIndex > _NOTE_RECEIVE_OFFSET && noteIndex < _NOTE_RECEIVE_OFFSET +8 )
{
matrix[noteIndex-_NOTE_RECEIVE_OFFSET][channelIndex] = value ;
}
}*/
}
/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS when a MIDI event has been received
// which has been specified in the MIOS_MPROC_EVENT_TABLE
/////////////////////////////////////////////////////////////////////////////
void MPROC_NotifyFoundEvent(unsigned entry, unsigned char evnt0, unsigned char evnt1, unsigned char evnt2) __wparam
{
}
/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS when a MIDI event has not been completly
// received within 2 seconds
/////////////////////////////////////////////////////////////////////////////
void MPROC_NotifyTimeout(void) __wparam
{
}
void DisplayLED(unsigned char column, unsigned char color) __wparam
{
color >>= 4;
MIOS_DOUT_PinSet(column+8, (color & 0x01)); // RED
color >>= 1;
MIOS_DOUT_PinSet(column+8+8, (color & 0x01)); // BLUE
color >>= 1;
MIOS_DOUT_PinSet(column+8+8+8, (color & 0x01)); // GREEN
}
/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS before the shift register are loaded
/////////////////////////////////////////////////////////////////////////////
void SR_Service_Prepare(void) __wparam
{
// HELPED BY BUGFIGHT => http://www.midibox.org/forum/index.php/topic,12786.0.html
static unsigned char row;
static unsigned char lastrow;
unsigned int x;
row = ++row & 0x07; // 8 cycle = 6.25% duty cycle
MIOS_DOUT_PinSet0(lastrow); // row driver pin of last row on pulled OFF
MIOS_DOUT_PinSet1(row); // row driver pin #row ON
for (x = 0; x < 8; x++)
{
DisplayLED(x , matrix[row][x]); // for the row row, cycle all column
}
lastrow = row;
}
/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS after the shift register have been loaded
/////////////////////////////////////////////////////////////////////////////
void SR_Service_Finish(void) __wparam
{
}
/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS when an button has been toggled
// pin_value is 1 when button released, and 0 when button pressed
/////////////////////////////////////////////////////////////////////////////
void DIN_NotifyToggle(unsigned char pin, unsigned char pin_value) __wparam
{
// a button has been pressed, send Note at channel 1
// MIOS_MIDI_BeginStream();
// MIOS_MIDI_TxBufferPut(0x90); // Note at channel 1
// MIOS_MIDI_TxBufferPut(pin); // pin number corresponds to note number
// MIOS_MIDI_TxBufferPut(pin_value ? 0x00 : 0x7f); // buttons are high-active
// MIOS_MIDI_EndStream();
unsigned char channel;
unsigned char note;
channel = button_event_map[pin][0];
note = button_event_map[pin][1];
if (pin_value == 0)
{
if (clipButtons[channel] != 0)
{
return;
}
clipButtons[channel] = 1;
}
else
{
clipButtons[channel] = 0;
}
MIOS_MIDI_BeginStream();
MIOS_MIDI_TxBufferPut(channel); // first value from table = CHANNEL
MIOS_MIDI_TxBufferPut(note); // second value from table = NOTE
MIOS_MIDI_TxBufferPut(pin_value ? 0x00 : 0x7f); // 1
MIOS_MIDI_EndStream();
// notify display handler in DISPLAY_Tick() that DIN value has changed
last_din_pin = pin;
app_flags.DISPLAY_UPDATE_REQ = 1;
}
/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS when an encoder has been moved
// incrementer is positive when encoder has been turned clockwise, else
// it is negative
/////////////////////////////////////////////////////////////////////////////
void ENC_NotifyChange(unsigned char encoder, char incrementer) __wparam
{
}
/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS when a pot has been moved
/////////////////////////////////////////////////////////////////////////////
void AIN_NotifyChange(unsigned char pin, unsigned int pin_value) __wparam
{
// // a pot has been moved, send CC#<pin-number> at channel 1
// MIOS_MIDI_BeginStream();
// MIOS_MIDI_TxBufferPut(0xb0); // CC at channel 1
// MIOS_MIDI_TxBufferPut(pin); // pin number corresponds to CC number
// MIOS_MIDI_TxBufferPut(MIOS_AIN_Pin7bitGet(pin)); // don't send 10bit pin_value, but 7bit value
// MIOS_MIDI_EndStream();
// send mapped CC value
MIOS_MIDI_BeginStream();
MIOS_MIDI_TxBufferPut(pot_event_map[pin][0]); // first value from table
MIOS_MIDI_TxBufferPut(pot_event_map[pin][1]); // second value from table
MIOS_MIDI_TxBufferPut(MIOS_AIN_Pin7bitGet(pin)); // 7bit pot value
MIOS_MIDI_EndStream();
// notify display handler in DISPLAY_Tick() that AIN value has changed
last_ain_pin = pin;
app_flags.DISPLAY_UPDATE_REQ = 1;
}
void ClearMatrix(void) __wparam
{
unsigned int column = 0;
unsigned int row = 0;
for (row = 0; row < 8; row++)
{
for (column = 0; column < 8; column++)
{
matrix[row][column] = _COLOR_OFF;
}
}
}
Indeed, it is the same code used by noofny/mike with his common cathode matrix.
but the hardware matches this code too, no?
if someone could help me . . . ![]()