diff --git a/Makefile b/Makefile index d672a52..595694a 100644 --- a/Makefile +++ b/Makefile @@ -46,7 +46,7 @@ INITRD = initrd.img all: $(OUT) -$(OUT): $(OFILES) initrd/init libinterp.a +$(OUT): $(OFILES) initrd/* libinterp.a @echo " INITRD " $(INITRD) @rm -f $(INITRD) @$(AR) $(INITRD) initrd/* diff --git a/include/display.h b/include/display.h index b8afe38..2d74fce 100644 --- a/include/display.h +++ b/include/display.h @@ -92,4 +92,7 @@ void dsp_set_addr(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2); */ void dsp_set_addr_read(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2); +void dsp_sleep(void); +void dsp_wakeup(void); + #endif // DISPLAY_H_ diff --git a/include/fat32.h b/include/fat32.h new file mode 100644 index 0000000..39d22f6 --- /dev/null +++ b/include/fat32.h @@ -0,0 +1,31 @@ +#ifndef FAT32_H_ +#define FAT32_H_ + +#include + +typedef struct { + uint32_t size; + uint32_t start; +} file_t; + +/** + * Finds a FAT partition on the SD card. + * @return non-zero if partition found + */ +int fat_find(void); + +/** + * Searches for the given file, returning necessary information to use it. + * @param name the file's name + * @return a file data structure, null if not found + */ +file_t *fat_findfile(const char *name); + +/** + * + */ +char *fat_readfile(file_t *file); + +char *fat_getname(uint32_t index); + +#endif // FAT32_H_ diff --git a/include/sdcard.h b/include/sdcard.h new file mode 100644 index 0000000..8cdef58 --- /dev/null +++ b/include/sdcard.h @@ -0,0 +1,42 @@ +/** + * @file sdcard.c + * Provides a basic library for accessing an SD card + * + * Copyright (C) 2018 Clyne Sullivan + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef SDCARD_H_ +#define SDCARD_H_ + +#include + +/** + * Attempts to initialize the SD card. + * Warning: Little to no error checking is done/handled properly. + */ +void sd_init(void); + +/** + * Reads in data from the SD card. + * LBAs are 512 bytes long. + * @param buf the pre-allocated buffer to store data in + * @param lba the lba to read from + * @param count the number of bytes to read + * @return the buffer + */ +uint8_t *sd_read(uint8_t *buf, uint32_t lba, uint32_t count); + +#endif // SDCARD_H_ diff --git a/initrd/graph b/initrd/graph index 8f9916a..949fd52 100644 --- a/initrd/graph +++ b/initrd/graph @@ -41,24 +41,24 @@ func(makegrid) { # makegrid() -clearcmd = "clear" +clearcmd = "" while (1) { rect(0, 0, 480, 40, 0) print("f(x) = ") - Fx = gets() + fx = gets() - if (Fx == clearcmd) { + if (fx == clearcmd) { makegrid() } else { # do function - x = xmin - while (x < xmax) { - y = solve(Fx) + X = xmin + while (X < xmax) { + y = solve(fx) y = 0 - y if ((y >= ymin) & (y <= ymax)) { - pixel(cx + x * xinc, cy + y * yinc, 511) + pixel(cx + X * xinc, cy + y * yinc, 511) } - x = x + 1 / xinc + X = X + 1 / xinc } } diff --git a/initrd/table b/initrd/table new file mode 100644 index 0000000..62961e3 --- /dev/null +++ b/initrd/table @@ -0,0 +1,85 @@ +ppos(0, 0) +array(table, 1) + +index = 0 +while (1) { + c = getkey() + # down + if (c == 25) { + rpos(0, 1) + index = index + 1 + } + # up + if (c == 24) { + rpos(0, -1) + if (index > 0) { + index = index - 1 + } + } + # right - insert + if (c == 26) { + print(" ") + rpos(-10, 0) + print("> ") + table.index = getf() + ppos(0, index) + print(index) + print(": ") + print(table.index) + print(" ") + index = index + 1 + ppos(0, index) + } + # plus - sum + if (c == 43) { + s = size(table) + j = 0 + sum = 0 + while (j < s) { + sum = sum + table.j + j = j + 1 + } + ppos(0, 17) + print(" ") + ppos(0, 17) + print("sum: ") + print(sum) + ppos(0, 0) + index = 0 + } + # * - product + if (c == 42) { + s = size(table) + j = 0 + product = 1 + while (j < s) { + product = product * table.j + j = j + 1 + } + ppos(0, 17) + print(" ") + ppos(0, 17) + print("product: ") + print(product) + ppos(0, 0) + index = 0 + } + # / - average + if (c == 47) { + s = size(table) + j = 0 + sum = 0 + while (j < s) { + sum = sum + table.j + j = j + 1 + } + average = sum / size(table) + ppos(0, 17) + print(" ") + ppos(0, 17) + print("average: ") + print(average) + ppos(0, 0) + index = 0 + } +} diff --git a/libinterp.a b/libinterp.a index 5b5da09..c5a2337 100644 Binary files a/libinterp.a and b/libinterp.a differ diff --git a/src/display.c b/src/display.c index e961299..376ba43 100644 --- a/src/display.c +++ b/src/display.c @@ -206,7 +206,13 @@ void dsp_init(void) dsp_write_cmd(0x11); delay(150); dsp_write_cmd(0x29); // set display on - delay(500); + delay(150); + + dsp_write_cmd(0x53); + dsp_write_data(0x2C); + //dsp_write_cmd(0x51); + //dsp_write_data(128); + /*dsp_write_cmd(0x33); // set scroll area dsp_write_data(0x00); dsp_write_data(0x00); @@ -219,3 +225,32 @@ void dsp_init(void) dsp_write_data(0x00);*/ } +void dsp_backlight(uint8_t value) +{ + dsp_write_cmd(0x51); + dsp_write_data(value); +} + +void dsp_sleep(void) +{ + // backlight + dsp_backlight(0x00); + // display off + dsp_write_cmd(0x28); + // sleep mode + dsp_write_cmd(0x10); + delay(5); +} + +void dsp_wakeup(void) +{ + // unsleep + dsp_write_cmd(0x11); + //delay(5); + for (uint32_t i = 0; i < 20000; i++) + asm(""); + // display on + dsp_write_cmd(0x29); + dsp_backlight(0xFF); +} + diff --git a/src/fat32.c b/src/fat32.c new file mode 100644 index 0000000..1154998 --- /dev/null +++ b/src/fat32.c @@ -0,0 +1,145 @@ +/** + * Implementation of a driver to read a FAT32 filesystem. + */ + +#include +#include +#include +#include +#include + +static uint32_t partition_lba = 0; + +static uint8_t SectorsPerCluster; +static uint32_t RootDirCluster; +static uint32_t ClustersLBA; +static uint32_t FATStartLBA; + +int fat_find(void) +{ + uint8_t *block = malloc(512); + + // find FAT partition + sd_read(block, 0, 512); + for (unsigned int i = 450; i < 450 + 64; i += 16) { + if (block[i] == 0x0B || block[i] == 0x0C) { + partition_lba = *((uint32_t *)(block + i + 4)); + break; + } + } + + if (partition_lba == 0) + return 0; + + // read FAT volume id + sd_read(block, partition_lba, 512); + SectorsPerCluster = block[0x0D]; + uint16_t ReservedSectors = *((uint16_t *)(block + 0x0E)); + uint32_t SectorsPerFAT = *((uint32_t *)(block + 0x24)); + RootDirCluster = *((uint32_t *)(block + 0x2C)); + + FATStartLBA = partition_lba + ReservedSectors; + ClustersLBA = FATStartLBA + 2 * SectorsPerFAT; + + free(block); + return 1; +} + +uint32_t fat_cluster2lba(uint32_t cluster) +{ + return ClustersLBA + (cluster - 2) * SectorsPerCluster; +} + +int fat_namecmp(const char *fatname, const char *name) +{ + for (unsigned int i = 0; i < 8; i++) { + if (name[i] == '.' || name[i] == '\0') + break; + + if (toupper(fatname[i]) != toupper(name[i])) + return 0; + } + + return 1; +} + +file_t *fat_findfile(const char *name) +{ + uint8_t *block = malloc(512 * SectorsPerCluster); + sd_read(block, fat_cluster2lba(RootDirCluster), 512 * SectorsPerCluster); + + for (unsigned int i = 0; block[i * 32] != 0; i++) { + if (block[i * 32] == 0xE5 || (block[i * 32 + 11] & 0x0F) == 0x0F) + continue; + + if (fat_namecmp((char *)(block + i * 32), name)) { + uint32_t size = *((uint32_t *)(block + i * 32 + 28)); + uint32_t start = *((uint16_t *)(block + i * 32 + 20)) + << 16 | *((uint16_t *)(block + i * 32 + 26)); + file_t *file = malloc(sizeof(file_t)); + file->size = size; + file->start = start; + free(block); + return file; + } + } + + free(block); + return 0; +} + +char *fat_getname(uint32_t index) +{ + uint8_t *block = malloc(512 * SectorsPerCluster); + sd_read(block, fat_cluster2lba(RootDirCluster), 512 * SectorsPerCluster); + + uint32_t idx = 0; + for (unsigned int i = 0; block[i * 32] != 0; i++) { + if (block[i * 32] == 0xE5 || (block[i * 32 + 11] & 0x0F) == 0x0F) + continue; + + if (idx == index) { + char *name = strncpy(malloc(11), (char *)(block + i * 32), 11); + free(block); + return name; + } + idx++; + } + + free(block); + return 0; +} + +char *fat_readfile(file_t *file) +{ + if (file == 0) + return 0; + + uint8_t *block = malloc(512); + + uint32_t start = file->start; + uint8_t *buffer = malloc(file->size + 1); + uint32_t offset = 0; + buffer[file->size] = '\0'; + while (start != 0) { + // find in FAT + sd_read(block, FATStartLBA + (start / 128), 512); + uint32_t next = ((uint32_t *)block)[start % 128]; + + // read start cluster + uint32_t size = 512 * SectorsPerCluster; + if (file->size - offset < size) + size = file->size - offset; + sd_read(buffer, fat_cluster2lba(start), size); + offset += size; + + if ((next & 0x0FFFFFFF) == 0x0FFFFFFF) + start = 0; + else + start = next; + + } + + free(block); + return (char *)buffer; +} diff --git a/src/gpio.c b/src/gpio.c index db67465..151779d 100644 --- a/src/gpio.c +++ b/src/gpio.c @@ -23,7 +23,7 @@ void gpio_init(void) { // enable clocks - RCC->AHB2ENR |= 0xFF; + RCC->AHB2ENR |= 0x0F; } void gpio_pupd(GPIO_TypeDef *port, uint32_t pin, uint32_t pupd) diff --git a/src/keypad.c b/src/keypad.c index b00cf41..cb569e1 100644 --- a/src/keypad.c +++ b/src/keypad.c @@ -35,6 +35,8 @@ #define COL_3 GPIO_PORT(A, 12) #define COL_4 GPIO_PORT(C, 5) +#define BTN_SLEEP GPIO_PORT(C, 11) + #define ROWS 6 #define COLS 5 @@ -59,7 +61,7 @@ static const port_t keypad_cols[COLS] = { static const char keypad_map[ROWS * COLS * 4] = { "\x7F\0\0\0" "\xFF\0\0\0" "\xFF\x02\0\0" "\x19\0\0\0" "\x18\0\0\0" - "x\0\0\0" "\0\0\0\0" "\0\0\0\0" "\x1B\0\0\0" "\x1A\0\0\0" + "sin\0" "cos\0" "tan\0" "\x1B\0\0\0" "\x1A\0\0\0" "7\0\0\0" "8\0\0\0" "9\0\0\0" "(\0\0\0" ")\0\0\0" "4\0\0\0" "5\0\0\0" "6\0\0\0" "/\0\0\0" "*\0\0\0" "1\0\0\0" "2\0\0\0" "3\0\0\0" "-\0\0\0" "+\0\0\0" @@ -67,12 +69,12 @@ static const char keypad_map[ROWS * COLS * 4] = { }; static const char keypad_map_2nd[ROWS * COLS * 4] = { - "a\0\0\0" "b\0\0\0" "c\0\0\0" "d\0\0\0" "e\0\0\0" - "f\0\0\0" "g\0\0\0" "h\0\0\0" "i\0\0\0" "j\0\0\0" - "k\0\0\0" "l\0\0\0" "m\0\0\0" "n\0\0\0" "o\0\0\0" - "p\0\0\0" "q\0\0\0" "r\0\0\0" "s\0\0\0" "t\0\0\0" - "u\0\0\0" "v\0\0\0" "w\0\0\0" "x\0\0\0" "y\0\0\0" - "z\0\0\0" "\0\0\0\0" "\0\0\0\0" "\0\0\0\0" "\xFF\x01\0\0" + "\x7F\0\0\0" "pi\0\0" "X\0\0\0" "Y\0\0\0" "Z\0\0\0" + "A\0\0\0" "B\0\0\0" "C\0\0\0" "D\0\0\0" "E\0\0\0" + "F\0\0\0" "G\0\0\0" "H\0\0\0" "I\0\0\0" "J\0\0\0" + "K\0\0\0" "L\0\0\0" "M\0\0\0" "N\0\0\0" "O\0\0\0" + "P\0\0\0" "Q\0\0\0" "R\0\0\0" "S\0\0\0" "T\0\0\0" + "U\0\0\0" "V\0\0\0" "W\0\0\0" "\b\0\0\0" "\xFF\x01\0\0" }; #define KEY(r, c, i) map[r * COLS * 4 + c * 4 + i] @@ -142,6 +144,19 @@ void keypad_init(void) gpio_speed(p, pin, VERYHIGH); gpio_dout(p, pin, 0); } + + gpio_mode(BTN_SLEEP, OUTPUT); + gpio_dout(BTN_SLEEP, 0); + gpio_mode(BTN_SLEEP, INPUT); + gpio_pupd(BTN_SLEEP, PULLDOWN); + + //SYSCFG->EXTICR[2] |= 0x200; // C10 + EXTI->RTSR1 |= (1 << 11); + EXTI->EMR1 |= (1 << 11); // Allow *10 + EXTI->IMR1 |= (1 << 11); + + // enable IRQ in NVIC + ((uint32_t *)0xE000E100)[1] |= (1 << 8); } void keypad_start(void) @@ -160,3 +175,24 @@ int keypad_get(void) keypad_buffer_pos--; return key; } + +uint32_t sleep_pending = 0; +void EXTI15_10_IRQHandler(void) +{ + uint32_t PR1 = EXTI->PR1; + + if (gpio_din(BTN_SLEEP)) { + while (gpio_din(BTN_SLEEP)); + if (sleep_pending != 0) { + sleep_pending = 0; + extern void wakeup(void); + wakeup(); + } else { + sleep_pending |= 1; + } + return; + } + + EXTI->PR1 |= PR1; +} + diff --git a/src/main.c b/src/main.c index a86db6a..4380eae 100644 --- a/src/main.c +++ b/src/main.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -30,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -60,7 +62,7 @@ int main(void) keypad_init(); flash_init(); - gpio_mode(GPIOA, 5, OUTPUT); + //gpio_mode(GPIOA, 5, OUTPUT); // taken by sd // enable FPU SCB->CPACR |= (0xF << 20); @@ -71,9 +73,25 @@ int main(void) while (1); } +void sleep(void) +{ + dsp_sleep(); + *((uint32_t *)0xE000ED10) |= 4; // SLEEPDEEP + PWR->CR1 |= 2; + asm("wfi"); +} + +void wakeup(void) +{ + clock_init(); + dsp_wakeup(); +} + void kmain(void) { dsp_init(); + sd_init(); + fat_find(); dsp_cursoron(); keypad_start(); @@ -81,30 +99,37 @@ void kmain(void) task_start(task_status, 512); while (1) { - gpio_dout(GPIOA, 5, 1); - delay(250); - gpio_dout(GPIOA, 5, 0); - delay(250); + extern uint32_t sleep_pending; + if (sleep_pending != 0) { + sleep(); + while (sleep_pending) + delay(1); + } + //gpio_dout(GPIOA, 5, 1); + //delay(250); + //gpio_dout(GPIOA, 5, 0); + delay(100); } } instance *load_program(const char *name) { // load file - char *s = initrd_readfile(name); - if (s == 0) { + file_t *file = fat_findfile(name); + if (file == 0) { dsp_puts("can't find "); dsp_puts(name); goto fail; } + char *s = fat_readfile(file); instance *it = inewinstance(); script_loadlib(it); // read in, parse into script code char *linebuf = (char *)malloc(120); uint32_t i = 0, prev = 0, lc; - uint32_t size = initrd_filesize(name); + uint32_t size = file->size; int ret = 0; while (i < size) { for (; s[i] != '\n' && s[i] != '\0'; i++); @@ -121,6 +146,8 @@ instance *load_program(const char *name) prev = ++i; } free(linebuf); + free(s); + free(file); return it; fail: while (1); diff --git a/src/script.c b/src/script.c index 51a3bb7..5ba0c08 100644 --- a/src/script.c +++ b/src/script.c @@ -39,9 +39,11 @@ int script_puts(instance *it); int script_putchar(instance *it); int script_gets(instance *it); +int script_getf(instance *it); int script_delay(instance *it); int script_rect(instance *it); int script_ppos(instance *it); +int script_rpos(instance *it); int script_line(instance *it); int script_color(instance *it); int script_rand(instance *it); @@ -53,6 +55,8 @@ int script_program(instance *it); int script_free(instance *it); int math_sin(instance *it); +int math_cos(instance *it); +int math_tan(instance *it); void script_loadlib(instance *it) { @@ -61,8 +65,10 @@ void script_loadlib(instance *it) inew_cfunc(it, "print", script_puts); inew_cfunc(it, "putchar", script_putchar); inew_cfunc(it, "gets", script_gets); + inew_cfunc(it, "getf", script_getf); inew_cfunc(it, "getkey", script_getkey); inew_cfunc(it, "ppos", script_ppos); + inew_cfunc(it, "rpos", script_rpos); inew_cfunc(it, "pixel", script_pixel); inew_cfunc(it, "line", script_line); @@ -78,6 +84,8 @@ void script_loadlib(instance *it) inew_cfunc(it, "freemem", script_free); inew_cfunc(it, "sin", math_sin); + inew_cfunc(it, "cos", math_cos); + inew_cfunc(it, "tan", math_tan); } int math_sin(instance *it) @@ -88,6 +96,22 @@ int math_sin(instance *it) return 0; } +int math_cos(instance *it) +{ + variable *n = igetarg(it, 0); + variable *v = make_varf(0, cosf(n->value.f)); + ipush(it, (uint32_t)v); + return 0; +} + +int math_tan(instance *it) +{ + variable *n = igetarg(it, 0); + variable *v = make_varf(0, tanf(n->value.f)); + ipush(it, (uint32_t)v); + return 0; +} + int script_menu(instance *it) { char listbuf[4]; @@ -113,13 +137,15 @@ int script_menu(instance *it) return 0; } +#include + int script_filemenu(instance *it) { char listbuf[4]; char *fname; strncpy(listbuf, " : \0", 4); dsp_puts("Choose a file: \n"); - for (unsigned int i = 0; (fname = initrd_getname(i)) != 0; i++) { + for (unsigned int i = 0; (fname = /*initrd*/fat_getname(i)) != 0; i++) { listbuf[0] = i + '0'; dsp_puts(listbuf); dsp_puts(fname); @@ -163,6 +189,18 @@ int script_putchar(instance *it) return 0; } +int script_getf(instance *it) +{ + if (script_gets(it) != 0) + return -1; + + variable *s = (variable *)ipop(it); + s->value.f = strtof((char *)s->value.p, 0); + s->type = NUMBER; + ipush(it, (uint32_t)s); + return 0; +} + int script_gets(instance *it) { char *s = malloc(64); @@ -261,8 +299,14 @@ int script_line(instance *it) int script_ppos(instance *it) { - dsp_cpos(0, 0); - dsp_coff(igetarg_integer(it, 0), igetarg_integer(it, 1)); + dsp_coff(0, 0); + dsp_cpos(igetarg_integer(it, 0), igetarg_integer(it, 1)); + return 0; +} + +int script_rpos(instance *it) +{ + dsp_spos(igetarg_integer(it, 0), igetarg_integer(it, 1)); return 0; } @@ -305,7 +349,7 @@ extern instance *load_program(const char *name); int script_program(instance *it) { int initrdOffset = (int)igetarg(it, 0)->value.f; - char *name = initrd_getname(initrdOffset); + char *name = fat_getname(initrdOffset); dsp_rect(0, 0, 480, 300, 0); dsp_cpos(0, 0); diff --git a/src/sdcard.c b/src/sdcard.c new file mode 100644 index 0000000..6cf602b --- /dev/null +++ b/src/sdcard.c @@ -0,0 +1,222 @@ +/** + * @file sdcard.c + * Provides a basic library for accessing an SD card + * + * Copyright (C) 2018 Clyne Sullivan + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include + +#define SCK GPIO_PORT(A, 5) +#define SO GPIO_PORT(A, 6) +#define SI GPIO_PORT(A, 7) +#define CS GPIO_PORT(B, 6) + +typedef struct { + uint8_t cmd; + uint32_t arg; + uint8_t crc; +} __attribute__ ((packed)) sdcmd_t; + +typedef struct { + uint8_t zero :1; + uint8_t param :1; + uint8_t address :1; + uint8_t erase :1; + uint8_t crc :1; + uint8_t badcmd :1; + uint8_t ereset :1; + uint8_t idle :1; +} __attribute__ ((packed)) r1_t; + +void flash_out(uint8_t byte) +{ + for (int i = 0; i < 8; i++) { + gpio_dout(SI, byte & (1 << (7 - i))); + gpio_dout(SCK, 1); + gpio_dout(SCK, 0); + } +} + +uint8_t flash_in(void) +{ + uint8_t byte = 0; + for (int i = 0; i < 8; i++) { + if (gpio_din(SO)) + byte |= 1 << (7 - i); + gpio_dout(SCK, 1); + gpio_dout(SCK, 0); + } + return byte; +} + +void sd_delay(void) +{ + gpio_dout(SI, 1); + uint8_t so; + int i = 0; + do { + so = flash_in(); + if (i < 8) + i++; + } while (i < 8 || so != 0xFF); +} + +uint8_t sd_send_cmd(uint8_t cmd, uint32_t arg) +{ + sdcmd_t cmdp; + cmdp.cmd = (cmd & 0x3F) | 0x40; + cmdp.arg = arg; + + sd_delay(); + flash_out(cmdp.cmd); + flash_out(cmdp.arg >> 24); + flash_out(cmdp.arg >> 16); + flash_out(cmdp.arg >> 8); + flash_out(cmdp.arg); + flash_out(cmd == 8 ? 0x87 : 0x95); + + // wait for a zero + gpio_dout(SI, 1); + uint8_t r1; + do { + r1 = flash_in(); + } while (r1 & 0x80); + + return r1; +} + +void sd_init(void) +{ + gpio_mode(SCK, OUTPUT); + gpio_mode(SI, OUTPUT); + gpio_mode(CS, OUTPUT); + gpio_mode(SO, OUTPUT); + gpio_speed(SCK, VERYHIGH); + gpio_speed(SI, VERYHIGH); + gpio_speed(SO, VERYHIGH); + gpio_speed(CS, VERYHIGH); + gpio_pupd(SCK, PULLUP); + gpio_pupd(SI, PULLUP); + gpio_pupd(SO, PULLUP); + gpio_pupd(CS, PULLUP); + gpio_dout(SO, 0); + gpio_mode(SO, INPUT); + gpio_dout(CS, 1); + gpio_dout(SCK, 0); + gpio_dout(SI, 1); + + // init? cs and si are high + delay(10); + sd_delay(); + + // pull cs low, send cmd0 + gpio_dout(CS, 0); + uint8_t resp = sd_send_cmd(0, 0); + sd_delay(); + gpio_dout(CS, 1); + + if (resp != 0x01) + while (1); + + // do cmd8 + delay(10); + gpio_dout(CS, 0); + resp = sd_send_cmd(8, 0x1AA); + uint8_t ocr[4]; + for (int i = 0; i < 4; i++) + ocr[i] = flash_in(); + sd_delay(); + gpio_dout(CS, 1); + (void)ocr; + + // initialize + do { + // cmd55 + gpio_dout(CS, 0); + resp = sd_send_cmd(55, 0); + sd_delay(); + gpio_dout(CS, 1); + delay(10); + + // acmd41 + gpio_dout(CS, 0); + resp = sd_send_cmd(41, 0x40000000); + sd_delay(); + gpio_dout(CS, 1); + } while (resp != 0x00); + + // set block length + gpio_dout(CS, 0); + resp = sd_send_cmd(16, 512); + sd_delay(); + gpio_dout(CS, 1); +} + +uint8_t *sd_read_block(uint8_t *buf, uint32_t lba) +{ + if (buf == 0) + return 0; + + // send command + gpio_dout(CS, 0); + if (sd_send_cmd(17, lba) != 0) + return 0; + + // wait for block + gpio_dout(SI, 1); + uint8_t byte; + do byte = flash_in(); + while (byte == 0xFF); + if (byte != 0xFE) + return 0; + + // get block + uint32_t i = 0; + for (i = 0; i < 512; i++) + buf[i] = flash_in(); + + sd_delay(); + gpio_dout(CS, 1); + return buf; +} + +uint8_t *sd_read(uint8_t *buf, uint32_t lba, uint32_t count) +{ + if (buf == 0) + return 0; + + uint8_t *block_buf = malloc(512); + uint32_t i = 0; + while (count > 0) { + sd_read_block(block_buf, lba); + memcpy(buf + i, block_buf, (count < 512) ? count : 512); + if (count < 512) + count = 0; + else + count -= 512; + i += 512; + lba++; + } + + free(block_buf); + return buf; +} + diff --git a/src/stdlib.c b/src/stdlib.c index 4714e93..a47fb03 100644 --- a/src/stdlib.c +++ b/src/stdlib.c @@ -85,7 +85,6 @@ char *snprintf(char *buf, unsigned int max, const char *format, ...) float strtof(const char *s, char **endptr) { - (void)s; (void)endptr; float res = 0.0f; @@ -139,6 +138,12 @@ char *ftostr(char *buf, float f) if (buf == 0) return 0; + if (f == 0) { + buf[0] = '0'; + buf[1] = '\0'; + return buf; + } + unsigned int i = 0; // offset // strip decimals, convert in reverse