Skip to content

Commit 2f72600

Browse files
committed
Merge branch 'refractor/image-switching' into pmc+/release
2 parents de5dd55 + 9c0d62d commit 2f72600

File tree

9 files changed

+286
-57
lines changed

9 files changed

+286
-57
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ add_subdirectory(no-OS-FatFS-SD-SPI-RPi-Pico/FatFs_SPI PicoMemcard)
2020
target_sources(PicoMemcard PUBLIC
2121
${CMAKE_SOURCE_DIR}/src/led.c
2222
${CMAKE_SOURCE_DIR}/src/main.c
23+
${CMAKE_SOURCE_DIR}/src/memcard_manager.c
2324
${CMAKE_SOURCE_DIR}/src/memcard_simulator.c
2425
${CMAKE_SOURCE_DIR}/src/memory_card.c
2526
${CMAKE_SOURCE_DIR}/src/msc_handler.c

inc/config.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
#define TUD_MOUNT_TIMEOUT 3000 // max time (in ms) before giving up on MSC mode (USB) and starting memcard simulation
66
#define MSC_WRITE_SYNC_TIMEOUT 1 * 1000 // time (in ms) expired since last MSC write before exporting RAM disk into LFS
77
#define IDLE_AUTOSYNC_TIMEOUT 5 * 1000 // time (in ms) the memory card must be inactive before automatic sync from RAM to LFS
8-
#define MAX_MC_FILENAME_LEN 32 // max length of memory card file name
9-
#define MAX_MC_INDEX 255 // maximum number of different mc images
8+
#define MAX_MC_FILENAME_LEN 32 // max length of memory card file name (including extension)
9+
#define MAX_MC_IMAGES 255 // maximum number of different mc images
1010
#define MC_RECONNECT_TIME 1000 // time (in ms) the memory card stays disconnected when simulating reconnection
1111

1212
/* Board targeted by build */

inc/led.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@ void led_init();
77
void led_output_sync_status(bool out_of_sync);
88
void led_blink_error(int amount);
99
void led_output_mc_change();
10+
void led_output_end_mc_list();
1011

1112
#endif

inc/memcard_manager.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#ifndef __MEMCARD_MANAGER_H__
2+
#define __MEMCARD_MANAGER_H__
3+
4+
#include <stdint.h>
5+
#include <stdbool.h>
6+
7+
/* Error codes */
8+
#define MM_OK 0
9+
#define MM_ALLOC_FAIL 1
10+
#define MM_INDEX_OUT_OF_BOUNDS 2
11+
#define MM_NO_ENTRY 3
12+
13+
bool memcard_manager_exist(uint8_t* filename);
14+
uint32_t memcard_manager_count();
15+
uint32_t memcard_manager_get(uint32_t index, uint8_t* out_filename);
16+
#define memcard_manager_get_first(out_filename) memcard_manager_get(0, (out_filename))
17+
uint32_t memcard_manager_get_next(uint8_t* filename, uint8_t* out_nextfile);
18+
uint32_t memcard_manager_get_prev(uint8_t* filename, uint8_t* out_prevfile);
19+
uint32_t memcard_manager_create();
20+
21+
#endif

inc/memory_card.h

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,11 @@
2222

2323
/* Error codes */
2424
#define MC_OK 0
25-
#define MC_MOUNT_ERR 1
26-
#define MC_FILE_OPEN_ERR 2
27-
#define MC_FILE_READ_ERR 3
28-
#define MC_FILE_WRITE_ERR 4
29-
#define MC_FILE_SIZE_ERR 5
30-
#define MC_NO_INIT 6
25+
#define MC_FILE_OPEN_ERR 1
26+
#define MC_FILE_READ_ERR 2
27+
#define MC_FILE_WRITE_ERR 3
28+
#define MC_FILE_SIZE_ERR 4
29+
#define MC_NO_INIT 5
3130

3231
typedef struct {
3332
uint8_t flag_byte;

src/led.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,4 +85,22 @@ void led_output_mc_change() {
8585
sleep_ms(100);
8686
ws2812_put_rgb(0, 0, 0);
8787
#endif
88+
}
89+
90+
void led_output_end_mc_list() {
91+
#ifdef PICO
92+
for(int i = 0; i < 3; ++i) {
93+
gpio_put(PICO_LED_PIN, false);
94+
sleep_ms(100);
95+
gpio_put(PICO_LED_PIN, true);
96+
sleep_ms(100);
97+
gpio_put(PICO_LED_PIN, false);
98+
sleep_ms(100);
99+
}
100+
#endif
101+
#ifdef RP2040ZERO
102+
ws2812_put_rgb(255, 180, 90); // orange
103+
sleep_ms(100);
104+
ws2812_put_rgb(0, 0, 0);
105+
#endif
88106
}

src/memcard_manager.c

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
#include "memcard_manager.h"
2+
#include <stdlib.h>
3+
#include <string.h>
4+
#include "sd_config.h"
5+
#include "memory_card.h"
6+
7+
bool is_name_valid(uint8_t* filename) {
8+
if(!filename)
9+
return false;
10+
filename = strupr(filename); // convert to upper case
11+
/* check .MCR extension */
12+
uint8_t* ext = strrchr(filename, '.');
13+
if(!ext || strcmp(ext, ".MCR"))
14+
return false;
15+
/* check that filename (excluding extension) is only digits */
16+
uint32_t digit_char_count = strspn(filename, "0123456789");
17+
if(digit_char_count != strlen(filename) - strlen(".MCR"))
18+
return false;
19+
return true;
20+
}
21+
22+
bool is_image_valid(uint8_t* filename) {
23+
if(!filename)
24+
return false;
25+
filename = strupr(filename); // convert to upper case
26+
if(!is_name_valid(filename))
27+
return false;
28+
FILINFO f_info;
29+
FRESULT f_res = f_stat(filename, &f_info);
30+
if(f_res != FR_OK)
31+
return false;
32+
if(f_info.fsize != MC_SIZE) // check that memory card image has correct size
33+
return false;
34+
return true;
35+
}
36+
37+
bool memcard_manager_exist(uint8_t* filename) {
38+
if(!filename)
39+
return false;
40+
return is_image_valid(filename);
41+
}
42+
43+
uint32_t memcard_manager_count() {
44+
FRESULT res;
45+
DIR root;
46+
FILINFO f_info;
47+
res = f_opendir(&root, ""); // open root directory
48+
uint32_t count = 0;
49+
if(res == FR_OK) {
50+
while(true) {
51+
res = f_readdir(&root, &f_info);
52+
if(res != FR_OK || f_info.fname[0] == 0) break;
53+
if(!(f_info.fattrib & AM_DIR)) { // not a directory
54+
if(is_image_valid(f_info.fname))
55+
++count;
56+
}
57+
}
58+
}
59+
return count;
60+
}
61+
62+
uint32_t memcard_manager_get(uint32_t index, uint8_t* out_filename) {
63+
if(index < 0 || index > MAX_MC_IMAGES)
64+
return MM_INDEX_OUT_OF_BOUNDS;
65+
uint32_t count = memcard_manager_count();
66+
if(index >= count)
67+
return MM_INDEX_OUT_OF_BOUNDS;
68+
uint8_t* image_names = malloc(((MAX_MC_FILENAME_LEN + 1) * count)); // allocate space for image names
69+
if(!image_names)
70+
return MM_ALLOC_FAIL; // malloc failed
71+
/* retrive images names */
72+
FRESULT res;
73+
DIR root;
74+
FILINFO f_info;
75+
res = f_opendir(&root, ""); // open root directory
76+
uint32_t i = 0;
77+
if(res == FR_OK) {
78+
while(true) {
79+
res = f_readdir(&root, &f_info);
80+
if(res != FR_OK || f_info.fname[0] == 0) break;
81+
if(!(f_info.fattrib & AM_DIR)) { // not a directory
82+
if(is_image_valid(f_info.fname)) {
83+
strcpy(&image_names[(MAX_MC_FILENAME_LEN + 1) * i], f_info.fname);
84+
++i;
85+
}
86+
}
87+
}
88+
}
89+
/* sort names alphabetically */
90+
qsort(image_names, count, (MAX_MC_FILENAME_LEN + 1), (__compar_fn_t) strcmp);
91+
strcpy(out_filename, &image_names[(MAX_MC_FILENAME_LEN + 1) * index]);
92+
free(image_names); // free allocated memory
93+
return MM_OK;
94+
}
95+
96+
uint32_t memcard_manager_get_next(uint8_t* filename, uint8_t* out_nextfile) {
97+
uint32_t count = memcard_manager_count();
98+
uint32_t buff_size = (MAX_MC_FILENAME_LEN + 1) * count;
99+
uint8_t* image_names = malloc(buff_size); // allocate space for image names
100+
if(!image_names)
101+
return MM_ALLOC_FAIL; // malloc failed
102+
/* retrive images names */
103+
FRESULT res;
104+
DIR root;
105+
FILINFO f_info;
106+
res = f_opendir(&root, ""); // open root directory
107+
uint32_t i = 0;
108+
if(res == FR_OK) {
109+
while(true) {
110+
res = f_readdir(&root, &f_info);
111+
if(res != FR_OK || f_info.fname[0] == 0) break;
112+
if(!(f_info.fattrib & AM_DIR)) { // not a directory
113+
if(is_image_valid(f_info.fname)) {
114+
strcpy(&image_names[(MAX_MC_FILENAME_LEN + 1) * i], f_info.fname);
115+
++i;
116+
}
117+
}
118+
}
119+
}
120+
/* sort names alphabetically */
121+
qsort(image_names, count, (MAX_MC_FILENAME_LEN + 1), (__compar_fn_t) strcmp);
122+
/* find current and return following one */
123+
bool found = false;
124+
for(uint32_t i = 0; i < buff_size; i = i + (MAX_MC_FILENAME_LEN + 1)) {
125+
if(!strcmp(filename, &image_names[i])) {
126+
int32_t next_i = i + (MAX_MC_FILENAME_LEN + 1);
127+
if(next_i < buff_size) {
128+
strcpy(out_nextfile, &image_names[next_i]);
129+
found = true;
130+
break;
131+
}
132+
}
133+
}
134+
free(image_names); // free allocated memory
135+
/* return */
136+
if(found)
137+
return MM_OK;
138+
else
139+
return MM_NO_ENTRY;
140+
}
141+
142+
uint32_t memcard_manager_get_prev(uint8_t* filename, uint8_t* out_prevfile) {
143+
uint32_t count = memcard_manager_count();
144+
uint32_t buff_size = (MAX_MC_FILENAME_LEN + 1) * count;
145+
uint8_t* image_names = malloc(buff_size); // allocate space for image names
146+
if(!image_names)
147+
return MM_ALLOC_FAIL; // malloc failed
148+
/* retrive images names */
149+
FRESULT res;
150+
DIR root;
151+
FILINFO f_info;
152+
res = f_opendir(&root, ""); // open root directory
153+
uint32_t i = 0;
154+
if(res == FR_OK) {
155+
while(true) {
156+
res = f_readdir(&root, &f_info);
157+
if(res != FR_OK || f_info.fname[0] == 0) break;
158+
if(!(f_info.fattrib & AM_DIR)) { // not a directory
159+
if(is_image_valid(f_info.fname)) {
160+
strcpy(&image_names[(MAX_MC_FILENAME_LEN + 1) * i], f_info.fname);
161+
++i;
162+
}
163+
}
164+
}
165+
}
166+
/* sort names alphabetically */
167+
qsort(image_names, count, (MAX_MC_FILENAME_LEN + 1), (__compar_fn_t) strcmp);
168+
/* find current and return prior one */
169+
bool found = false;
170+
for(uint32_t i = 0; i < buff_size; i = i + (MAX_MC_FILENAME_LEN + 1)) {
171+
if(!strcmp(filename, &image_names[i])) {
172+
int32_t prev_i = i - (MAX_MC_FILENAME_LEN + 1);
173+
if(prev_i >= 0) {
174+
strcpy(out_prevfile, &image_names[prev_i]);
175+
found = true;
176+
break;
177+
}
178+
}
179+
}
180+
free(image_names); // free allocated memory
181+
/* return */
182+
if(found)
183+
return MM_OK;
184+
else
185+
return MM_NO_ENTRY;
186+
}
187+
188+
uint32_t memcard_manager_create() {
189+
190+
}

0 commit comments

Comments
 (0)