SD cardgit status FAT32git status Beautiful!

master
Clyne Sullivan 7 years ago
parent 8e11f269ce
commit 1a11ab00d8

@ -46,7 +46,7 @@ INITRD = initrd.img
all: $(OUT) all: $(OUT)
$(OUT): $(OFILES) initrd/init libinterp.a $(OUT): $(OFILES) initrd/* libinterp.a
@echo " INITRD " $(INITRD) @echo " INITRD " $(INITRD)
@rm -f $(INITRD) @rm -f $(INITRD)
@$(AR) $(INITRD) initrd/* @$(AR) $(INITRD) initrd/*

@ -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_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_ #endif // DISPLAY_H_

@ -0,0 +1,31 @@
#ifndef FAT32_H_
#define FAT32_H_
#include <stdint.h>
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_

@ -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 <https://www.gnu.org/licenses/>.
*/
#ifndef SDCARD_H_
#define SDCARD_H_
#include <stdint.h>
/**
* 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_

@ -41,24 +41,24 @@ func(makegrid) {
# #
makegrid() makegrid()
clearcmd = "clear" clearcmd = ""
while (1) { while (1) {
rect(0, 0, 480, 40, 0) rect(0, 0, 480, 40, 0)
print("f(x) = ") print("f(x) = ")
Fx = gets() fx = gets()
if (Fx == clearcmd) { if (fx == clearcmd) {
makegrid() makegrid()
} else { } else {
# do function # do function
x = xmin X = xmin
while (x < xmax) { while (X < xmax) {
y = solve(Fx) y = solve(fx)
y = 0 - y y = 0 - y
if ((y >= ymin) & (y <= ymax)) { 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
} }
} }

@ -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
}
}

Binary file not shown.

@ -206,7 +206,13 @@ void dsp_init(void)
dsp_write_cmd(0x11); dsp_write_cmd(0x11);
delay(150); delay(150);
dsp_write_cmd(0x29); // set display on 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_cmd(0x33); // set scroll area
dsp_write_data(0x00); dsp_write_data(0x00);
dsp_write_data(0x00); dsp_write_data(0x00);
@ -219,3 +225,32 @@ void dsp_init(void)
dsp_write_data(0x00);*/ 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);
}

@ -0,0 +1,145 @@
/**
* Implementation of a driver to read a FAT32 filesystem.
*/
#include <ctype.h>
#include <fat32.h>
#include <heap.h>
#include <sdcard.h>
#include <string.h>
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;
}

@ -23,7 +23,7 @@
void gpio_init(void) void gpio_init(void)
{ {
// enable clocks // enable clocks
RCC->AHB2ENR |= 0xFF; RCC->AHB2ENR |= 0x0F;
} }
void gpio_pupd(GPIO_TypeDef *port, uint32_t pin, uint32_t pupd) void gpio_pupd(GPIO_TypeDef *port, uint32_t pin, uint32_t pupd)

@ -35,6 +35,8 @@
#define COL_3 GPIO_PORT(A, 12) #define COL_3 GPIO_PORT(A, 12)
#define COL_4 GPIO_PORT(C, 5) #define COL_4 GPIO_PORT(C, 5)
#define BTN_SLEEP GPIO_PORT(C, 11)
#define ROWS 6 #define ROWS 6
#define COLS 5 #define COLS 5
@ -59,7 +61,7 @@ static const port_t keypad_cols[COLS] = {
static const char keypad_map[ROWS * COLS * 4] = { 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" "\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" "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" "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" "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] = { 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" "\x7F\0\0\0" "pi\0\0" "X\0\0\0" "Y\0\0\0" "Z\0\0\0"
"f\0\0\0" "g\0\0\0" "h\0\0\0" "i\0\0\0" "j\0\0\0" "A\0\0\0" "B\0\0\0" "C\0\0\0" "D\0\0\0" "E\0\0\0"
"k\0\0\0" "l\0\0\0" "m\0\0\0" "n\0\0\0" "o\0\0\0" "F\0\0\0" "G\0\0\0" "H\0\0\0" "I\0\0\0" "J\0\0\0"
"p\0\0\0" "q\0\0\0" "r\0\0\0" "s\0\0\0" "t\0\0\0" "K\0\0\0" "L\0\0\0" "M\0\0\0" "N\0\0\0" "O\0\0\0"
"u\0\0\0" "v\0\0\0" "w\0\0\0" "x\0\0\0" "y\0\0\0" "P\0\0\0" "Q\0\0\0" "R\0\0\0" "S\0\0\0" "T\0\0\0"
"z\0\0\0" "\0\0\0\0" "\0\0\0\0" "\0\0\0\0" "\xFF\x01\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] #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_speed(p, pin, VERYHIGH);
gpio_dout(p, pin, 0); 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) void keypad_start(void)
@ -160,3 +175,24 @@ int keypad_get(void)
keypad_buffer_pos--; keypad_buffer_pos--;
return key; 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;
}

