Skip to content

Commit

Permalink
Merge pull request #781 from Daft-Freak/user-i2c-2
Browse files Browse the repository at this point in the history
User I2C support v2
  • Loading branch information
Gadgetoid authored Sep 27, 2022
2 parents 65d0bfd + e0133c9 commit e792895
Show file tree
Hide file tree
Showing 7 changed files with 270 additions and 106 deletions.
1 change: 1 addition & 0 deletions 32blit-stm32/Inc/32blit.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ bool blit_user_code_running();
extern "C" void blit_reset_with_error();
void blit_enable_user_code();
void blit_disable_user_code();
bool blit_user_code_disabled();
RawMetadata *blit_get_running_game_metadata();

void blit_menu_update(uint32_t time);
Expand Down
3 changes: 3 additions & 0 deletions 32blit-stm32/Inc/32blit/i2c.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,7 @@
namespace i2c {
void init();
void tick();

bool user_send(uint8_t address, uint8_t reg, const uint8_t *data, uint16_t len);
bool user_receive(uint8_t address, uint8_t reg, uint8_t *data, uint16_t len);
}
11 changes: 10 additions & 1 deletion 32blit-stm32/Inc/CDCCommandStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,18 @@ class CDCCommandStream
void Stream(void);
uint8_t Stream(uint8_t *data, uint32_t len);

void SetParsingEnabled(bool enabled);

uint32_t Read(uint8_t *data, uint32_t len);

// USB Packet fifo
uint8_t *GetFifoWriteBuffer(void);
void ReleaseFifoWriteBuffer(uint8_t uLen);
CDCFifoElement *GetFifoReadElement(void);
void ReleaseFifoReadElement(void);

private:
typedef enum { stDetect, stDetectCommandWord, stDispatch, stProcessing, stError } StreamState;
typedef enum { stDetect, stDetectCommandWord, stDispatch, stProcessing, stError, stDisabled } StreamState;

StreamState m_state;

Expand All @@ -63,15 +67,20 @@ class CDCCommandStream

CDCDataStream m_dataStream;

uint32_t uLastResumeTime;

CDCFifoElement m_fifoElements[CDC_FIFO_BUFFERS];
uint8_t m_uFifoReadPos;
uint8_t m_uFifoWritePos;

bool m_bNeedsUSBResume;

uint8_t m_uCurElementOff = 0;


void LogTimeTaken(CDCCommandHandler::StreamResult result, uint32_t uBytesHandled);

void Resume();
};

#endif /* SRC_CDCCOMMANDSTREAM_H_ */
186 changes: 108 additions & 78 deletions 32blit-stm32/Src/32blit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "power.hpp"
#include "quadspi.hpp"

#include "CDCCommandStream.h"
#include "tim.h"
#include "rng.h"
#include "ff.h"
Expand All @@ -31,6 +32,7 @@ using namespace blit;

extern USBD_HandleTypeDef hUsbDeviceHS;
extern USBManager g_usbManager;
extern CDCCommandStream g_commandStream;

FATFS filesystem;
static bool fs_mounted = false;
Expand Down Expand Up @@ -81,19 +83,28 @@ static void init_api_shared() {
api.channels[i] = AudioChannel();

api.message_received = nullptr;
api.i2c_completed = nullptr;

// take CDC back
g_commandStream.SetParsingEnabled(true);
}

