Skip to content

Commit

Permalink
Merge branch 'refractor/image-switching' into pmc+/release
Browse files Browse the repository at this point in the history
  • Loading branch information
dangiu committed Aug 25, 2022
2 parents de5dd55 + 9c0d62d commit 2f72600
Show file tree
Hide file tree
Showing 9 changed files with 286 additions and 57 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ add_subdirectory(no-OS-FatFS-SD-SPI-RPi-Pico/FatFs_SPI PicoMemcard)
target_sources(PicoMemcard PUBLIC
${CMAKE_SOURCE_DIR}/src/led.c
${CMAKE_SOURCE_DIR}/src/main.c
${CMAKE_SOURCE_DIR}/src/memcard_manager.c
${CMAKE_SOURCE_DIR}/src/memcard_simulator.c
${CMAKE_SOURCE_DIR}/src/memory_card.c
${CMAKE_SOURCE_DIR}/src/msc_handler.c
Expand Down
4 changes: 2 additions & 2 deletions inc/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
#define TUD_MOUNT_TIMEOUT 3000 // max time (in ms) before giving up on MSC mode (USB) and starting memcard simulation
#define MSC_WRITE_SYNC_TIMEOUT 1 * 1000 // time (in ms) expired since last MSC write before exporting RAM disk into LFS
#define IDLE_AUTOSYNC_TIMEOUT 5 * 1000 // time (in ms) the memory card must be inactive before automatic sync from RAM to LFS
#define MAX_MC_FILENAME_LEN 32 // max length of memory card file name
#define MAX_MC_INDEX 255 // maximum number of different mc images
#define MAX_MC_FILENAME_LEN 32 // max length of memory card file name (including extension)
#define MAX_MC_IMAGES 255 // maximum number of different mc images
#define MC_RECONNECT_TIME 1000 // time (in ms) the memory card stays disconnected when simulating reconnection

/* Board targeted by build */
Expand Down
1 change: 1 addition & 0 deletions inc/led.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ void led_init();
void led_output_sync_status(bool out_of_sync);
void led_blink_error(int amount);
void led_output_mc_change();
void led_output_end_mc_list();

#endif
21 changes: 21 additions & 0 deletions inc/memcard_manager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#ifndef __MEMCARD_MANAGER_H__
#define __MEMCARD_MANAGER_H__

#include <stdint.h>
#include <stdbool.h>

/* Error codes */
#define MM_OK 0
#define MM_ALLOC_FAIL 1
#define MM_INDEX_OUT_OF_BOUNDS 2
#define MM_NO_ENTRY 3

bool memcard_manager_exist(uint8_t* filename);
uint32_t memcard_manager_count();
uint32_t memcard_manager_get(uint32_t index, uint8_t* out_filename);
#define memcard_manager_get_first(out_filename) memcard_manager_get(0, (out_filename))
uint32_t memcard_manager_get_next(uint8_t* filename, uint8_t* out_nextfile);
uint32_t memcard_manager_get_prev(uint8_t* filename, uint8_t* out_prevfile);
uint32_t memcard_manager_create();

#endif
11 changes: 5 additions & 6 deletions inc/memory_card.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,11 @@

/* Error codes */
#define MC_OK 0
#define MC_MOUNT_ERR 1
#define MC_FILE_OPEN_ERR 2
#define MC_FILE_READ_ERR 3
#define MC_FILE_WRITE_ERR 4
#define MC_FILE_SIZE_ERR 5
#define MC_NO_INIT 6
#define MC_FILE_OPEN_ERR 1
#define MC_FILE_READ_ERR 2
#define MC_FILE_WRITE_ERR 3
#define MC_FILE_SIZE_ERR 4
#define MC_NO_INIT 5

typedef struct {
uint8_t flag_byte;
Expand Down
18 changes: 18 additions & 0 deletions src/led.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,22 @@ void led_output_mc_change() {
sleep_ms(100);
ws2812_put_rgb(0, 0, 0);
#endif
}

void led_output_end_mc_list() {
#ifdef PICO
for(int i = 0; i < 3; ++i) {
gpio_put(PICO_LED_PIN, false);
sleep_ms(100);
gpio_put(PICO_LED_PIN, true);
sleep_ms(100);
gpio_put(PICO_LED_PIN, false);
sleep_ms(100);
}
#endif
#ifdef RP2040ZERO
ws2812_put_rgb(255, 180, 90); // orange
sleep_ms(100);
ws2812_put_rgb(0, 0, 0);
#endif
}
190 changes: 190 additions & 0 deletions src/memcard_manager.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
#include "memcard_manager.h"
#include <stdlib.h>
#include <string.h>
#include "sd_config.h"
#include "memory_card.h"

bool is_name_valid(uint8_t* filename) {
if(!filename)
return false;
filename = strupr(filename); // convert to upper case
/* check .MCR extension */
uint8_t* ext = strrchr(filename, '.');
if(!ext || strcmp(ext, ".MCR"))
return false;
/* check that filename (excluding extension) is only digits */
uint32_t digit_char_count = strspn(filename, "0123456789");
if(digit_char_count != strlen(filename) - strlen(".MCR"))
return false;
return true;
}

bool is_image_valid(uint8_t* filename) {
if(!filename)
return false;
filename = strupr(filename); // convert to upper case
if(!is_name_valid(filename))
return false;
FILINFO f_info;
FRESULT f_res = f_stat(filename, &f_info);
if(f_res != FR_OK)
return false;
if(f_info.fsize != MC_SIZE) // check that memory card image has correct size
return false;
return true;
}

bool memcard_manager_exist(uint8_t* filename) {
if(!filename)
return false;
return is_image_valid(filename);
}

uint32_t memcard_manager_count() {
FRESULT res;
DIR root;
FILINFO f_info;
res = f_opendir(&root, ""); // open root directory
uint32_t count = 0;
if(res == FR_OK) {
while(true) {
res = f_readdir(&root, &f_info);
if(res != FR_OK || f_info.fname[0] == 0) break;
if(!(f_info.fattrib & AM_DIR)) { // not a directory
if(is_image_valid(f_info.fname))
++count;
}
}
}
return count;
}

uint32_t memcard_manager_get(uint32_t index, uint8_t* out_filename) {
if(index < 0 || index > MAX_MC_IMAGES)
return MM_INDEX_OUT_OF_BOUNDS;
uint32_t count = memcard_manager_count();
if(index >= count)
return MM_INDEX_OUT_OF_BOUNDS;
uint8_t* image_names = malloc(((MAX_MC_FILENAME_LEN + 1) * count)); // allocate space for image names
if(!image_names)
return MM_ALLOC_FAIL; // malloc failed
/* retrive images names */
FRESULT res;
DIR root;
FILINFO f_info;
res = f_opendir(&root, ""); // open root directory
uint32_t i = 0;
if(res == FR_OK) {
while(true) {
res = f_readdir(&root, &f_info);
if(res != FR_OK || f_info.fname[0] == 0) break;
if(!(f_info.fattrib & AM_DIR)) { // not a directory
if(is_image_valid(f_info.fname)) {
strcpy(&image_names[(MAX_MC_FILENAME_LEN + 1) * i], f_info.fname);
++i;
}
}
}
}
/* sort names alphabetically */
qsort(image_names, count, (MAX_MC_FILENAME_LEN + 1), (__compar_fn_t) strcmp);
strcpy(out_filename, &image_names[(MAX_MC_FILENAME_LEN + 1) * index]);
free(image_names); // free allocated memory
return MM_OK;
}

uint32_t memcard_manager_get_next(uint8_t* filename, uint8_t* out_nextfile) {
uint32_t count = memcard_manager_count();
uint32_t buff_size = (MAX_MC_FILENAME_LEN + 1) * count;
uint8_t* image_names = malloc(buff_size); // allocate space for image names
if(!image_names)
return MM_ALLOC_FAIL; // malloc failed
/* retrive images names */
FRESULT res;
DIR root;
FILINFO f_info;
res = f_opendir(&root, ""); // open root directory
uint32_t i = 0;
if(res == FR_OK) {
while(true) {
res = f_readdir(&root, &f_info);
if(res != FR_OK || f_info.fname[0] == 0) break;
if(!(f_info.fattrib & AM_DIR)) { // not a directory
if(is_image_valid(f_info.fname)) {
strcpy(&image_names[(MAX_MC_FILENAME_LEN + 1) * i], f_info.fname);
++i;
}
}
}
}
/* sort names alphabetically */
qsort(image_names, count, (MAX_MC_FILENAME_LEN + 1), (__compar_fn_t) strcmp);
/* find current and return following one */
bool found = false;
for(uint32_t i = 0; i < buff_size; i = i + (MAX_MC_FILENAME_LEN + 1)) {
if(!strcmp(filename, &image_names[i])) {
int32_t next_i = i + (MAX_MC_FILENAME_LEN + 1);
if(next_i < buff_size) {
strcpy(out_nextfile, &image_names[next_i]);
found = true;
break;
}
}
}
free(image_names); // free allocated memory
/* return */
if(found)
return MM_OK;
else
return MM_NO_ENTRY;
}

uint32_t memcard_manager_get_prev(uint8_t* filename, uint8_t* out_prevfile) {
uint32_t count = memcard_manager_count();
uint32_t buff_size = (MAX_MC_FILENAME_LEN + 1) * count;
uint8_t* image_names = malloc(buff_size); // allocate space for image names
if(!image_names)
return MM_ALLOC_FAIL; // malloc failed
/* retrive images names */
FRESULT res;
DIR root;
FILINFO f_info;
res = f_opendir(&root, ""); // open root directory
uint32_t i = 0;
if(res == FR_OK) {
while(true) {
res = f_readdir(&root, &f_info);
if(res != FR_OK || f_info.fname[0] == 0) break;
if(!(f_info.fattrib & AM_DIR)) { // not a directory
if(is_image_valid(f_info.fname)) {
strcpy(&image_names[(MAX_MC_FILENAME_LEN + 1) * i], f_info.fname);
++i;
}
}
}
}
/* sort names alphabetically */
qsort(image_names, count, (MAX_MC_FILENAME_LEN + 1), (__compar_fn_t) strcmp);
/* find current and return prior one */
bool found = false;
for(uint32_t i = 0; i < buff_size; i = i + (MAX_MC_FILENAME_LEN + 1)) {
if(!strcmp(filename, &image_names[i])) {
int32_t prev_i = i - (MAX_MC_FILENAME_LEN + 1);
if(prev_i >= 0) {
strcpy(out_prevfile, &image_names[prev_i]);
found = true;
break;
}
}
}
free(image_names); // free allocated memory
/* return */
if(found)
return MM_OK;
else
return MM_NO_ENTRY;
}

uint32_t memcard_manager_create() {

}
Loading

0 comments on commit 2f72600

Please sign in to comment.