close to a functioning skeleton
This commit is contained in:
parent
57cf2de7c7
commit
49b8aee14b
@ -7,7 +7,7 @@ SOURCES := $(wildcard *.c)
|
|||||||
HEADERS := $(wildcard *.h)
|
HEADERS := $(wildcard *.h)
|
||||||
OBJECTS := $(patsubst %.c,%.o,$(SOURCES))
|
OBJECTS := $(patsubst %.c,%.o,$(SOURCES))
|
||||||
|
|
||||||
MCU := atmega328
|
MCU := atmega328p
|
||||||
MCU_AVRDUDE := m328
|
MCU_AVRDUDE := m328
|
||||||
MCU_FREQ := 16000000UL
|
MCU_FREQ := 16000000UL
|
||||||
|
|
||||||
@ -16,7 +16,7 @@ OBJCOPY := avr-objcopy
|
|||||||
SIZE := avr-size -A
|
SIZE := avr-size -A
|
||||||
DOXYGEN := doxygen
|
DOXYGEN := doxygen
|
||||||
|
|
||||||
CFLAGS := -Wall -pedantic -mmcu=$(MCU) -std=c99 -g -Os -DF_CPU=$(MCU_FREQ)
|
CFLAGS := -Werror -Wall -pedantic -mmcu=$(MCU) -std=c99 -g -Os -DF_CPU=$(MCU_FREQ)
|
||||||
|
|
||||||
all: $(HEX)
|
all: $(HEX)
|
||||||
|
|
||||||
|
52
final_project/sd_reader/fifo.c
Normal file
52
final_project/sd_reader/fifo.c
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#include "fifo.h"
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
FIFO_TYPE buffer[FIFO_LEN];
|
||||||
|
uint16_t rd_ptr;
|
||||||
|
uint16_t wr_ptr;
|
||||||
|
uint16_t entries;
|
||||||
|
} fifo;
|
||||||
|
|
||||||
|
void fifo_init() {
|
||||||
|
fifo.rd_ptr = 0;
|
||||||
|
fifo.wr_ptr = 0;
|
||||||
|
fifo.entries = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fifo_err_t fifo_pop(FIFO_TYPE* dest) {
|
||||||
|
// FIFO is empty, nothing to return!
|
||||||
|
if (fifo.entries == 0) {
|
||||||
|
return FIFO_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Entries in FIFO, pop
|
||||||
|
*dest = fifo.buffer[fifo.rd_ptr];
|
||||||
|
fifo.rd_ptr++;
|
||||||
|
fifo.entries--;
|
||||||
|
|
||||||
|
// Ensure pointers don't overflow!
|
||||||
|
if (fifo.rd_ptr == FIFO_LEN) {
|
||||||
|
fifo.rd_ptr = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FIFO_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
fifo_err_t fifo_push(FIFO_TYPE src) {
|
||||||
|
// FIFO is full, don't store anything
|
||||||
|
if (fifo.entries == FIFO_LEN) {
|
||||||
|
return FIFO_FULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIFO has space, write
|
||||||
|
fifo.buffer[fifo.wr_ptr] = src;
|
||||||
|
fifo.wr_ptr++;
|
||||||
|
fifo.entries++;
|
||||||
|
|
||||||
|
// Ensure pointers don't overflow!
|
||||||
|
if (fifo.wr_ptr == FIFO_LEN) {
|
||||||
|
fifo.wr_ptr = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FIFO_SUCCESS;
|
||||||
|
}
|
36
final_project/sd_reader/fifo.h
Normal file
36
final_project/sd_reader/fifo.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#ifndef FIFO_H_
|
||||||
|
#define FIFO_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FIFO_SUCCESS,
|
||||||
|
FIFO_FULL,
|
||||||
|
FIFO_EMPTY
|
||||||
|
} fifo_err_t;
|
||||||
|
|
||||||
|
#define FIFO_LEN 20
|
||||||
|
#define FIFO_TYPE uint8_t
|
||||||
|
|
||||||
|
/** @brief Initialises FIFO
|
||||||
|
*
|
||||||
|
* This MUST be called before any other fifo_* functions are called.
|
||||||
|
* Unless memory is initialised to 0. Then it's fine I guess.
|
||||||
|
*/
|
||||||
|
void fifo_init();
|
||||||
|
|
||||||
|
/** @brief Pops most recent addition off of FIFO buffer.
|
||||||
|
*
|
||||||
|
* @retval FIFO_SUCCESS Successfully read data from FIFO
|
||||||
|
* @retval FIFO_EMPTY Buffer was empty, no data read
|
||||||
|
*/
|
||||||
|
fifo_err_t fifo_pop(FIFO_TYPE* dest);
|
||||||
|
|
||||||
|
/** @brief Pushes entry onto FIFO buffer.
|
||||||
|
*
|
||||||
|
* @retval FIFO_SUCCESS successfully wrote data to FIFO buffer
|
||||||
|
* @retval FIFO_FULL buffer, was full, no data written
|
||||||
|
*/
|
||||||
|
fifo_err_t fifo_push(FIFO_TYPE src);
|
||||||
|
|
||||||
|
#endif
|
@ -7,209 +7,22 @@
|
|||||||
* published by the Free Software Foundation.
|
* published by the Free Software Foundation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
#include "main.h"
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
#include <avr/sleep.h>
|
|
||||||
#include "fat.h"
|
|
||||||
#include "fat_config.h"
|
|
||||||
#include "partition.h"
|
|
||||||
#include "sd_raw.h"
|
|
||||||
#include "sd_raw_config.h"
|
|
||||||
|
|
||||||
#define DEBUG 1
|
#define DEBUG 1
|
||||||
|
|
||||||
/**
|
#define MAX_SONG_NUM 9
|
||||||
* \mainpage MMC/SD/SDHC card library
|
|
||||||
*
|
|
||||||
* This project provides a general purpose library which implements read and write
|
|
||||||
* support for MMC, SD and SDHC memory cards.
|
|
||||||
*
|
|
||||||
* It includes
|
|
||||||
* - low-level \link sd_raw MMC, SD and SDHC read/write routines \endlink
|
|
||||||
* - \link partition partition table support \endlink
|
|
||||||
* - a simple \link fat FAT16/FAT32 read/write implementation \endlink
|
|
||||||
*
|
|
||||||
* \section circuit The circuit
|
|
||||||
* The circuit which was mainly used during development consists of an Atmel AVR
|
|
||||||
* microcontroller with some passive components. It is quite simple and provides
|
|
||||||
* an easy test environment. The circuit which can be downloaded on the
|
|
||||||
* <a href="http://www.roland-riegel.de/sd-reader/">project homepage</a> has been
|
|
||||||
* improved with regard to operation stability.
|
|
||||||
*
|
|
||||||
* I used different microcontrollers during development, the ATmega8 with 8kBytes
|
|
||||||
* of flash, and its pin-compatible alternative, the ATmega168 with 16kBytes flash.
|
|
||||||
* The first one is the one I started with, but when I implemented FAT16 write
|
|
||||||
* support, I ran out of flash space and switched to the ATmega168. For FAT32, an
|
|
||||||
* ATmega328 is required.
|
|
||||||
*
|
|
||||||
* The circuit board is a self-made and self-soldered board consisting of a single
|
|
||||||
* copper layer and standard DIL components, except of the MMC/SD card connector.
|
|
||||||
*
|
|
||||||
* The connector is soldered to the bottom side of the board. It has a simple
|
|
||||||
* eject button which, when a card is inserted, needs some space beyond the connector
|
|
||||||
* itself. As an additional feature the connector has two electrical switches
|
|
||||||
* to detect wether a card is inserted and wether this card is write-protected.
|
|
||||||
*
|
|
||||||
* \section pictures Pictures
|
|
||||||
* \image html pic01.jpg "The circuit board used to implement and test this application."
|
|
||||||
* \image html pic02.jpg "The MMC/SD card connector on the soldering side of the circuit board."
|
|
||||||
*
|
|
||||||
* \section software The software
|
|
||||||
* The software is written in C (ISO C99). It might not be the smallest or
|
|
||||||
* the fastest one, but I think it is quite flexible. See the project's
|
|
||||||
* <a href="http://www.roland-riegel.de/sd-reader/benchmarks/">benchmark page</a> to get an
|
|
||||||
* idea of the possible data rates.
|
|
||||||
*
|
|
||||||
* I implemented an example application providing a simple command prompt which is accessible
|
|
||||||
* via the UART at 9600 Baud. With commands similiar to the Unix shell you can browse different
|
|
||||||
* directories, read and write files, create new ones and delete them again. Not all commands are
|
|
||||||
* available in all software configurations.
|
|
||||||
* - <tt>cat \<file\></tt>\n
|
|
||||||
* Writes a hexdump of \<file\> to the terminal.
|
|
||||||
* - <tt>cd \<directory\></tt>\n
|
|
||||||
* Changes current working directory to \<directory\>.
|
|
||||||
* - <tt>disk</tt>\n
|
|
||||||
* Shows card manufacturer, status, filesystem capacity and free storage space.
|
|
||||||
* - <tt>init</tt>\n
|
|
||||||
* Reinitializes and reopens the memory card.
|
|
||||||
* - <tt>ls</tt>\n
|
|
||||||
* Shows the content of the current directory.
|
|
||||||
* - <tt>mkdir \<directory\></tt>\n
|
|
||||||
* Creates a directory called \<directory\>.
|
|
||||||
* - <tt>mv \<file\> \<file_new\></tt>\n
|
|
||||||
* Renames \<file\> to \<file_new\>.
|
|
||||||
* - <tt>rm \<file\></tt>\n
|
|
||||||
* Deletes \<file\>.
|
|
||||||
* - <tt>sync</tt>\n
|
|
||||||
* Ensures all buffered data is written to the card.
|
|
||||||
* - <tt>touch \<file\></tt>\n
|
|
||||||
* Creates \<file\>.
|
|
||||||
* - <tt>write \<file\> \<offset\></tt>\n
|
|
||||||
* Writes text to \<file\>, starting from \<offset\>. The text is read
|
|
||||||
* from the UART, line by line. Finish with an empty line.
|
|
||||||
*
|
|
||||||
* \htmlonly
|
|
||||||
* <p>
|
|
||||||
* The following table shows some typical code sizes in bytes, using the 20090330 release with a
|
|
||||||
* buffered read-write MMC/SD configuration, FAT16 and static memory allocation:
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* <table border="1" cellpadding="2">
|
|
||||||
* <tr>
|
|
||||||
* <th>layer</th>
|
|
||||||
* <th>code size</th>
|
|
||||||
* <th>static RAM usage</th>
|
|
||||||
* </tr>
|
|
||||||
* <tr>
|
|
||||||
* <td>MMC/SD</td>
|
|
||||||
* <td align="right">2410</td>
|
|
||||||
* <td align="right">518</td>
|
|
||||||
* </tr>
|
|
||||||
* <tr>
|
|
||||||
* <td>Partition</td>
|
|
||||||
* <td align="right">456</td>
|
|
||||||
* <td align="right">17</td>
|
|
||||||
* </tr>
|
|
||||||
* <tr>
|
|
||||||
* <td>FAT16</td>
|
|
||||||
* <td align="right">7928</td>
|
|
||||||
* <td align="right">188</td>
|
|
||||||
* </tr>
|
|
||||||
* </table>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* The static RAM is mostly used for buffering memory card access, which
|
|
||||||
* improves performance and reduces implementation complexity.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Please note that the numbers above do not include the C library functions
|
|
||||||
* used, e.g. some string functions. These will raise the numbers somewhat
|
|
||||||
* if they are not already used in other program parts.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* When opening a partition, filesystem, file or directory, a little amount
|
|
||||||
* of RAM is used, as listed in the following table. Depending on the library
|
|
||||||
* configuration, the memory is either allocated statically or dynamically.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* <table border="1" cellpadding="2">
|
|
||||||
* <tr>
|
|
||||||
* <th>descriptor</th>
|
|
||||||
* <th>dynamic/static RAM</th>
|
|
||||||
* </tr>
|
|
||||||
* <tr>
|
|
||||||
* <td>partition</td>
|
|
||||||
* <td align="right">17</td>
|
|
||||||
* </tr>
|
|
||||||
* <tr>
|
|
||||||
* <td>filesystem</td>
|
|
||||||
* <td align="right">26</td>
|
|
||||||
* </tr>
|
|
||||||
* <tr>
|
|
||||||
* <td>file</td>
|
|
||||||
* <td align="right">53</td>
|
|
||||||
* </tr>
|
|
||||||
* <tr>
|
|
||||||
* <td>directory</td>
|
|
||||||
* <td align="right">49</td>
|
|
||||||
* </tr>
|
|
||||||
* </table>
|
|
||||||
*
|
|
||||||
* \endhtmlonly
|
|
||||||
*
|
|
||||||
* \section adaptation Adapting the software to your needs
|
|
||||||
* The only hardware dependent part is the communication layer talking to the
|
|
||||||
* memory card. The other parts like partition table and FAT support are
|
|
||||||
* completely independent, you could use them even for managing Compact Flash
|
|
||||||
* cards or standard ATAPI hard disks.
|
|
||||||
*
|
|
||||||
* By changing the MCU* variables in the Makefile, you can use other Atmel
|
|
||||||
* microcontrollers or different clock speeds. You might also want to change
|
|
||||||
* the configuration defines in the files fat_config.h, partition_config.h,
|
|
||||||
* sd_raw_config.h and sd-reader_config.h. For example, you could disable
|
|
||||||
* write support completely if you only need read support.
|
|
||||||
*
|
|
||||||
* For further information, visit the project's
|
|
||||||
* <a href="http://www.roland-riegel.de/sd-reader/faq/">FAQ page</a>.
|
|
||||||
*
|
|
||||||
* \section bugs Bugs or comments?
|
|
||||||
* If you have comments or found a bug in the software - there might be some
|
|
||||||
* of them - you may contact me per mail at feedback@roland-riegel.de.
|
|
||||||
*
|
|
||||||
* \section acknowledgements Acknowledgements
|
|
||||||
* Thanks go to Ulrich Radig, who explained on his homepage how to interface
|
|
||||||
* MMC cards to the Atmel microcontroller (http://www.ulrichradig.de/).
|
|
||||||
* I adapted his work for my circuit.
|
|
||||||
*
|
|
||||||
* \section copyright Copyright 2006-2012 by Roland Riegel
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License version 2 as published by
|
|
||||||
* the Free Software Foundation (http://www.gnu.org/copyleft/gpl.html).
|
|
||||||
* At your option, you can alternatively redistribute and/or modify the following
|
|
||||||
* files under the terms of the GNU Lesser General Public License version 2.1
|
|
||||||
* as published by the Free Software Foundation (http://www.gnu.org/copyleft/lgpl.html):
|
|
||||||
* - byteordering.c
|
|
||||||
* - byteordering.h
|
|
||||||
* - fat.c
|
|
||||||
* - fat.h
|
|
||||||
* - fat_config.h
|
|
||||||
* - partition.c
|
|
||||||
* - partition.h
|
|
||||||
* - partition_config.h
|
|
||||||
* - sd_raw.c
|
|
||||||
* - sd_raw.h
|
|
||||||
* - sd_raw_config.h
|
|
||||||
* - sd-reader_config.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
static struct fat_file_struct* open_file_in_dir(struct fat_fs_struct* fs, struct fat_dir_struct* dd, const char* name);
|
|
||||||
|
typedef struct {
|
||||||
|
struct fat_file_struct* fd;
|
||||||
|
char* name;
|
||||||
|
} song_info_t;
|
||||||
|
|
||||||
|
song_info_t songs[MAX_SONG_NUM];
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
lcd_init(LCD_DISP_ON);
|
|
||||||
|
|
||||||
/* we will just use ordinary idle mode */
|
/* we will just use ordinary idle mode */
|
||||||
//set_sleep_mode(SLEEP_MODE_IDLE);
|
//set_sleep_mode(SLEEP_MODE_IDLE);
|
||||||
|
|
||||||
@ -242,16 +55,45 @@ int main()
|
|||||||
fat_get_dir_entry_of_path(fs, "/", &directory);
|
fat_get_dir_entry_of_path(fs, "/", &directory);
|
||||||
|
|
||||||
struct fat_dir_struct* dd = fat_open_dir(fs, &directory);
|
struct fat_dir_struct* dd = fat_open_dir(fs, &directory);
|
||||||
|
|
||||||
|
// Get all of the song names
|
||||||
|
struct fat_dir_entry_struct dir_entry;
|
||||||
|
uint8_t song_id = 0;
|
||||||
|
while(fat_read_dir(dd, &dir_entry)) {
|
||||||
|
// too many files!
|
||||||
|
if (song_id == MAX_SONG_NUM) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is file, so add to list
|
||||||
|
if (!(dir_entry.attributes & FAT_ATTRIB_DIR)) {
|
||||||
|
// TODO add checking if its .wav
|
||||||
|
|
||||||
|
// Copy song name into memory
|
||||||
|
uint8_t len = strlen(dir_entry.long_name);
|
||||||
|
songs[song_id].name = malloc(len);
|
||||||
|
strcpy(songs[song_id].name, dir_entry.long_name);
|
||||||
|
|
||||||
|
// Open file and keep info in songs
|
||||||
|
fat_open_file(fs, songs[song_id].fd);
|
||||||
|
|
||||||
|
// Move on to reading next song
|
||||||
|
song_id++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Print out all files/directories in top level
|
// Print out all files/directories in top level
|
||||||
while (1) {
|
while (1) {
|
||||||
struct fat_dir_entry_struct dir_entry;
|
/// do stuff
|
||||||
while(fat_read_dir(dd, &dir_entry)) {
|
|
||||||
// print out directory entry name
|
uint8_t incoming_cmd;
|
||||||
lcd_clrscr();
|
if (fifo_pop(&incoming_cmd) == FIFO_SUCCESS) {
|
||||||
lcd_gotoxy(0,0);
|
// Handle incoming command
|
||||||
lcd_puts(dir_entry.long_name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO check here if we are running into the end of our song buffer, and read in song data
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
16
final_project/sd_reader/main.h
Normal file
16
final_project/sd_reader/main.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#ifndef MAIN_H_
|
||||||
|
#define MAIN_H_
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
#include <avr/sleep.h>
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_config.h"
|
||||||
|
#include "partition.h"
|
||||||
|
#include "sd_raw.h"
|
||||||
|
#include "sd_raw_config.h"
|
||||||
|
#include "fifo.h"
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
16
final_project/sd_reader/periph.c
Normal file
16
final_project/sd_reader/periph.c
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#include "main.h"
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
|
||||||
|
ISR(USART_RX_vect) {
|
||||||
|
cli();
|
||||||
|
// Read byte into FIFO
|
||||||
|
|
||||||
|
sei();
|
||||||
|
}
|
||||||
|
|
||||||
|
ISR(TIMER0_COMPA_vect) {
|
||||||
|
cli();
|
||||||
|
// Handle music playing
|
||||||
|
|
||||||
|
sei();
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user