@ -21,6 +21,7 @@
#include <clock.h> #include <clock.h>
#include <display.h> #include <display.h>
#include <display_draw.h> #include <display_draw.h>
#include <fat32.h>
#include <flash.h> #include <flash.h>
#include <gpio.h> #include <gpio.h>
#include <heap.h> #include <heap.h>
@ -30,6 +31,7 @@
#include <it/parser.h> #include <it/parser.h>
#include <random.h> #include <random.h>
#include <script.h> #include <script.h>
#include <sdcard.h>
#include <serial.h> #include <serial.h>
#include <stm32l476xx.h> #include <stm32l476xx.h>
#include <string.h> #include <string.h>
@ -60,7 +62,7 @@ int main(void)
keypad_init(); keypad_init();
flash_init(); flash_init();
gpio_mode(GPIOA, 5, OUTPUT); //gpio_mode(GPIOA, 5, OUTPUT); // taken by sd
// enable FPU // enable FPU
SCB->CPACR |= (0xF << 20); SCB->CPACR |= (0xF << 20);
@ -71,9 +73,25 @@ int main(void)
while (1); 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) void kmain(void)
{ {
dsp_init(); dsp_init();
sd_init();
fat_find();
dsp_cursoron(); dsp_cursoron();
keypad_start(); keypad_start();
@ -81,30 +99,37 @@ void kmain(void)
task_start(task_status, 512); task_start(task_status, 512);
while (1) { while (1) {
gpio_dout(GPIOA, 5, 1); extern uint32_t sleep_pending;
delay(250); if (sleep_pending != 0) {
gpio_dout(GPIOA, 5, 0); sleep();
delay(250); 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) instance *load_program(const char *name)
{ {
// load file // load file
char *s = initrd_readfile(name); file_t *file = fat_findfile(name);
if (s == 0) { if (file == 0) {
dsp_puts("can't find "); dsp_puts("can't find ");
dsp_puts(name); dsp_puts(name);
goto fail; goto fail;
} }
char *s = fat_readfile(file);
instance *it = inewinstance(); instance *it = inewinstance();
script_loadlib(it); script_loadlib(it);
// read in, parse into script code // read in, parse into script code
char *linebuf = (char *)malloc(120); char *linebuf = (char *)malloc(120);
uint32_t i = 0, prev = 0, lc; uint32_t i = 0, prev = 0, lc;
uint32_t size = initrd_filesize(name); uint32_t size = file->size;
int ret = 0; int ret = 0;
while (i < size) { while (i < size) {
for (; s[i] != '\n' && s[i] != '\0'; i++); for (; s[i] != '\n' && s[i] != '\0'; i++);
@ -121,6 +146,8 @@ instance *load_program(const char *name)
prev = ++i; prev = ++i;
} }
free(linebuf); free(linebuf);
free(s);
free(file);
return it; return it;
fail: fail:
while (1); while (1);

@ -39,9 +39,11 @@
int script_puts(instance *it); int script_puts(instance *it);
int script_putchar(instance *it); int script_putchar(instance *it);
int script_gets(instance *it); int script_gets(instance *it);
int script_getf(instance *it);
int script_delay(instance *it); int script_delay(instance *it);
int script_rect(instance *it); int script_rect(instance *it);
int script_ppos(instance *it); int script_ppos(instance *it);
int script_rpos(instance *it);
int script_line(instance *it); int script_line(instance *it);
int script_color(instance *it); int script_color(instance *it);
int script_rand(instance *it); int script_rand(instance *it);
@ -53,6 +55,8 @@ int script_program(instance *it);
int script_free(instance *it); int script_free(instance *it);
int math_sin(instance *it); int math_sin(instance *it);
int math_cos(instance *it);
int math_tan(instance *it);
void script_loadlib(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, "print", script_puts);
inew_cfunc(it, "putchar", script_putchar); inew_cfunc(it, "putchar", script_putchar);
inew_cfunc(it, "gets", script_gets); inew_cfunc(it, "gets", script_gets);
inew_cfunc(it, "getf", script_getf);
inew_cfunc(it, "getkey", script_getkey); inew_cfunc(it, "getkey", script_getkey);
inew_cfunc(it, "ppos", script_ppos); inew_cfunc(it, "ppos", script_ppos);
inew_cfunc(it, "rpos", script_rpos);
inew_cfunc(it, "pixel", script_pixel); inew_cfunc(it, "pixel", script_pixel);
inew_cfunc(it, "line", script_line); inew_cfunc(it, "line", script_line);
@ -78,6 +84,8 @@ void script_loadlib(instance *it)
inew_cfunc(it, "freemem", script_free); inew_cfunc(it, "freemem", script_free);
inew_cfunc(it, "sin", math_sin); inew_cfunc(it, "sin", math_sin);
inew_cfunc(it, "cos", math_cos);
inew_cfunc(it, "tan", math_tan);
} }
int math_sin(instance *it) int math_sin(instance *it)
@ -88,6 +96,22 @@ int math_sin(instance *it)
return 0; 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) int script_menu(instance *it)
{ {
char listbuf[4]; char listbuf[4];
@ -113,13 +137,15 @@ int script_menu(instance *it)
return 0; return 0;
} }
#include <fat32.h>
int script_filemenu(instance *it) int script_filemenu(instance *it)
{ {
char listbuf[4]; char listbuf[4];
char *fname; char *fname;
strncpy(listbuf, " : \0", 4); strncpy(listbuf, " : \0", 4);
dsp_puts("Choose a file: \n"); 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'; listbuf[0] = i + '0';
dsp_puts(listbuf); dsp_puts(listbuf);
dsp_puts(fname); dsp_puts(fname);
@ -163,6 +189,18 @@ int script_putchar(instance *it)
return 0; 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) int script_gets(instance *it)
{ {
char *s = malloc(64); char *s = malloc(64);
@ -261,8 +299,14 @@ int script_line(instance *it)
int script_ppos(instance *it) int script_ppos(instance *it)
{ {
dsp_cpos(0, 0); dsp_coff(0, 0);
dsp_coff(igetarg_integer(it, 0), igetarg_integer(it, 1)); 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; return 0;
} }
@ -305,7 +349,7 @@ extern instance *load_program(const char *name);
int script_program(instance *it) int script_program(instance *it)
{ {
int initrdOffset = (int)igetarg(it, 0)->value.f; 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_rect(0, 0, 480, 300, 0);
dsp_cpos(0, 0); dsp_cpos(0, 0);

@ -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 <https://www.gnu.org/licenses/>.
*/
#include <clock.h>
#include <gpio.h>
#include <heap.h>
#include <sdcard.h>
#include <string.h>
#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;
}

@ -85,7 +85,6 @@ char *snprintf(char *buf, unsigned int max, const char *format, ...)
float strtof(const char *s, char **endptr) float strtof(const char *s, char **endptr)
{ {
(void)s;
(void)endptr; (void)endptr;
float res = 0.0f; float res = 0.0f;
@ -139,6 +138,12 @@ char *ftostr(char *buf, float f)
if (buf == 0) if (buf == 0)
return 0; return 0;
if (f == 0) {
buf[0] = '0';
buf[1] = '\0';
return buf;
}
unsigned int i = 0; // offset unsigned int i = 0; // offset
// strip decimals, convert in reverse // strip decimals, convert in reverse

Loading…
Cancel
Save