Files
RP2350_MIDI_Lighter/Firmware/EEPROM_M24C64.c
Chris 128d42c586 - Fixed drawing of round objects (Circles, Rounded Rects) using a lookup table
- Added function to read out the display_buffer via USB-Serial
 - Added basic structure and files for later complete firmware (still in progress)
 - Added Doc folder with schematic in it
 - Added Python script and batch file to read out the display buffer and open the image in gimp
2025-09-07 08:55:39 +02:00

227 lines
7.0 KiB
C

/*
* EEPROM_M24C64.c
*
* Created: Fri Dec 24 2021 12:24:26
* Author Chris
*/
// ============================================================================================
// Includes
#include "EEPROM_M24C64.h"
#include "I2C_Master.h"
#include "Hue.h"
#include "MIDI_Note_List.h"
// ============================================================================================
// Defines
#define EEPROM_I2C_ADDRESS 0b1010000
#define EEPROM_PAGE_SIZE 32
#define EEPROM_CONTENT_SIZE sizeof(EEPROM_Content_t)
#define EEPROM_READ_WRITE_STEPS (EEPROM_CONTENT_SIZE / EEPROM_PAGE_SIZE) + 1
// ============================================================================================
// Variables
volatile EEPROM_Content_t _EEPROM_Content;
volatile bool _Update_Triggered;
volatile uint8_t _Write_Status;
volatile uint _Read_Write_Counter;
// ============================================================================================
// Function Declarations
void EEPROM_Read_Data();
bool EEPROM_Write_Data(uint section);
void EEPROM_Check_Content_Valid();
/*******************************************************************
Interrupt Service Routines
*******************************************************************/
/*******************************************************************
Functions
*******************************************************************/
void EEPROM_Init(void)
{
_Update_Triggered = false;
_Write_Status = EEPROM_STATUS_NONE;
_Read_Write_Counter = 0;
EEPROM_Read_Data();
EEPROM_Check_Content_Valid();
}
void EEPROM_Tick(void)
{
if(_Update_Triggered == true) {
// Wait 1ms to let other I2C traffic to be completed
sleep_ms(1);
EEPROM_Write_Data(_Read_Write_Counter);
_Read_Write_Counter++;
if(_Read_Write_Counter == EEPROM_READ_WRITE_STEPS) {
_Update_Triggered = false;
}
}
}
void EEPROM_Trigger_Update()
{
_Read_Write_Counter = 0;
_Update_Triggered = true;
}
uint8_t EEPROM_Get_Write_Status()
{
uint8_t Return_Value = _Write_Status;
_Write_Status = EEPROM_STATUS_NONE;
return Return_Value;
}
uint EEPROM_Get_Content_Size()
{
return EEPROM_CONTENT_SIZE;
}
uint EEPROM_Get_Read_Write_Steps()
{
return EEPROM_READ_WRITE_STEPS;
}
/*******************************************************************
Internal Functions
*******************************************************************/
void EEPROM_Read_Data(void)
{
for(uint i=0;i<EEPROM_READ_WRITE_STEPS;i++)
{
uint16_t EEPROM_Read_Address = i * EEPROM_PAGE_SIZE;
uint8_t* Read_Address = ((uint8_t*)&_EEPROM_Content) + i * EEPROM_PAGE_SIZE;
uint8_t Read_Size = EEPROM_CONTENT_SIZE - i * EEPROM_PAGE_SIZE;
if(Read_Size > EEPROM_PAGE_SIZE) {
Read_Size = EEPROM_PAGE_SIZE;
}
I2CM_Packet_Receive(EEPROM_I2C_ADDRESS, EEPROM_Read_Address, sizeof(EEPROM_Read_Address), Read_Address, Read_Size);
}
}
bool EEPROM_Write_Data(uint section)
{
uint16_t EEPROM_Write_Address = section * EEPROM_PAGE_SIZE;
uint8_t* Write_Address = ((uint8_t*)&_EEPROM_Content) + section * EEPROM_PAGE_SIZE;
uint8_t Write_Size = EEPROM_CONTENT_SIZE - section * EEPROM_PAGE_SIZE;
if(Write_Size > EEPROM_PAGE_SIZE) {
Write_Size = EEPROM_PAGE_SIZE;
}
int Bytes_Written = I2CM_Packet_Transmit(EEPROM_I2C_ADDRESS, EEPROM_Write_Address, sizeof(EEPROM_Write_Address), Write_Address, Write_Size);
if(Bytes_Written == sizeof(EEPROM_Write_Address) + Write_Size) {
_Write_Status = EEPROM_STATUS_WRITE_OK;
return true;
}
_Write_Status = EEPROM_STATUS_WRITE_FAILED;
return false;
}
void EEPROM_Check_Content_Valid()
{
if(_EEPROM_Content.Device_Configuration.Idle_Screen > IDLE_SCREEN_MODE_ACTIVITY) {
_EEPROM_Content.Device_Configuration.Idle_Screen = IDLE_SCREEN_BLACK;
}
if(_EEPROM_Content.Device_Configuration.Screen_Timeout > SCREEN_TIMEOUT_MAX_s) {
_EEPROM_Content.Device_Configuration.Screen_Timeout = SCREEN_TIMEOUT_MAX_s;
}
// Reverse Scrolling no need, as bool is compared with equal to 0
if(_EEPROM_Content.Channel_MIDI_Configuration[LED_Channel_1].MIDI_Channel > MIDI_CHANNEL_16) {
_EEPROM_Content.Channel_MIDI_Configuration[LED_Channel_1].MIDI_Channel = MIDI_CHANNEL_1;
}
if( _EEPROM_Content.Channel_MIDI_Configuration[LED_Channel_1].Octave > _MIDI_Note_List[MIDI_NOTE_LIST_LENGTH-1].Octave ||
_EEPROM_Content.Channel_MIDI_Configuration[LED_Channel_1].Octave < _MIDI_Note_List[0].Octave) {
_EEPROM_Content.Channel_MIDI_Configuration[LED_Channel_1].Octave = _MIDI_Note_List[0].Octave;
}
// Note Colors no need, as full range of UINT8 is valid
if(_EEPROM_Content.Channel_MIDI_Configuration[LED_Channel_1].Skip_Note_Off_Event > 1) {
_EEPROM_Content.Channel_MIDI_Configuration[LED_Channel_1].Skip_Note_Off_Event = 1;
}
// Pause Light Enabled no need, as bool is compared with equal to 0
// Pause Light Color no need, as full range of UINT8 is valid
if(_EEPROM_Content.Pause_Light_Configuration[LED_Channel_1].Timeout > PAUSE_LIGHT_DELAY_MAX_s) {
_EEPROM_Content.Pause_Light_Configuration[LED_Channel_1].Timeout = PAUSE_LIGHT_DELAY_MIN_s;
}
if(_EEPROM_Content.Pause_Light_Configuration[LED_Channel_1].Reset_Condition > CHANNEL_AND_EVENT_MATCH) {
_EEPROM_Content.Pause_Light_Configuration[LED_Channel_1].Reset_Condition = ANY_TRAFFIC;
}
if(_EEPROM_Content.Pause_Light_Configuration[LED_Channel_1].Fade_Speed > FADE_SPEED_MAX) {
_EEPROM_Content.Pause_Light_Configuration[LED_Channel_1].Fade_Speed = FADE_SPEED_MIN;
}
// Pause Light Timer and Active no need here
// Note Stack Enabled no need, as bool is compared with equal to 0
if(_EEPROM_Content.Jam_Light_Configuration.Duration_Max_s > DURATION_MAX_s) {
_EEPROM_Content.Jam_Light_Configuration.Duration_Max_s = DURATION_MAX_s;
}
if(_EEPROM_Content.Jam_Light_Configuration.Duration_Min_s > _EEPROM_Content.Jam_Light_Configuration.Duration_Max_s || _EEPROM_Content.Jam_Light_Configuration.Duration_Min_s < DURATION_MIN_s) {
_EEPROM_Content.Jam_Light_Configuration.Duration_Min_s = DURATION_MIN_s;
}
if(_EEPROM_Content.Jam_Light_Configuration.Duration_Max_s <= _EEPROM_Content.Jam_Light_Configuration.Duration_Min_s) {
_EEPROM_Content.Jam_Light_Configuration.Duration_Max_s = DURATION_MAX_s;
}
while(_EEPROM_Content.Jam_Light_Configuration.Hue_Angle_Start_Color < 0) {
_EEPROM_Content.Jam_Light_Configuration.Hue_Angle_Start_Color += HUE_MAX_ANGLE;
}
_EEPROM_Content.Jam_Light_Configuration.Hue_Angle_Start_Color %= HUE_MAX_ANGLE;
if(_EEPROM_Content.Jam_Light_Configuration.Color_Change > COLOR_CHANGE_MAX) {
_EEPROM_Content.Jam_Light_Configuration.Color_Change = COLOR_CHANGE_MIN;
}
if(_EEPROM_Content.Jam_Light_Configuration.Fade_Speed > FADE_SPEED_MAX) {
_EEPROM_Content.Jam_Light_Configuration.Fade_Speed = FADE_SPEED_MIN;
}
// Const Color no need, as full range of UINT8 is valid
if(_EEPROM_Content.Const_Light_Configuration.Fade_Speed > FADE_SPEED_MAX) {
_EEPROM_Content.Const_Light_Configuration.Fade_Speed = FADE_SPEED_MIN;
}
if(_EEPROM_Content.Device_Configuration.Transition_Type >= 0) {
_EEPROM_Content.Device_Configuration.Transition_Type = 0;
}
if(_EEPROM_Content.Device_Configuration.Transition_Frames == 0) {
_EEPROM_Content.Device_Configuration.Transition_Frames = 16;
}
}