Files
RP2350_MIDI_Lighter/Firmware/main.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

267 lines
7.4 KiB
C

/*
* main.c
*
* Created: Mon Nov 08 2021 14:06:53
* Author Chris
*/
// ============================================================================================
// Includes
#include <stdio.h>
#include "pico/stdlib.h"
#include "Core1.h"
#include "Core1_LED_Enable.h"
#include "I2C_Master.h"
#include "Command.h"
#include "UI_Control.h"
#include "Mode_Manager.h"
#include "INA260.h"
#include "Switch.h"
#include "EEPROM_M24C64.h"
#include "Rotary_Encoder.h"
#include "Display.h"
#include "Display_SPI.h"
#include "Display_Image.h"
#include "Screens.h"
#include "USB_Serial.h"
// ============================================================================================
// Defines
#define LEDG_PIN 12
#define LEDG_CONFIG gpio_init(LEDG_PIN); gpio_set_dir(LEDG_PIN, GPIO_OUT)
#define LEDG_ON gpio_put(LEDG_PIN, 0)
#define LEDG_OFF gpio_put(LEDG_PIN, 1)
#define LEDG_TOGGLE gpio_put(LEDG_PIN, !gpio_get(LEDG_PIN))
#define LEDG_ANIMATION_1 LEDG_ON; sleep_ms(100); LEDG_OFF; sleep_ms(100);
#define LEDG_ANIMATION_3 LEDG_ANIMATION_1; LEDG_ANIMATION_1; LEDG_ANIMATION_1
#define LEDR_PIN 11
#define LEDR_CONFIG gpio_init(LEDR_PIN); gpio_set_dir(LEDR_PIN, GPIO_OUT)
#define LEDR_ON gpio_put(LEDR_PIN, 0)
#define LEDR_OFF gpio_put(LEDR_PIN, 1)
#define LEDR_TOGGLE gpio_put(LEDR_PIN, !gpio_get(LEDR_PIN))
#define TRIGGER_PIN 18
#define TRIGGER_CONFIG gpio_init(TRIGGER_PIN); gpio_set_dir(TRIGGER_PIN, GPIO_OUT)
#define TRIGGER_ON gpio_put(TRIGGER_PIN, 1)
#define TRIGGER_OFF gpio_put(TRIGGER_PIN, 0)
// ============================================================================================
// Variables
static bool _Timer_Fired = false;
static struct repeating_timer _Timer;
extern uint16_t _Image_Power_Critical_32x32[];
extern uint16_t _Image_Power_Overvoltage_32x32[];
extern uint16_t _Image_Power_Undervoltage_32x32[];
extern uint16_t _Image_Power_Unplugged_32x32[];
// ============================================================================================
// Function Declarations
void Check_For_Serial_Input(void);
void Display_Start_Buffer_Readout(void);
/*******************************************************************
Interrupt Service Routines
*******************************************************************/
bool ISR_Repeating_Timer(struct repeating_timer *t)
{
LEDR_TOGGLE;
_Timer_Fired = true;
return true;
}
/*******************************************************************
Main Routine
*******************************************************************/
int main(void)
{
// LED =================================================
LEDG_CONFIG;
LEDR_CONFIG; LEDR_OFF;
LEDG_ANIMATION_3;
// Trigger =================================================
TRIGGER_CONFIG;
TRIGGER_OFF;
// USB Serial =================================================
USB_Serial_Init();
// I2C Master =============================================
I2CM_Init(I2C_NO_INTERNAL_PULLUP);
// EEPROM =================================================
EEPROM_Init();
// INA 260 =============================================
INA260_Init();
// Core 1 =================================================
multicore_launch_core1(Core1_Main);
// Command =================================================
Command_Init();
// UI Control =================================================
UI_Control_Init();
// Display =================================================
Display_Init(DISPLAY_COLOR_BLACK, true, false);
// Screen_Setup_Loading();
Screen_Setup_Menu_Main(TRANSITION_NONE, TRANSITION_NONE, LINEAR, 0, false, 3);
// Rotary Encoder =============================================
Rotary_Encoder_Init();
// Switch =================================================
Switch_Init(SWITCH_NO_INTERNAL_PULLUP);
// Mode Manager =============================================
Mode_Manager_Init();
// Repeating Timer =============================================
add_repeating_timer_ms(40, ISR_Repeating_Timer, NULL, &_Timer);
while (1)
{
if (_Timer_Fired == true)
{
_Timer_Fired = false;
Display_Send_Buffer();
Display_Inc_Frame_Counter();
Display_Screen_Transition_Tick();
_Screen_Tick();
UI_Control_Acceleration_Update(CURRENT_TIME_ms);
INA260_Read_BusVoltage();
INA260_Read_Current();
Command_Issue_Set_Request(MULTICORE_COMMAND_SET_INA260_BUSVOLTAGE, 0, INA260_Get_BusVoltage_mV());
}
// Add functions here to execute during the DMA Transfer
if(Display_SPI_DMA_Transfer_Ongoing())
{
}
if(Display_Send_Buffer_Completed())
{
TRIGGER_ON;
Command_Issue_Get_Request(MULTICORE_COMMAND_GET_LED_POWER_ERROR, 0);
Display_Render_Objects();
LED_Power_Error Error = Command_Get_Request_Response_By_Command_Only(MULTICORE_COMMAND_GET_LED_POWER_ERROR, 100);
uint16_t *Image = NULL;
switch (Error)
{
case BUS_NO_SUPPLY: Image = _Image_Power_Unplugged_32x32; break;
case BUS_UNDERVOLTAGE: Image = _Image_Power_Undervoltage_32x32; break;
case BUS_OVERVOLTAGE: Image = _Image_Power_Overvoltage_32x32; break;
case BUS_VOLTAGE_MEASUREMENT: Image = _Image_Power_Critical_32x32; break;
}
if(Image != NULL && Display_Screen_Transition_Ongoing() == false) {
Display_Image_Draw_Color(DISPLAY_X_CENTER + 50, 30, Image);
}
TRIGGER_OFF;
}
else
{
Check_For_Serial_Input();
if(Rotary_Encoder_Rotation_CW_Occurred()) {
Display_Action_CW();
}
if(Rotary_Encoder_Rotation_CCW_Occurred()) {
Display_Action_CCW();
}
if(Rotary_Encoder_Switch_Press_Occurred()) {
Display_Action_SW();
}
}
}
}
void Check_For_Serial_Input(void)
{
int Analog_Data = -1;
while(USB_Serial_Available())
{
uint8_t USB_Data = USB_Serial_Get_Byte();
switch(USB_Data)
{
case 'a':
USB_SERIAL_SEND_STRING("SPI Baudrate: ");
USB_Serial_Send_Int_Dec(Display_SPI_Get_Baudrate(), 10);
USB_SERIAL_SEND_TERMINATOR();
break;
case 'b': // New command for buffer readout
Display_Start_Buffer_Readout();
break;
case 'c':
Command_Issue_Get_Request(MULTICORE_COMMAND_GET_ANALOG_VOLTAGE, 0);
Analog_Data = Command_Get_Request_Response_By_Command_Only(MULTICORE_COMMAND_GET_ANALOG_VOLTAGE, 100);
USB_SERIAL_SEND_STRING("Analog: "); USB_Serial_Send_Int_Dec(Analog_Data, 5); USB_SERIAL_SEND_STRING("mV"); USB_SERIAL_SEND_TERMINATOR();
USB_SERIAL_SEND_STRING("INA260: "); USB_Serial_Send_Int_Dec(INA260_Get_BusVoltage_mV(), 5); USB_SERIAL_SEND_STRING("mV"); USB_SERIAL_SEND_TERMINATOR();
break;
default:
USB_SERIAL_SEND_STRING("Unknown Command: ");
USB_Serial_Put_Char(USB_Data);
USB_SERIAL_SEND_STRING(" (");
USB_Serial_Send_Int_Hex(USB_Data, 2, true);
USB_SERIAL_SEND_STRING(")");
USB_SERIAL_SEND_TERMINATOR();
break;
}
}
}
void Display_Start_Buffer_Readout(void)
{
cancel_repeating_timer(&_Timer);
// Send header
USB_SERIAL_SEND_STRING("IMGBUF");
USB_Serial_Send_Int_Dec(DISPLAY_WIDTH, 4);
USB_Serial_Put_Char(',');
USB_Serial_Send_Int_Dec(DISPLAY_HEIGHT, 4);
USB_Serial_Put_Char(',');
USB_Serial_Send_Int_Dec(16, 2);
USB_SERIAL_SEND_TERMINATOR();
uint32_t Pixel_Count = DISPLAY_WIDTH * DISPLAY_HEIGHT;
for(uint32_t i = 0; i < Pixel_Count; i++)
{
Display_Color Pixel = Display_Get_Pixel(i);
USB_Serial_Send_Int_Hex(Pixel, 4, false);
}
sleep_ms(100);
USB_SERIAL_SEND_TERMINATOR();
add_repeating_timer_ms(40, ISR_Repeating_Timer, NULL, &_Timer);
}