/* * Core1_Light_Controller.c * * Created: Sat Jan 21 2023 16:22:51 * Author Chris */ // ============================================================================================ // Includes #include "Core1_Light_Controller.h" #include "MIDI_Note_List.h" #include "Core1_LED_Control.h" #include "Command_Definition.h" // ============================================================================================ // Defines #define PAUSE_LIGHT_TIMEOUT_TICKS (_EEPROM_Content.Pause_Light_Configuration[ch].Timeout * (1000 / TIMER_INTERVALL_LED_UPDATE_ms)) #define NOTE_COLOR_RED _EEPROM_Content.Channel_MIDI_Configuration[ch].Note_Color_Red #define NOTE_COLOR_GREEN _EEPROM_Content.Channel_MIDI_Configuration[ch].Note_Color_Green #define NOTE_COLOR_BLUE _EEPROM_Content.Channel_MIDI_Configuration[ch].Note_Color_Blue #define NOTE_COLOR_RED_ALT NOTE_COLOR_RED + 1 #define NOTE_COLOR_GREEN_ALT NOTE_COLOR_GREEN + 1 #define NOTE_COLOR_BLUE_ALT NOTE_COLOR_BLUE + 1 #define NOTE_COLOR_COUNT_RESET_THRESHOLD_TICKS (_EEPROM_Content.Channel_MIDI_Configuration[ch].Note_Reset_Timeout * (1000 / TIMER_INTERVALL_LED_UPDATE_ms)) // #define COUNT_APPLIED_NOTES // ============================================================================================ // Datatypes // ============================================================================================ // Variables volatile bool _MIDI_To_Light_Enabled; extern volatile EEPROM_Content_t _EEPROM_Content; Info_Last_Received_Note_t _Info_Last_Received_Note[NUM_LED_CHANNELS]; Info_Last_Received_Note_t _Info_Last_Applied_Note[NUM_LED_CHANNELS]; volatile Pause_Light_Timer_s _Pause_Light_Timer[NUM_LED_CHANNELS]; volatile int _NoteOn_Color_Counter[NUM_LED_CHANNELS][NUM_LED_COLORS]; volatile int _NoteOn_Color_Reset_Counter; // 1 LED Channel, 3 LED Colors, 2 Event Types (Note On & Off) int32_t _Event_Received_Counter[NUM_LED_CHANNELS][NUM_LED_COLORS][2]; static const uint8_t _PWM_Lookup[NUM_LED_COLORS][128] = { { // Red 0x04, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09, 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x0B, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x10, 0x10, 0x11, 0x11, 0x12, 0x12, 0x13, 0x14, 0x14, 0x15, 0x15, 0x16, 0x17, 0x18, 0x19, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x25, 0x26, 0x28, 0x29, 0x2A, 0x2C, 0x2D, 0x2E, 0x30, 0x32, 0x33, 0x35, 0x37, 0x38, 0x3A, 0x3C, 0x3E, 0x40, 0x42, 0x45, 0x47, 0x49, 0x4B, 0x4E, 0x50, 0x53, 0x56, 0x58, 0x5B, 0x5E, 0x61, 0x64, 0x68, 0x6B, 0x6E, 0x72, 0x76, 0x79, 0x7E, 0x82, 0x86, 0x8B, 0x8F, 0x94, 0x99, 0x9E, 0xA6, 0xAC, 0xB2, 0xB9, 0xBF, 0xC6, 0xCD, 0xD5, 0xDD, 0xE5, 0xED, 0xFF }, { // Green 0x03, 0x04, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x0A, 0x0A, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C, 0x0D, 0x0E, 0x0E, 0x0F, 0x0F, 0x10, 0x11, 0x12, 0x12, 0x13, 0x14, 0x15, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x23, 0x24, 0x25, 0x26, 0x28, 0x29, 0x2A, 0x2C, 0x2D, 0x2F, 0x30, 0x32, 0x33, 0x35, 0x37, 0x38, 0x3A, 0x3C, 0x3D, 0x3F, 0x41, 0x43, 0x45, 0x47, 0x49, 0x4B, 0x4D, 0x4F, 0x51, 0x53, 0x55, 0x57, 0x5A, 0x5C, 0x5E, 0x60, 0x63, 0x65, 0x68, 0x6B, 0x6F, 0x72, 0x75, 0x78, 0x7A, 0x7D, 0x81, 0x84, 0x87, 0x8A, 0x8D, 0x90, 0x94, 0x98, 0x9B, 0x9F, 0xA2, 0xA6, 0xAA, 0xAE, 0xB3, 0xB6, 0xBA, 0xBF, 0xC3, 0xC8, 0xCC, 0xD1, 0xD6, 0xDB, 0xE0, 0xE5, 0xE9, 0xEE, 0xF1, 0xFF }, { // Blue 0x01, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x0A, 0x0A, 0x0A, 0x0B, 0x0B, 0x0B, 0x0C, 0x0C, 0x0D, 0x0D, 0x0E, 0x0E, 0x0F, 0x0F, 0x10, 0x10, 0x11, 0x12, 0x12, 0x13, 0x14, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x25, 0x26, 0x27, 0x29, 0x2A, 0x2B, 0x2D, 0x2E, 0x30, 0x31, 0x33, 0x35, 0x36, 0x38, 0x39, 0x3B, 0x3D, 0x3F, 0x40, 0x42, 0x44, 0x46, 0x49, 0x4B, 0x4E, 0x50, 0x52, 0x55, 0x57, 0x59, 0x5C, 0x5E, 0x61, 0x63, 0x66, 0x69, 0x6C, 0x6F, 0x72, 0x75, 0x77, 0x7B, 0x7E, 0x81, 0x85, 0x88, 0x8C, 0x90, 0x93, 0x97, 0x9B, 0x9F, 0xA3, 0xA8, 0xAC, 0xB0, 0xB5, 0xBA, 0xBE, 0xC4, 0xC9, 0xCE, 0xD4, 0xD9, 0xDF, 0xE4, 0xEA, 0xEF, 0xFF } }; // ============================================================================================ // Function Declarations bool Core1_Light_Controller_Check_Channel_Match (enum LED_Channel channel, uint8_t midi_channel); bool Core1_Light_Controller_Check_Octave_Match (enum LED_Channel channel, uint midi_note); void Core1_Light_Controller_Pause_Light_Trigger (uint8_t midi_event, uint8_t midi_channel); void Core1_Light_Controller_Reset_NoteOn_Counter(); /******************************************************************* Interrupt Service Routines *******************************************************************/ /******************************************************************* Functions *******************************************************************/ void Core1_Light_Controller_Init(void) { _MIDI_To_Light_Enabled = true; for(uint32_t ch=0;ch 0) { if(_NoteOn_Color_Reset_Counter < NOTE_COLOR_COUNT_RESET_THRESHOLD_TICKS) { _NoteOn_Color_Reset_Counter++; } else { Core1_Light_Controller_Reset_NoteOn_Counter(); } } } } void Core1_Light_Controller_MIDI_OnOff_Event_Received(uint8_t midi_command_shifted_right, uint8_t midi_channel) { if(_MIDI_To_Light_Enabled != true) { return; } Core1_Light_Controller_Pause_Light_Trigger(midi_command_shifted_right, midi_channel); } void Core1_Light_Controller_MIDI_Other_Event_Received(uint8_t midi_data) { if(_MIDI_To_Light_Enabled != true) { return; } if(IS_MIDI_COMMAND_WITH_CHANNEL(midi_data)) { Core1_Light_Controller_Pause_Light_Trigger(MIDI_EVENT_FROM_COMMAND(midi_data), MIDI_CHANNEL_FROM_COMMAND(midi_data)); } else { Core1_Light_Controller_Pause_Light_Trigger(midi_data, MIDI_CHANNEL_16 + 1); } } void Core1_Light_Controller_MIDI_Full_Note_Received(uint8_t midi_event, uint8_t midi_channel, uint8_t midi_note, uint8_t value) { if(_MIDI_To_Light_Enabled != true) { return; } Core1_Light_Controller_Pause_Light_Trigger(midi_event, midi_channel); for(uint ch=0;ch 0) { DutyCycle = _PWM_Lookup[R][value]; } else { DutyCycle = value << 1; } Core1_LED_Control_Set_DC_Direct(ch, R, DutyCycle); _NoteOn_Color_Counter[ch][R]++; #ifdef COUNT_APPLIED_NOTES _Event_Received_Counter[ch][R][MIDI_EVENT_NOTE_ON - MIDI_EVENT_NOTE_OFF]++; #endif } else if(midi_note_in_octave == NOTE_COLOR_GREEN || midi_note_in_octave == NOTE_COLOR_GREEN_ALT) { uint8_t DutyCycle = value; if(_EEPROM_Content.Device_Configuration.Use_Color_Correction > 0) { DutyCycle = _PWM_Lookup[G][value]; } else { DutyCycle = value << 1; } Core1_LED_Control_Set_DC_Direct(ch, G, DutyCycle); _NoteOn_Color_Counter[ch][G]++; #ifdef COUNT_APPLIED_NOTES _Event_Received_Counter[ch][G][MIDI_EVENT_NOTE_ON - MIDI_EVENT_NOTE_OFF]++; #endif } else if(midi_note_in_octave == NOTE_COLOR_BLUE || midi_note_in_octave == NOTE_COLOR_BLUE_ALT) { uint8_t DutyCycle = value; if(_EEPROM_Content.Device_Configuration.Use_Color_Correction > 0) { DutyCycle = _PWM_Lookup[B][value]; } else { DutyCycle = value << 1; } Core1_LED_Control_Set_DC_Direct(ch, B, DutyCycle); _NoteOn_Color_Counter[ch][B]++; #ifdef COUNT_APPLIED_NOTES _Event_Received_Counter[ch][B][MIDI_EVENT_NOTE_ON - MIDI_EVENT_NOTE_OFF]++; #endif } else { Note_Applied = false; } } else if((midi_event == MIDI_EVENT_NOTE_OFF && _EEPROM_Content.Channel_MIDI_Configuration[ch].Skip_Note_Off_Event == 0)) { if(midi_note_in_octave == NOTE_COLOR_RED || midi_note_in_octave == NOTE_COLOR_RED_ALT) { if(_NoteOn_Color_Counter[ch][R] > 0) { _NoteOn_Color_Counter[ch][R]--; } if(_NoteOn_Color_Counter[ch][R] == 0) { Core1_LED_Control_Set_DC_Direct(ch, R, 0); } #ifdef COUNT_APPLIED_NOTES _Event_Received_Counter[ch][R][MIDI_EVENT_NOTE_OFF - MIDI_EVENT_NOTE_OFF]++; #endif } else if(midi_note_in_octave == NOTE_COLOR_GREEN || midi_note_in_octave == NOTE_COLOR_GREEN_ALT) { if(_NoteOn_Color_Counter[ch][G] > 0) { _NoteOn_Color_Counter[ch][G]--; } if(_NoteOn_Color_Counter[ch][G] == 0) { Core1_LED_Control_Set_DC_Direct(ch, G, 0); } #ifdef COUNT_APPLIED_NOTES _Event_Received_Counter[ch][G][MIDI_EVENT_NOTE_OFF - MIDI_EVENT_NOTE_OFF]++; #endif } else if(midi_note_in_octave == NOTE_COLOR_BLUE || midi_note_in_octave == NOTE_COLOR_BLUE_ALT) { if(_NoteOn_Color_Counter[ch][B] > 0) { _NoteOn_Color_Counter[ch][B]--; } if(_NoteOn_Color_Counter[ch][B] == 0) { Core1_LED_Control_Set_DC_Direct(ch, B, 0); } #ifdef COUNT_APPLIED_NOTES _Event_Received_Counter[ch][B][MIDI_EVENT_NOTE_OFF - MIDI_EVENT_NOTE_OFF]++; #endif } else { Note_Applied = false; } } else { Note_Applied = false; } if(Note_Applied == true) { _Info_Last_Applied_Note[ch].Event = midi_event; _Info_Last_Applied_Note[ch].Note = midi_note; _Info_Last_Applied_Note[ch].Note_In_Octave = midi_note_in_octave; _Info_Last_Applied_Note[ch].Velocity = value; _Info_Last_Applied_Note[ch].Timestamp_ms = to_ms_since_boot(get_absolute_time()); } } } void Core1_Light_Controller_MIDI_Full_CC_Received(uint8_t midi_event, uint8_t midi_channel, uint8_t controller_number, uint8_t controller_value) { Core1_Light_Controller_Pause_Light_Trigger(midi_event, midi_channel); for(uint ch=0;ch= NUM_LED_CHANNELS) { return false; } return (midi_channel == _EEPROM_Content.Channel_MIDI_Configuration[channel].MIDI_Channel); } bool Core1_Light_Controller_Check_Octave_Match(enum LED_Channel channel, uint midi_note) { if(channel >= NUM_LED_CHANNELS) { return false; } if(midi_note >= MIDI_NOTE_LIST_LENGTH) { return false; } return (_MIDI_Note_List[midi_note].Octave == _EEPROM_Content.Channel_MIDI_Configuration[channel].Octave); } void Core1_Light_Controller_Pause_Light_Trigger(uint8_t midi_event, uint8_t midi_channel) { for(uint ch=0;ch 0) { Core1_LED_Control_Set_DC_Direct(ch, l, 0); } _NoteOn_Color_Counter[ch][l] = 0; } } } Note_t Core1_Light_Controller_Get_Octave_Note_For_Channel(enum LED_Channel channel) { if(channel >= NUM_LED_CHANNELS) { return NO_NOTE; } return _Info_Last_Applied_Note[channel].Note_In_Octave; } Value_t Core1_Light_Controller_Get_Note_Value_For_Channel(enum LED_Channel channel) { if(channel >= NUM_LED_CHANNELS) { return 0; } return _Info_Last_Applied_Note[channel].Velocity; }