8 #include "cfs-coffee-arch.h"
10 #include "pb_encode.h"
15 #include "cc1120-arch.h"
24 #define CONFIG_FILENAME "conf"
29 #define FILENAME_LENGTH COFFEE_NAME_LENGTH
33 _Static_assert(strlen(CONFIG_FILENAME) <= (FILENAME_LENGTH - 1),
"FILENAME_LENGTH too small to store config filename");
37 _Static_assert((
COFFEE_SIZE /
COFFEE_PAGE_SIZE) <= (pow(10.0, (
double) FILENAME_LENGTH - 1) - 1),
"FILENAME_LENGTH too small to store all samples");
51 static const uint8_t END_CANARY = 0xAF;
56 static uint16_t last_id;
61 static void radio_lock(
void);
66 static void radio_release(
void);
71 static uint16_t find_latest_sample(
void);
78 static uint8_t read_file(
char *filename, uint8_t *buffer, uint8_t length);
85 static bool write_file(
char *filename, uint8_t *buffer, uint8_t length);
91 static char* id_to_file(uint16_t
id,
char* filename);
98 static bool file_to_id(
char *filename, uint16_t *
id);
101 pb_ostream_t pb_ostream;
102 uint8_t pb_buffer[Sample_size];
103 char filename[FILENAME_LENGTH];
107 sample->id = last_id;
109 DEBUG(
"Attempting to save reading with id %d\n", last_id);
111 pb_ostream = pb_ostream_from_buffer(pb_buffer,
sizeof(pb_buffer));
112 if (!pb_encode_delimited(&pb_ostream, Sample_fields, sample)) {
119 if (!write_file(id_to_file(last_id, filename), pb_buffer, pb_ostream.bytes_written)) {
120 DEBUG(
"Failed to save reading %d\n", last_id);
140 pb_istream_t pb_istream;
141 uint8_t pb_buffer[Sample_size];
147 pb_istream = pb_istream_from_buffer(pb_buffer,
sizeof(pb_buffer));
148 if (!pb_decode_delimited(&pb_istream, Sample_fields, sample)) {
156 char filename[FILENAME_LENGTH];
159 DEBUG(
"Attempting to get sample %d\n",
id);
163 bytes = read_file(id_to_file(
id, filename), buffer, Sample_size);
176 char filename[FILENAME_LENGTH];
179 DEBUG(
"Attempting to delete invalid sample %d\n", sample);
183 DEBUG(
"Attempting to delete sample %d\n", sample);
185 id_to_file(sample, filename);
190 DEBUG(
"Error deleting sample %d\n", sample);
196 if (sample == last_id) {
197 DEBUG(
"Sample %d is last known sample. Searching for previous sample...\n", sample);
201 id_to_file(last_id, filename);
207 id_to_file(last_id, filename);
213 DEBUG(
"Sample %d deleted. Last_id is now %d\n", sample, last_id);
221 pb_ostream_t pb_ostream;
222 uint8_t pb_buffer[SensorConfig_size];
224 DEBUG(
"Attempting to save config\n");
226 pb_ostream = pb_ostream_from_buffer(pb_buffer,
sizeof(pb_buffer));
228 if (!pb_encode_delimited(&pb_ostream, SensorConfig_fields, config)) {
236 DEBUG(
"Error deleting old config\n");
239 if (!write_file(CONFIG_FILENAME, pb_buffer, pb_ostream.bytes_written)) {
250 pb_istream_t pb_istream;
251 uint8_t pb_buffer[SensorConfig_size];
257 pb_istream = pb_istream_from_buffer(pb_buffer,
sizeof(pb_buffer));
259 return pb_decode_delimited(&pb_istream, SensorConfig_fields, config);
265 DEBUG(
"Attempting to get config\n");
269 bytes = read_file(CONFIG_FILENAME, buffer, SensorConfig_size);
276 uint8_t read_file(
char *filename, uint8_t *buffer, uint8_t length) {
280 DEBUG(
"Failed to open file %s\n", filename);
284 uint8_t bytes = cfs_read(fd, buffer, length);
289 DEBUG(
"Failed to read file %s\n", filename);
294 if (buffer[bytes-1] == END_CANARY) {
298 DEBUG(
"%d bytes read\n", bytes);
303 bool write_file(
char *filename, uint8_t *buffer, uint8_t length) {
308 DEBUG(
"Failed to reserve space for file %s\n", filename);
314 DEBUG(
"Failed to open file %s for writing\n", filename);
321 bytes = cfs_write(fd, buffer, length);
323 if (bytes != length) {
324 DEBUG(
"Failed to write file to %s, wrote %d bytes\n", filename, bytes);
329 if (cfs_write(fd, &END_CANARY, 1) == -1) {
330 DEBUG(
"Failed to write trailing canary to file %s\n", filename);
334 DEBUG(
"%d bytes written\n", bytes);
340 DEBUG(
"Initializing...\n");
342 last_id = find_latest_sample();
344 printf(
"Store initialized. %d previous files found.\n", last_id);
347 void radio_lock(
void) {
350 cc1120_arch_interrupt_disable();
352 DEBUG(
"Radio Locked\n");
356 void radio_release(
void) {
358 CC1120_RELEASE_SPI();
359 cc1120_arch_interrupt_enable();
361 DEBUG(
"Radio Unlocked\n");
365 uint16_t find_latest_sample(
void) {
366 struct cfs_dirent dirent;
370 DEBUG(
"Refreshing filename cache\n");
377 if (file_to_id(dirent.name, &file_id)) {
379 if(file_id > max_id) {
393 char* id_to_file(uint16_t
id,
char* filename) {
394 sprintf(filename,
"%u",
id);
398 bool file_to_id(
char *filename, uint16_t *
id) {
399 if (strlen(filename) <= 0) {
403 bool is_sample =
true;
407 for (i = 0; i < strlen(filename); i++) {
409 is_sample &= (isdigit((
unsigned char) filename[i]) > 0);
413 *
id = atoi(filename);
int cfs_open(const char *name, int flags)
Open a file.
#define CFS_WRITE
Specify that cfs_open() should open a file for writing.
bool store_get_latest_sample(Sample *sample)
Get the most recent sample from the flash.
bool store_save_config(SensorConfig *config)
Save the configuration to flash.
int cfs_opendir(struct cfs_dir *dir, const char *name)
Open a directory for reading directory entries.
void cfs_close(int fd)
Close an open file.
bool store_get_config(SensorConfig *config)
Get the configuration from the flash.
#define CFS_READ
Specify that cfs_open() should open a file for reading.
#define COFFEE_SIZE
Total size in bytes of the file system.
uint8_t store_get_raw_sample(uint16_t id, uint8_t buffer[Sample_size])
Get a given sample from the flash, in the form of an encoded protocol buffer.
uint16_t store_save_sample(Sample *sample)
Store a sample in the flash.
int cfs_coffee_set_io_semantics(int fd, unsigned flags)
Set the I/O semantics for accessing a file.
bool store_get_sample(uint16_t id, Sample *sample)
Get a given sample from the flash,.
Convenience layer for storing readings and the config.
bool store_delete_sample(uint16_t id)
Delete a given sample from the flash.
void store_init(void)
Initialize the data store.
int cfs_readdir(struct cfs_dir *dir, struct cfs_dirent *record)
Read a directory entry.
#define CFS_COFFEE_IO_FIRM_SIZE
Instruct Coffee not to attempt to extend the file upon a request to write past the reserved file size...
uint8_t store_get_raw_config(uint8_t buffer[SensorConfig_size])
Get the configuration from the flash.
int cfs_remove(const char *name)
Remove a file.
#define COFFEE_PAGE_SIZE
Logical page size.
Header for the Coffee file system.
int cfs_coffee_reserve(const char *name, cfs_offset_t size)
Reserve space for a file.
void cfs_closedir(struct cfs_dir *dir)
Close a directory opened with cfs_opendir().
uint8_t store_get_latest_raw_sample(uint8_t buffer[Sample_size])
Get the most recent sample from the flash, in the form of an encoded protocol buffer.
uint16_t store_get_latest_sample_id(void)
Get the identifer of the most recent sample stored.