bool g_bConsumerConnected = true;
void blit_debug(const char *message) {
if(g_usbManager.GetType() == USBManager::usbtCDC)
{

static bool set_raw_cdc_enabled(bool enabled) {
g_commandStream.SetParsingEnabled(!enabled);
return true;
}

static void cdc_write(const uint8_t *data, uint16_t len) {
if(g_usbManager.GetType() == USBManager::usbtCDC) {
// The mad STM CDC implementation relies on a USB packet being received to set TxState
// Also calls to CDC_Transmit_HS do not buffer the data so we have to rely on TxState before sending new data.
// So if there is no consumer running at the other end we will hang, so we need to check for this
if(g_bConsumerConnected)
{
uint32_t tickstart = HAL_GetTick();
while(g_bConsumerConnected && CDC_Transmit_HS((uint8_t *)message, strlen(message)) == USBD_BUSY)
while(g_bConsumerConnected && CDC_Transmit_HS((uint8_t *)data, len) == USBD_BUSY)
g_bConsumerConnected = !(HAL_GetTick() > (tickstart + 2));
}
else
Expand All @@ -104,6 +115,14 @@ void blit_debug(const char *message) {
}
}

static uint16_t cdc_read(uint8_t *data, uint16_t len) {
return g_commandStream.Read(data, len);
}

void blit_debug(const char *message) {
cdc_write((uint8_t *)message, strlen(message));
}

void blit_exit(bool is_error) {
if(is_error)
blit_reset_with_error(); // likely an abort
Expand Down Expand Up @@ -299,98 +318,105 @@ static void save_screenshot() {
}

void blit_init() {
// enable backup sram
__HAL_RCC_RTC_ENABLE();
__HAL_RCC_BKPRAM_CLK_ENABLE();
HAL_PWR_EnableBkUpAccess();
HAL_PWREx_EnableBkUpReg();

// need to wit for sram, I tried a few things I found on the net to wait
// based on PWR flags but none seemed to work, a simple delay does work!
HAL_Delay(5);

if(persist.magic_word != persistence_magic_word) {
// Set persistent defaults if the magic word does not match
persist.magic_word = persistence_magic_word;
persist.volume = 0.5f;
persist.backlight = 1.0f;
persist.selected_menu_item = 0;
persist.reset_target = prtFirmware;
persist.reset_error = false;
persist.last_game_offset = 0;
memset(persist.launch_path, 0, sizeof(persist.launch_path));

// clear LTDC buffer to avoid flash of uninitialised data
extern char __ltdc_start;
int len = 320 * 240 * 2;
memset(&__ltdc_start, 0, len);
}
// enable backup sram
__HAL_RCC_RTC_ENABLE();
__HAL_RCC_BKPRAM_CLK_ENABLE();
HAL_PWR_EnableBkUpAccess();
HAL_PWREx_EnableBkUpReg();

// need to wit for sram, I tried a few things I found on the net to wait
// based on PWR flags but none seemed to work, a simple delay does work!
HAL_Delay(5);

if(persist.magic_word != persistence_magic_word) {
// Set persistent defaults if the magic word does not match
persist.magic_word = persistence_magic_word;
persist.volume = 0.5f;
persist.backlight = 1.0f;
persist.selected_menu_item = 0;
persist.reset_target = prtFirmware;
persist.reset_error = false;
persist.last_game_offset = 0;
memset(persist.launch_path, 0, sizeof(persist.launch_path));

// clear LTDC buffer to avoid flash of uninitialised data
extern char __ltdc_start;
int len = 320 * 240 * 2;
memset(&__ltdc_start, 0, len);
}

// don't switch to game if it crashed, or home is held
if(persist.reset_target == prtGame && (gpio::read(BUTTON_HOME_GPIO_Port, BUTTON_HOME_Pin) || persist.reset_error))
persist.reset_target = prtFirmware;
// don't switch to game if it crashed, or home is held
if(persist.reset_target == prtGame && (gpio::read(BUTTON_HOME_GPIO_Port, BUTTON_HOME_Pin) || persist.reset_error))
persist.reset_target = prtFirmware;

init_api_shared();
init_api_shared();

blit_update_volume();
blit_update_volume();

// enable cycle counting
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CYCCNT = 0;
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
// enable cycle counting
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CYCCNT = 0;
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;

fs_mounted = f_mount(&filesystem, "", 1) == FR_OK; // this shouldn't be necessary here right?
fs_mounted = f_mount(&filesystem, "", 1) == FR_OK; // this shouldn't be necessary here right?

i2c::init();
i2c::init();

blit::api.version_major = api_version_major;
blit::api.version_minor = api_version_minor;
blit::api.version_major = api_version_major;
blit::api.version_minor = api_version_minor;

blit::api.debug = blit_debug;
blit::api.now = HAL_GetTick;
blit::api.random = HAL_GetRandom;
blit::api.exit = blit_exit;
blit::api.debug = blit_debug;
blit::api.now = HAL_GetTick;
blit::api.random = HAL_GetRandom;
blit::api.exit = blit_exit;

blit::api.set_screen_mode = display::set_screen_mode;
blit::api.set_screen_palette = display::set_screen_palette;
blit::api.set_screen_mode_format = display::set_screen_mode_format;
blit::api.set_screen_mode = display::set_screen_mode;
blit::api.set_screen_palette = display::set_screen_palette;
blit::api.set_screen_mode_format = display::set_screen_mode_format;

display::set_screen_mode(blit::lores);
display::set_screen_mode(blit::lores);

blit::update = ::update;
blit::render = ::render;
blit::init = ::init;
blit::update = ::update;
blit::render = ::render;
blit::init = ::init;

blit::api.open_file = ::open_file;
blit::api.read_file = ::read_file;
blit::api.write_file = ::write_file;
blit::api.close_file = ::close_file;
blit::api.get_file_length = ::get_file_length;
blit::api.list_files = ::list_files;
blit::api.file_exists = ::file_exists;
blit::api.directory_exists = ::directory_exists;
blit::api.create_directory = ::create_directory;
blit::api.rename_file = ::rename_file;
blit::api.remove_file = ::remove_file;
blit::api.get_save_path = ::get_save_path;
blit::api.is_storage_available = blit_sd_mounted;

blit::api.open_file = ::open_file;
blit::api.read_file = ::read_file;
blit::api.write_file = ::write_file;
blit::api.close_file = ::close_file;
blit::api.get_file_length = ::get_file_length;
blit::api.list_files = ::list_files;
blit::api.file_exists = ::file_exists;
blit::api.directory_exists = ::directory_exists;
blit::api.create_directory = ::create_directory;
blit::api.rename_file = ::rename_file;
blit::api.remove_file = ::remove_file;
blit::api.get_save_path = ::get_save_path;
blit::api.is_storage_available = blit_sd_mounted;
blit::api.enable_us_timer = ::enable_us_timer;
blit::api.get_us_timer = ::get_us_timer;
blit::api.get_max_us_timer = ::get_max_us_timer;

blit::api.enable_us_timer = ::enable_us_timer;
blit::api.get_us_timer = ::get_us_timer;
blit::api.get_max_us_timer = ::get_max_us_timer;
blit::api.decode_jpeg_buffer = blit_decode_jpeg_buffer;
blit::api.decode_jpeg_file = blit_decode_jpeg_file;

blit::api.decode_jpeg_buffer = blit_decode_jpeg_buffer;
blit::api.decode_jpeg_file = blit_decode_jpeg_file;
blit::api.get_launch_path = ::get_launch_path;

blit::api.get_launch_path = ::get_launch_path;
blit::api.is_multiplayer_connected = multiplayer::is_connected;
blit::api.set_multiplayer_enabled = multiplayer::set_enabled;
blit::api.send_message = multiplayer::send_message;

blit::api.is_multiplayer_connected = multiplayer::is_connected;
blit::api.set_multiplayer_enabled = multiplayer::set_enabled;
blit::api.send_message = multiplayer::send_message;
blit::api.get_metadata = ::get_metadata;

blit::api.get_metadata = ::get_metadata;
blit::api.tick_function_changed = false;

blit::api.tick_function_changed = false;
blit::api.i2c_send = i2c::user_send;
blit::api.i2c_receive = i2c::user_receive;

blit::api.set_raw_cdc_enabled = set_raw_cdc_enabled;
blit::api.cdc_write = cdc_write;
blit::api.cdc_read = cdc_read;

display::init();

Expand Down Expand Up @@ -732,6 +758,10 @@ void blit_disable_user_code() {
user_code_disabled = true;
}

bool blit_user_code_disabled() {
return user_code_disabled;
}

RawMetadata *blit_get_running_game_metadata() {
if(!blit_user_code_running())
return nullptr;
Expand Down
Loading

0 comments on commit e792895

Please sign in to comment.