34 Commits

Author SHA1 Message Date
optixx
23efb8da74 change project 2009-08-24 20:27:28 +02:00
David Voswinkel
dade0ea275 add test dir loop 2009-08-18 09:11:07 +02:00
David Voswinkel
6edd54b092 switch file id to 32bit and get sram push working 2009-08-18 08:38:48 +02:00
David Voswinkel
dc8ed94279 add dir entry debug dump 2009-08-17 22:05:05 +02:00
David Voswinkel
7046230e31 push dir entry to sram 2009-08-17 21:44:38 +02:00
David Voswinkel
ed0a95cad5 fix file_entry struct 2009-08-17 20:39:38 +02:00
David Voswinkel
31768e2a41 Merge branch 'mmc' of git@github.com:optixx/quickdev16 into mmc 2009-08-12 21:19:18 +02:00
optixx
041cf089ad add header 2009-08-12 18:04:54 +02:00
optixx
cf090451df add dir ent to sram copy 2009-08-11 15:42:14 +02:00
David Voswinkel
51876b83ad cleanup 2009-08-10 19:46:45 +02:00
David Voswinkel
8d961dc446 Merge branch 'mmc' of git@github.com:optixx/quickdev16 into mmc
Conflicts:
	avr/usbload/fat.h
	avr/usbload/file.c
	avr/usbload/testing.c
2009-08-10 19:44:15 +02:00
David Voswinkel
9859b1fbc8 cleanup types: 2009-08-10 19:34:03 +02:00
David Voswinkel
8656beb769 code cleanup 2009-08-10 19:26:01 +02:00
optixx
f1f836bdc7 disable file write function and save 4kb progmem 2009-08-10 16:29:36 +02:00
David Voswinkel
4a0740dd02 replace mmc layer with old software spi stuff 2009-08-09 14:19:32 +02:00
David Voswinkel
d095867fe4 try to use irq for CS and use dedicated SS for hardware SPI 2009-08-09 13:12:44 +02:00
David Voswinkel
2aee210d13 switch to mmc-0.5.4 2009-08-09 12:15:06 +02:00
David Voswinkel
a27521b22b first tests 2009-08-09 10:37:51 +02:00
David Voswinkel
2132b572ff add mmc layer 2009-08-08 16:43:51 +02:00
David Voswinkel
dbff180a91 get sram restore working and make the switch to quickdev loader more
mature
2009-08-08 16:04:45 +02:00
David Voswinkel
df167b285e Merge branch 'master' of git@github.com:optixx/quickdev16 2009-08-08 15:06:35 +02:00
David Voswinkel
cd7ac81a2d add debug shm 2009-08-06 22:04:08 +02:00
David Voswinkel
f7dc5b3bd8 add upload progress 2009-08-06 22:03:50 +02:00
David Voswinkel
1f68465dc6 simplify mode swicthing 2009-08-06 21:26:16 +02:00
David Voswinkel
5e5df7e275 remove obsolte slow sram functions and depending higherlevel stuff 2009-08-06 21:25:24 +02:00
David Voswinkel
ba2ac254a7 remove sram_copy and sram_set 2009-08-06 21:18:11 +02:00
David Voswinkel
1282e93334 refactor testing code 2009-08-06 21:16:58 +02:00
David Voswinkel
decb810bcc move commands to own file and remove unsed usb methods 2009-08-06 21:10:25 +02:00
David Voswinkel
b6d5d1b571 add delya/irq switch for shared mem 2009-08-06 20:44:44 +02:00
optixx
406c884cfe add addr save and restore functions 2009-08-06 12:15:04 +02:00
optixx
6ef9989320 add sharedmem read 2009-08-06 11:22:14 +02:00
optixx
97962b8e89 split shared memroy access into tx and rx section 2009-08-06 10:52:44 +02:00
David Voswinkel
cf95b95723 make huffman optional 2009-08-05 20:15:28 +02:00
David Voswinkel
af45ed720b cleanup up and remove huffman stuff 2009-08-04 08:38:26 +02:00
32 changed files with 4672 additions and 3091 deletions

View File

@@ -30,11 +30,16 @@ SIZE = avr-size
ifeq ($(DEBUG),1)
LDFLAGS = -Wl,-u,vfprintf -lprintf_flt
CFLAGS = -Iusbdrv -I. -DDEBUG_LEVEL=0
OBJECTS = usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o main.o usb_bulk.o uart.o fifo.o sram.o crc.o debug.o dump.o timer.o watchdog.o huffman-decode.o rle.c loader.o info.o shared_memory.o
OBJECTS = usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o \
main.o usb_bulk.o uart.o fifo.o sram.o crc.o debug.o \
dump.o timer.o watchdog.o rle.c loader.o info.o shared_memory.o \
command.o mmc.o fat.o file.o dir.o testing.o
else
LDFLAGS = -Wl,-u
CFLAGS = -Iusbdrv -I. -DDEBUG_LEVEL=0 -DNO_DEBUG -DNO_INFO
OBJECTS = usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o main.o usb_bulk.o uart.o fifo.o sram.o crc.o debug.o dump.o timer.o watchdog.o rle.c loader.o info.o shared_memory.o
OBJECTS = usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o main.o usb_bulk.o \
uart.o fifo.o sram.o crc.o debug.o dump.o timer.o watchdog.o rle.c loader.o \
info.o shared_memory.o command.o
endif
COMPILE = avr-gcc -Wall -Os -DF_CPU=$(F_CPU) $(CFLAGS) -mmcu=$(DEVICE)

61
avr/usbload/command.c Normal file
View File

@@ -0,0 +1,61 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include "config.h"
#include "requests.h"
#include "sram.h"
#include "info.h"
extern uint32_t req_bank_size;
void send_reset()
{
info("Reset Snes\n");
snes_reset_on();
snes_reset_lo();
_delay_ms(2);
snes_reset_hi();
snes_reset_off();
}
void send_irq()
{
snes_irq_on();
snes_irq_lo();
_delay_us(20);
snes_irq_hi();
snes_irq_off();
}
void set_rom_mode()
{
if (req_bank_size == 0x8000) {
snes_lorom();
info("Set Snes lowrom \n");
} else {
snes_hirom();
info("Set Snes hirom \n");
}
}

View File

@@ -13,39 +13,17 @@
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#ifndef AVR_HUFFMAN_DECODE_H_
#define AVR_HUFFMAN_DECODE_H_
#include <stdint.h>
#ifndef __COMMAND_H__
#define __COMMAND_H__
#define HUFFMAN_USE_ADDR_16 1
void send_reset();
void send_irq();
void set_rom_mode();
typedef struct {
void* tree;
uint8_t rbuffer;
uint8_t rbuffer_index;
#if HUFFMAN_USE_ADDR_16
uint16_t(*read_byte)(uint16_t addr);
uint16_t addr;
#else
uint16_t(*read_byte)(uint32_t addr);
uint32_t addr;
#endif
} huffman_dec_ctx_t;
#if HUFFMAN_USE_ADDR_16
void huffman_dec_init(huffman_dec_ctx_t* ctx, uint16_t(*rb_func)(uint16_t));
void huffman_dec_set_addr(huffman_dec_ctx_t* ctx,uint16_t addr);
#else
void huffman_dec_init(huffman_dec_ctx_t* ctx, uint16_t(*rb_func)(uint32_t));
void huffman_dec_set_addr(huffman_dec_ctx_t* ctx,uint32_t addr);
#endif
uint16_t huffman_dec_byte(huffman_dec_ctx_t* ctx);
#endif /* AVR_HUFFMAN_DECODE_H_ */

View File

@@ -27,8 +27,9 @@
#define DEBUG_USB_TRANS 4
#define DEBUG_SRAM 8
#define DEBUG_SRAM_RAW 16
#define DEBUG_SREG 32
#define DEBUG_FAT 32
#define DEBUG_CRC 64
#define DEBUG_SHM 128
#define REQ_STATUS_IDLE 0x01
#define REQ_STATUS_UPLOAD 0x02

View File

@@ -91,31 +91,13 @@ uint16_t crc_check_bulk_memory(uint32_t bottom_addr, uint32_t top_addr, uint32_t
void crc_check_memory(uint32_t bottom_addr,uint32_t top_addr,uint32_t bank_size,uint8_t *buffer)
{
uint16_t crc = 0;
uint32_t addr;
uint8_t req_bank = 0;
for (addr = bottom_addr; addr < top_addr; addr += TRANSFER_BUFFER_SIZE) {
if (addr && addr % bank_size == 0) {
debug(DEBUG_CRC,"crc_check_memory: bank=0x%02x addr=0x%08lx crc=0x%04x\n",
req_bank,addr,crc);
req_bank++;
crc = 0;
}
sram_read_buffer(addr, buffer, TRANSFER_BUFFER_SIZE);
crc = do_crc_update(crc, buffer, TRANSFER_BUFFER_SIZE);
}
}
uint16_t crc_check_memory_range(uint32_t start_addr, uint32_t size,uint8_t *buffer)
{
uint16_t crc = 0;
uint32_t addr;
for (addr = start_addr; addr < start_addr + size; addr += TRANSFER_BUFFER_SIZE) {
sram_read_buffer(addr, buffer, TRANSFER_BUFFER_SIZE);
sram_bulk_read_buffer(addr, buffer, TRANSFER_BUFFER_SIZE);
crc = do_crc_update(crc, buffer, TRANSFER_BUFFER_SIZE);
}
return crc;

View File

@@ -29,7 +29,6 @@
uint16_t crc_xmodem_update(uint16_t crc, uint8_t data);
uint16_t do_crc(uint8_t * data,uint16_t size);
uint16_t do_crc_update(uint16_t crc,uint8_t * data,uint16_t size);
void crc_check_memory(uint32_t bottom_addr,uint32_t top_addr,uint32_t bank_size,uint8_t *buffer);
uint16_t crc_check_memory_range(uint32_t start_addr, uint32_t size,uint8_t *buffer);
uint16_t crc_check_bulk_memory(uint32_t bottom_addr, uint32_t bank_size,uint32_t top_addr);

96
avr/usbload/dir.c Normal file
View File

@@ -0,0 +1,96 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#include "dir.h"
#include "file.h"
#include "fat.h"
#include "debug.h"
#include "sram.h"
#include "config.h"
#include <string.h>
uint16_t position = 0;
extern struct File file;
void dir_entry_start(){
position = 0;
}
void dir_entry_dump(uint32_t addr, dir_ent_t* ent){
debug(DEBUG_FAT,"dir_entry_dump: addr=0x%06lx id=%li name=%s size=%li attr=%i\n", addr, ent->id, ent->file_name,
ent->file_size, ent->file_attr);
}
void dir_entry_add(uint32_t id, uint8_t* file_name,uint32_t file_size,uint8_t file_attr){
uint32_t addr;
dir_ent_t ent;
strncpy(ent.file_name,file_name,13);
ent.id = id;
ent.file_size = file_size;
ent.file_attr = file_attr;
addr = DIR_ENTRY_LOC + (position << DIR_ENTRY_SIZE_SHIFT );
sram_bulk_copy(addr, (uint8_t *) &ent, DIR_ENTRY_SIZE );
dir_entry_dump(addr, &ent);
position++;
}
void dir_entry_header(uint16_t idx, uint8_t * header){
uint32_t addr;
addr = DIR_ENTRY_LOC + ( idx << DIR_ENTRY_SIZE_SHIFT ) + DIR_ENTRY_HEADER_OFF;
sram_bulk_copy(addr, (uint8_t *) header, DIR_ENTRY_HEADER_SIZE);
}
uint32_t dir_entry_get(uint32_t idx, dir_ent_t* ent){
uint32_t addr;
addr = DIR_ENTRY_LOC + ( idx << DIR_ENTRY_SIZE_SHIFT );
sram_bulk_read_buffer( addr, (uint8_t *) ent, DIR_ENTRY_SIZE);
return addr;
}
void dir_entry_loop(){
uint8_t i;
uint8_t j;
uint32_t addr;
dir_ent_t ent;
for (i=0; i< position; i++){
addr = dir_entry_get(i,&ent);
dir_entry_dump(addr,&ent);
ffopen( ent.file_name );
if (file.length != 524288){
ffclose();
continue;
}
//ffseek(0x7fc0);
for (j=0; j< 64; j++)
printf ("0x%02x " ,ffread());
printf("\n");
ffclose();
}
}

64
avr/usbload/dir.h Normal file
View File

@@ -0,0 +1,64 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#ifndef __DIR_H__
#define __DIR_H__
#include <stdlib.h>
#include <stdint.h>
#define DIR_ENTRY_LOC 0x010000
#define DIR_ENTRY_SIZE 64
#define DIR_ENTRY_SIZE_SHIFT 6
#define DIR_ENTRY_HEADER_SIZE 44
#define DIR_ENTRY_HEADER_OFF 20
typedef struct {
uint32_t id; // 4
uint8_t file_name[13]; // 8.3 = 12 + 1 = 13
uint32_t file_size; // 4
uint8_t file_attr; // 1
uint8_t snes_header[41]; // 41
} dir_ent_t; // 64
void dir_entry_start();
void dir_entry_add(uint32_t id, uint8_t* file_name,uint32_t file_size,uint8_t file_attr);
void dir_entry_header(uint16_t position, uint8_t * header);
/*
lo:
0x7fc0
0x7fc0 + 0x200
hi:
0xffc0
0xffc0 + 0x200
emulated reset vector MSB must be set
sei
clc
xce
*/
#endif

View File

@@ -31,4 +31,4 @@ void dump_memory(uint32_t bottom_addr, uint32_t top_addr);
void dump_packet(uint32_t addr,uint32_t len,uint8_t *packet);
#endif

668
avr/usbload/fat.c Normal file
View File

@@ -0,0 +1,668 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include "fat.h"
#include "file.h"
#include "mmc.h"
#include "config.h"
struct Fat fat; // wichtige daten/variablen der fat
struct File file; // wichtige dateibezogene daten/variablen
#if (WRITE==1)
// ***************************************************************************************************************
// schreibt sektor nummer:sec auf die karte (puffer:sector) !!
// setzt bufferFlag=0 da puffer nicht dirty sein kann nach schreiben !
// ***************************************************************************************************************
uint8_t fat_writeSector(uint32_t sec)
{
fat.bufferDirty = 0; // buffer kann nicht dirty sein weil wird geschrieben
return (mmc_write_sector(sec, fat.sector)); // schreiben von sektor puffer
}
#endif
// ***************************************************************************************************************
// umrechnung cluster auf 1.sektor des clusters (möglicherweise mehrere sektoren/cluster) !
// ***************************************************************************************************************
uint32_t fat_clustToSec(uint32_t clust)
{
return (fat.dataDirSec + 2 + ((clust - 2) * fat.secPerClust)); // errechnet den 1. sektor der sektoren des clusters
}
// ***************************************************************************************************************
// umrechnung sektor auf cluster (nicht die position im cluster selber!!)
// ***************************************************************************************************************
uint32_t fat_secToClust(uint32_t sec)
{
return ((sec - fat.dataDirSec - 2 + 2 * fat.secPerClust) / fat.secPerClust); // umkerhrfunktion von fat_clustToSec
}
// ***************************************************************************************************************
// läd sektor:sec auf puffer:sector zum bearbeiten im ram !
// setzt currentSectorNr auf richtigen wert (also den sektor der gepuffert ist). es wird geprüft
// ob der gepufferte sektor geändert wurde, wenn ja muss erst geschrieben werden, um diese daten nicht zu verlieren !
// ***************************************************************************************************************
uint8_t fat_loadSector(uint32_t sec)
{
if (sec != fat.currentSectorNr) { // nachladen nötig
#if (WRITE==1)
if (fat.bufferDirty == 1)
fat_writeSector(fat.currentSectorNr); // puffer diry, also vorher schreiben
#endif
mmc_read_sector(sec, fat.sector); // neuen sektor laden
fat.currentSectorNr = sec; // aktualisiert sektor nummer (nummer des gepufferten sektors)
return (0);
}
else
return (0); // alles ok, daten sind schon da (sec==fat.currentSectorNr)
return (1); // fehler
}
// datei lesen funktionen:
// fat_loadSector -> fat_loadRowOfSector -> fat_loadFileDataFromCluster -> fat_loadFileDataFromDir -> fat_loadFileDataFromDir -> fat_cd
// "daten chain"
// ***************************************************************************************************************
// läd die reihe:row des gepufferten sektors auf das struct:file. dort stehen dann
// alle wichgigen daten wie: 1.cluster,länge bei dateien, name des eintrags, reihen nummer (im sektor), attribut use...
// ***************************************************************************************************************
uint8_t fat_loadRowOfSector(uint16_t row)
{
uint8_t i;
row = row << 5; // multipliziert mit 32 um immer auf zeilen anfang zu kommen (zeile 0=0,zeile 1=32,zeile 2=62 usw).
void *vsector; // void, damit man schoen umbiegen kann :)
for (i = 0; i < 11; i++)
file.name[i] = fat.sector[row + i]; // datei name, ersten 10 bytes vom 32 byte eintrag.
file.attrib = fat.sector[row + 11]; // datei attribut, byte 11.
vsector = &fat.sector[row + 26]; // low word von fist.cluster
file.firstCluster = *(uint16_t *) vsector;
vsector = &fat.sector[row + 20]; // high word von first.cluster
file.firstCluster |= (*(uint16_t *) vsector) << 16;
vsector = &fat.sector[row + 28]; // 4 byte von file.length
file.length = *(uint32_t *) vsector;
return (0);
}
// ***************************************************************************************************************
// geht reihen weise durch sektoren des clusters mit dem startsektor:sec, und sucht nach der datei mit dem
// namen:name. es werden die einzelnen sektoren nachgeladen auf puffer:sector vor dem bearbeiten.
// wird die datei in dem cluster gefunden ist return 0 , sonst return1.
// ***************************************************************************************************************
uint8_t fat_loadFileDataFromCluster(uint32_t sec, char name[])
{
uint8_t r;
uint8_t s = 0;
do { // sektoren des clusters prüfen
r = 0; // neuer sektor, dann reihen von 0 an.
mmc_read_sector(sec + s, fat.sector); // läd den sektor sec auf den puffer fat.sector
fat.currentSectorNr = sec + s; // setzen des aktuellen sektors
do { // reihen des sektors prüfen
fat_loadRowOfSector(r); // zeile 0-15 auf struct file laden
if (file.name[0] == 0) { // wenn man auf erste 0 stößt müsste der rest auch leer sein!
file.row = r; // zeile sichern.
return (1);
}
if (0 == strncmp((char *) file.name, name, 10)) { // zeile r ist gesuchte
file.row = r; // zeile sichern.
return (0);
}
r++;
} while (r < 16); // zählt zeilennummer (16(zeilen) * 32(spalten) == 512 bytes des sektors)
s++;
} while (s < fat.secPerClust); // geht durch sektoren des clusters
return (1); // fehler (datei nicht gefunden, oder fehler beim lesen)
}
// ***************************************************************************************************************
// wenn dir == 0 dann wird das root direktory durchsucht, wenn nicht wird der ordner cluster-chain gefolgt, um
// die datei zu finden. es wird das komplette directory in dem man sich befindet durchsucht.
// bei fat16 wird der rootDir berreich durchsucht, bei fat32 die cluster chain des rootDir.
// ***************************************************************************************************************
uint8_t fat_loadFileDataFromDir(char name[])
{
uint16_t s;
if (fat.dir == 0 && fat.fatType == 16) { // IM ROOTDIR. fat16
for (s = 0; s < (uint16_t) (fat.dataDirSec + 2 - fat.rootDir); s++) { // zählt durch RootDir sektoren (errechnet anzahl
// rootDir sektoren).
if (0 == fat_loadFileDataFromCluster(fat.rootDir + s, name))
return (0); // sucht die datei, wenn da, läd daten (1.cluster usw)
}
}
else {
uint32_t i;
if (fat.dir == 0 && fat.fatType == 32)
i = fat.rootDir; // IM ROOTDIR. fat32
else
i = fat.dir; // NICHT ROOTDIR
while (!((i == 0xfffffff && fat.fatType == 32) || (i == 0xffff && fat.fatType == 16))) { // prüft ob weitere sektoren zum
// lesen da sind (fat32||fat16)
if (0 == fat_loadFileDataFromCluster(fat_clustToSec(i), name))
return (0); // lät die daten der datei auf struct:file. datei gefunden (umrechnung auf absoluten sektor)
i = fat_getNextCluster(i); // liest nächsten cluster des dir-eintrags (unterverzeichniss größer 16 einträge)
}
}
return (1); // datei/verzeichniss nicht gefunden
}
#if (SMALL_FILE_SYSTEM==0)
// ***************************************************************************************************************
// start immer im root Dir. start in root dir (dir==0).
// es MUSS in das direktory gewechselt werden, in dem die datei zum lesen/anhängen ist (außer root, da startet mann)!
// ***************************************************************************************************************
uint8_t fat_cd(char name[])
{
if (name[0] == 0) { // ZUM ROOTDIR FAT16/32
fat.dir = 0; // root dir
return (0);
}
if (0 == fat_loadFileDataFromDir(name)) { // NICHT ROOTDIR (fat16/32)
fat.dir = file.firstCluster; // zeigt auf 1.cluster des dir (fat16/32)
return (0);
}
return (1); // dir nicht gewechselt (nicht da?) !!
}
#endif
#if (WRITE==1)
// datei anlegen funktionen :
// ***************************************************************************************************************
// sucht leeren eintrag (zeile) im cluster mit dem startsektor:secStart.
// wird dort kein freier eintrag gefunden ist return (1).
// wird ein freier eintrag gefunden, ist die position der freien reihe auf file.row abzulesen und return (0).
// der sektor mit der freien reihe ist auf dem puffer:sector gepuffert.
// ****************************************************************************************************************
uint8_t fat_getFreeRowOfCluster(unsigned long secStart)
{
uint16_t b; // zum durchgenen der sektor bytes
uint8_t s = 0; // sektoren des clusters.
do {
file.row = 0; // neuer sektor(oder 1.sektor), reihen von vorne.
if (0 == fat_loadSector(secStart + s)) { // laed sektor auf puffer fat.sector
for (b = 0; b < 512; b = b + 32) { // zaehlt durch zeilen (0-15).
if (fat.sector[b] == 0x00 || fat.sector[b] == 0xE5)
return (0); // prueft auf freihen eintrag (leer oder geloescht == OK!).
file.row++; // zählt reihe hoch (nächste reihe im sektor).
}
}
s++; // sektoren des clusters ++ weil einen geprüft.
} while (s < fat.secPerClust); // geht die sektoren des clusters durch (moeglicherweise auch nur 1. sektor).
return (1); // nicht gefunden in diesem cluster (== nicht OK!).
}
// ***************************************************************************************************************
// sucht leeren eintrag (zeile) im directory mit dem startcluster:dir.
// geht die cluster chain des direktories durch. dabei werden auch alle sektoren der cluster geprüft.
// wird dort kein freier eintrag gefunden, wird ein neuer leerer cluster gesucht, verkettet und der
// 1. sektor des freien clusters geladen. die reihe wird auf den ersten eintrag gesetzt, da frei.
// anhand der reihe kann man nun den direktory eintrag vornehmen, und auf die karte schreiben.
// ****************************************************************************************************************
void fat_getFreeRowOfDir(uint32_t dir)
{
uint32_t start = dir;
// solange bis ende cluster chain.
while (!
((dir == 0xfffffff && fat.fatType == 32)
|| (dir == 0xffff && fat.fatType == 16))) {
if (0 == fat_getFreeRowOfCluster(fat_clustToSec(dir)))
return; // freien eintrag in clustern, des dir gefunden !!
start = dir;
dir = fat_getNextCluster(dir);
} // wenn aus schleife raus, kein freier eintrag da -> neuer cluster nötig.
dir = fat_secToClust(fat.startSectors); // dir ist jetzt neuer cluster zum verketten !
fat_setCluster(start, dir); // cluster-chain mit neuem cluster verketten
fat_setCluster(dir, 0x0fffffff); // cluster-chain ende markieren
// es muessen neue gesucht werden, weil der bekannte aus file.c ja grade verkettet wurden. datei eintrag passte nicht mehr ins dir...
fat_getFreeClustersInRow(2); // neue freie cluster suchen, für datei.
file.firstCluster = fat_secToClust(fat.startSectors); // 1. cluster der datei
file.lastCluster = fat_secToClust(fat.endSectors); // letzter bekannter cluster der datei
fat.currentSectorNr = fat_clustToSec(dir); // setzen des richtigen sektors, also auf den 1. der neu verketteten
uint16_t j = 511;
do {
fat.sector[j] = 0x00; // schreibt puffer fat.sector voll mit 0x00==leer
} while (j--);
uint8_t i = 1; // ab 1 weil der 1.sektor des clusters eh noch beschrieben wird...
do {
fat_writeSector(fat.currentSectorNr + i); // löschen des cluster (überschreibt mit 0x00), wichtig bei ffls,
i++;
} while (i < fat.secPerClust);
file.row = 0; // erste reihe frei, weil grad neuen cluster verkettet !
}
// ***************************************************************************************************************
// erstellt 32 byte eintrag einer datei, oder verzeichnisses im puffer:sector.
// erstellt eintrag in reihe:row, mit namen:name usw... !!
// muss noch auf die karte geschrieben werden ! nicht optimiert auf geschwindigkeit.
// ***************************************************************************************************************
void fat_makeRowDataEntry(uint16_t row, char name[], uint8_t attrib,
uint32_t cluster, uint32_t length)
{
fat.bufferDirty = 1; // puffer beschrieben, also neue daten darin(vor lesen muss geschrieben werden)
row = row << 5; // multipliziert mit 32 um immer auf zeilen anfang zu kommen (zeile 0=0,zeile 1=32,zeile 2=62 ... zeile
// 15=480)
uint8_t i; // byte zähler in reihe von sektor (32byte eintrag)
uint8_t *bytesOfSec = &fat.sector[row]; // zeiger auf sector bytes
void *vsector;
for (i = 0; i < 11; i++)
*bytesOfSec++ = name[i]; // namen schreiben
*bytesOfSec++ = attrib; // attrib schreiben
vsector = &fat.sector[row + 12];
*(uint32_t *) vsector++ = 0x01010101; // unnoetige felder beschreiben
*(uint32_t *) vsector = 0x01010101;
vsector = &fat.sector[row + 20];
*(uint16_t *) vsector = (cluster & 0xffff0000) >> 16; // low word von cluster
vsector = &fat.sector[row + 22];
*(uint32_t *) vsector = 0x01010101; // unnoetige felder beschreiben
vsector = &fat.sector[row + 26];
*(uint16_t *) vsector = (cluster & 0x0000ffff); // high word von cluster
vsector = &fat.sector[row + 28];
*(uint32_t *) vsector = length; // laenge
}
// ***************************************************************************************************************
// macht den datei eintrag im jetzigen verzeichniss (fat.dir).
// file.row enthält die reihen nummer des leeren eintrags, der vorher gesucht wurde, auf puffer:sector ist der gewünschte
// sektor gepuffert. für fat16 im root dir muss andere funktion genutzt werden, als fat_getFreeRowOfDir (durchsucht nur dirs).
// fat.rootDir enthält bei fat32 den start cluster des directory, bei fat16 den 1. sektor des rootDir bereichs!
// ***************************************************************************************************************
void fat_makeFileEntry(char name[], uint8_t attrib,
uint32_t length)
{
uint16_t s; // zähler für root dir sektoren fat16
if (fat.dir == 0 && fat.fatType == 32)
fat_getFreeRowOfDir(fat.rootDir); // IM ROOT DIR (fat32)
else if (fat.dir == 0 && fat.fatType == 16) { // IM ROOT DIR (fat16)
for (s = 0; s < (uint16_t) (fat.dataDirSec + 2 - fat.rootDir); s++) { // zählt durch RootDir sektoren (errechnet anzahl
// rootDir sektoren).
if (0 == fat_getFreeRowOfCluster(fat.rootDir + s))
break; // geht durch sektoren des root dir.
}
}
else
fat_getFreeRowOfDir(fat.dir); // NICHT ROOT DIR fat32/fat16
fat_makeRowDataEntry(file.row, name, attrib, file.firstCluster, length); // schreibt file eintrag auf puffer
fat_writeSector(fat.currentSectorNr); // schreibt puffer auf karte
}
#endif
// fat funktionen:
// ***************************************************************************************************************
// sucht nötige folge Cluster aus der fat !
// erster daten cluster = 2, ende einer cluster chain 0xFFFF (fat16) oder 0xFFFFFFF, 0xFFFFFF8 (fat32),
// stelle des clusters in der fat, hat als wert, den nächsten cluster. (1:1 gemapt)!
// ***************************************************************************************************************
uint32_t fat_getNextCluster(uint32_t oneCluster)
{
// FAT 16**************FAT 16
if (fat.fatType == 16) {
uint32_t i = oneCluster >> 8;; // (i=oneCluster/256)errechnet den sektor der fat in dem oneCluster ist (rundet immer ab)
uint32_t j = (oneCluster << 1) - (i << 9); // (j=(oneCluster-256*i)*2 == 2*oneCluster-512*i)errechnet das low byte von
// oneCluster
if (0 == fat_loadSector(i + fat.fatSec)) { // ob neu laden nötig, wird von fat_loadSector geprüft
void *bytesOfSec = &fat.sector[j]; // zeiger auf puffer
return *(uint16_t *) bytesOfSec; // da der ram auch little endian ist, kann einfach gecastet werden und gut :)
}
}
// FAT 32**************FAT 32
else {
uint32_t i = oneCluster >> 7; // (i=oneCluster/128)errechnet den sektor der fat in dem oneCluster ist (rundet immer ab)
uint32_t j = (oneCluster << 2) - (i << 9); // (j=(oneCluster-128*i)*4 == oneCluster*4-512*i)errechnet das low byte von
// oneCluster
if (0 == fat_loadSector(i + fat.fatSec)) { // ob neu laden nötig wird von fat_loadSector geprüft
void *bytesOfSec = &fat.sector[j]; // zeiger auf puffer
return *(uint32_t *) bytesOfSec; // da der ram auch little endian ist, kann einfach gecastet werden und gut :)
}
}
return (0);
}
// ***************************************************************************************************************
// sucht verkettete cluster einer datei, die in einer reihe liegen. worst case: nur ein cluster.
// sieht in der fat ab dem cluster offsetCluster nach. sucht die anzahl von MAX_CLUSTERS_IN_ROW,
// am stück,falls möglich. prüft ob der cluster neben offsetCluster dazu gehört...
// setzt dann fat.endSectors und fat.startSectors. das -1 weil z.b. [95,98] = {95,96,97,98} = 4 sektoren
// ***************************************************************************************************************
void fat_getFatChainClustersInRow(uint32_t offsetCluster)
{
uint16_t i = 0;
fat.startSectors = fat_clustToSec(offsetCluster); // setzen des 1. sektors der datei
fat.endSectors = fat.startSectors;
do {
if ((offsetCluster + 1 + i) == fat_getNextCluster(offsetCluster + i))
fat.endSectors += fat.secPerClust; // zählen der zusammenhängenden sektoren
else {
file.lastCluster = offsetCluster + i; // cluster daneben gehört nicht dazu, somit ist offset+i der letzte bekannte
break;
}
} while (i++ < MAX_CLUSTERS_IN_ROW);
fat.endSectors += fat.secPerClust - 1;
}
#if (WRITE==1)
// ***************************************************************************************************************
// sucht freie zusammenhängende cluster aus der fat. maximal MAX_CLUSTERS_IN_ROW am stück.
// erst wir der erste frei cluster gesucht, ab offsetCluster(iklusive) und dann wird geschaut, ob der
// daneben auch frei ist. setzt dann fat.endSectors und fat.startSectors. das -1 weil z.b. [95,98] = {95,96,97,98} = 4 sektoren
// ***************************************************************************************************************
void fat_getFreeClustersInRow(uint32_t offsetCluster)
{
uint16_t i = 1; // variable für anzahl der zu suchenden sektoren
while (fat_getNextCluster(offsetCluster))
offsetCluster++; // suche des 1. freien clusters
fat.startSectors = fat_clustToSec(offsetCluster); // setzen des startsektors der freien sektoren (umrechnen von cluster zu sektoren)
fat.endSectors = fat.startSectors;
do { // suche der nächsten freien
if (0 == fat_getNextCluster(offsetCluster + i))
fat.endSectors += fat.secPerClust; // zählen der zusammenhängenden sektoren
else
break; // cluster daneben ist nicht frei
} while (i++ < MAX_CLUSTERS_IN_ROW);
fat.endSectors += fat.secPerClust - 1; // -1 weil der erste sektor schon mit zählt z.b. [95,98] = 4 sektoren
}
// ***************************************************************************************************************
// verkettet ab startCluster bis einschließlich endCluster. verkettet auch den letzten bekannten mit den neu übergebenen !
// es ist wegen der fragmentierung der fat nötig, sich den letzten bekannten cluster zu merken,
// damit man bei weiteren cluster in einer reihe die alten cluster noch dazu verketten kann (so sind lücken im verketten möglich).
// ***************************************************************************************************************
void fat_setClusterChain(uint32_t startCluster,
uint16_t endCluster)
{
fat_setCluster(file.lastCluster, startCluster); // ende der chain setzen, bzw verketten der ketten
while (startCluster != endCluster) {
startCluster++;
fat_setCluster(startCluster - 1, startCluster); // verketten der cluster der neuen kette
}
fat_setCluster(startCluster, 0xfffffff); // ende der chain setzen
file.lastCluster = endCluster; // ende cluster der kette updaten
fat_writeSector(fat.currentSectorNr); // schreiben des fat sektors auf die karte
}
// ***************************************************************************************************************
// setzt den cluster inhalt. errechnet den sektor der fat in dem cluster ist, errechnet das low byte von
// cluster und setzt dann byteweise den inhalt:content.
// prüft ob buffer dirty (zu setztender cluster nicht in jetzt gepuffertem).
// prüfung erfolgt in fat_loadSector, dann wird alter vorher geschrieben, sonst gehen dort daten verloren !!
// ***************************************************************************************************************
void fat_setCluster(uint32_t cluster, uint32_t content)
{
// FAT 16**************FAT 16
if (fat.fatType == 16) {
uint32_t i = cluster >> 8; // (i=cluster/256)errechnet den sektor der fat in dem cluster ist (rundet immer ab)
uint32_t j = (cluster << 1) - (i << 9); // (j=(cluster-256*i)*2 == 2*cluster-512*i)errechnet das low byte von
// cluster
if (0 == fat_loadSector(i + fat.fatSec)) { // neu laden (fat_loadSector prüft ob schon gepuffert)
void *bytesOfSec = &fat.sector[j]; // init des zeigers auf unterste adresse
*(uint16_t *) bytesOfSec = content; // weil ram auch little endian geht das so :)
fat.bufferDirty = 1; // zeigt an, dass im aktuellen sector geschrieben wurde
}
}
// FAT 32**************FAT 32
else {
uint32_t i = cluster >> 7; // (i=cluster/128)errechnet den sektor der fat in dem cluster ist (rundet immer ab)
uint32_t j = (cluster << 2) - (i << 9); // (j=(cluster-128*i)*4 == cluster*4-512*i)errechnet das low byte von
// cluster
if (0 == fat_loadSector(i + fat.fatSec)) { // neu laden (fat_loadSector prüft ob schon gepuffert)
void *bytesOfSec = &fat.sector[j]; // init des zeigers auf unterste adresse
*(uint32_t *) bytesOfSec = content; // weil ram auch little endian geht das so :)
fat.bufferDirty = 1; // zeigt an, dass im aktuellen sector geschrieben wurde
}
}
}
// ***************************************************************************************************************
// löscht cluster chain, beginnend ab dem startCluster.
// sucht cluster, setzt inhalt usw.. abschließend noch den cluster-chain ende markierten cluster löschen.
// ***************************************************************************************************************
void fat_delClusterChain(uint32_t startCluster)
{
uint32_t nextCluster = startCluster; // tmp variable, wegen verketteter cluster..
do {
startCluster = nextCluster;
nextCluster = fat_getNextCluster(startCluster);
fat_setCluster(startCluster, 0x00000000);
} while (!
((nextCluster == 0xfffffff && fat.fatType == 32)
|| (nextCluster == 0xffff && fat.fatType == 16)));
fat_writeSector(fat.currentSectorNr);
}
#endif
// ***************************************************************************************************************
// Initialisiert die Fat(16/32) daten, wie: root directory sektor, daten sektor, fat sektor...
// siehe auch Fatgen103.pdf. ist NICHT auf performance optimiert!
// byte/sector, byte/cluster, anzahl der fats, sector/fat ... (halt alle wichtigen daten zum lesen ders datei systems!)
// *****************************************************************<**********************************************
uint8_t fat_loadFatData(uint32_t sec)
{
// offset,size
uint16_t rootEntCnt; // 17,2 größe die eine fat belegt
uint16_t fatSz16; // 22,2 sectors occupied by one fat16
uint32_t fatSz32; // 36,4 sectors occupied by one fat32
void *vsector;
if (0 == mmc_read_sector(sec, fat.sector)) { // lesen von fat sector und bestimmen der wichtigen berreiche
fat.bufferDirty = 0; // init wert des flags
fat.secPerClust = fat.sector[13]; // fat.secPerClust, 13 only (power of 2)
vsector = &fat.sector[14];
fat.fatSec = *(uint16_t *) vsector;
vsector = &fat.sector[17];
rootEntCnt = *(uint16_t *) vsector;
vsector = &fat.sector[22];
fatSz16 = *(uint16_t *) vsector;
fat.rootDir = (((rootEntCnt << 5) + 512) / 512) - 1; // ist 0 bei fat 32, sonst der root dir sektor
if (fat.rootDir == 0) { // FAT32 spezifisch (die prüfung so, ist nicht spezifikation konform !).
vsector = &fat.sector[36];
fatSz32 = *(uint32_t *) vsector;
vsector = &fat.sector[44];
fat.rootDir = *(uint32_t *) vsector;
fat.dataDirSec = fat.fatSec + (fatSz32 * fat.sector[16]); // data sector (beginnt mit cluster 2)
fat.fatType = 32; // fat typ
}
else { // FAT16 spezifisch
fat.dataDirSec = fat.fatSec + (fatSz16 * fat.sector[16]) + fat.rootDir; // data sektor (beginnt mit cluster 2)
fat.rootDir = fat.dataDirSec - fat.rootDir; // root dir sektor, da nicht im datenbereich (cluster)
fat.rootDir += sec; // addiert den startsektor auf "
fat.fatType = 16; // fat typ
}
fat.fatSec += sec; // addiert den startsektor auf
fat.dataDirSec += sec; // addiert den startsektor auf (umrechnung von absolut auf real)
fat.dataDirSec -= 2; // zeigt auf 1. cluster
fat.dir = 0; // dir auf '0'==root dir, sonst 1.Cluster des dir
return (0);
}
return (1); // sector nicht gelesen, fat nicht initialisiert!!
}
// ************************************************************************************************<<***************
// int fat sucht den 1. cluster des dateisystems (fat16/32) auch VBR genannt,
// ************************************************************************************************<<***************
uint8_t fat_initfat(void)
{
uint32_t secOfFirstPartition = 0; // ist 1. sektor der 1. partition aus dem MBR
if (0 == mmc_read_sector(0, fat.sector)) {
void *vsector = &fat.sector[454]; // startsektor bestimmen
secOfFirstPartition = *(uint32_t *) vsector;
// prüfung ob man schon im VBR gelesen hat (0x6964654d = "Medi")
if (secOfFirstPartition == 0x6964654d)
return fat_loadFatData(0); // ist superfloppy
else {
return fat_loadFatData(secOfFirstPartition);
} // ist partitioniert...
}
return (1);
}
#if (SMALL_FILE_SYSTEM==0)
// *****************************************************************************************************************
// bereitet str so auf, dass man es auf die mmc/sd karte schreiben kann.
// wandelt z.b. "t.txt" -> "T TXT" oder "main.c" in "MAIN C " => also immer 8.3 und upper case letter
// VORSICHT es werden keine Prüfungen gemacht !
// *****************************************************************************************************************
char *fat_str(char *str)
{
uint8_t i;
uint8_t j = 0;
uint8_t c;
char tmp[12]; // tmp string zum einfacheren umwandeln
strcpy(tmp, str);
for (i = 0; i < 11; i++)
str[i] = ' '; // als vorbereitung alles mit leerzeichen füllen
str[11] = '\0';
i = 0;
do {
c = toupper(tmp[j]);
if (c == '\0')
return str;
if (c != '.')
str[i] = c;
else
i = 7;
i++;
j++;
} while (i < 12);
return str;
}
#endif

78
avr/usbload/fat.h Normal file
View File

@@ -0,0 +1,78 @@
#ifndef _FAT_H
#define _FAT_H
// **************************************************************************************************************************
// WICHTIGE SCHLATER: -> hier kann die code größe angepasst werden, zu lasten der funktionalität !
// die fat nicht fragmentiert ist !
#define SMALL_FILE_SYSTEM 0 // wenn 1 dann ist kleines file system, wenn 0 dann komplette file unterstützung !
#define WRITE 0 // wenn 1 dann ist write an, wenn 0 dann read only !
#define OVER_WRITE 0 // wenn 1 dann kann ffwrite dateien überschreiben (nicht performant), wenn 0 dann nur normales schreiben !
#define MAX_CLUSTERS_IN_ROW 256 // gibt an wie viele cluster am stück ohne fat lookup geschrieben bzw gelesen werden können, wenn die fat nicht fragmentiert ist !
// 1. fat_getFreeRowOfCluster -> fat_getFreeRowOfDir -> fat_makeRowDataEntry -> fat_makeFileEntry -> fat_writeSector "eintrag gemacht !!"
// 2. fat_loadSector -> fat_loadRowOfSector -> fat_loadFileDataFromCluster -> fat_loadFileDataFromDir (-> fat_cd) "daten chain"
// **************************************************************************************************************************
// funktionen
extern uint32_t fat_clustToSec(uint32_t); // rechnet cluster zu 1. sektor des clusters um
extern uint32_t fat_secToClust(uint32_t sec); // rechnet sektor zu cluster um!
extern uint32_t fat_getNextCluster(uint32_t oneCluster); // fat auf nächsten, verketteten cluster durchsuchen
extern uint8_t fat_initfat(void); // initalisierung (durchsucht MBR oder nicht)
extern uint8_t fat_writeSector(uint32_t sec); // schreibt sektor auf karte
extern void fat_setCluster(uint32_t cluster, uint32_t content); // setzt cluster inhalt in der fat
extern void fat_delClusterChain(uint32_t startCluster); // löscht cluster-chain in der fat
extern void fat_getFreeRowOfDir(uint32_t dir); // durchsucht directory nach feiem eintrag
extern void fat_makeFileEntry(char name[], uint8_t attrib,
uint32_t length);
extern uint8_t fat_loadSector(uint32_t sec); // läd übergebenen absoluten sektor
extern uint8_t fat_loadFileDataFromDir(char name[]); // durchsucht das aktuelle directory
extern uint8_t fat_cd(char *); // wechselt directory (start im rootDir)
extern uint8_t fat_loadFatData(uint32_t); // läd fat daten
extern uint8_t fat_getFreeRowOfCluster(unsigned long secStart); // durchsucht cluster nach freiem eintrag
extern void fat_getFreeClustersInRow(uint32_t offsetCluster); // sucht zusammenhängende freie cluster aus der fat
extern void fat_getFatChainClustersInRow(uint32_t offsetCluster); // sucht fat-chain cluster die zusammenhängen
extern void fat_makeRowDataEntry(uint16_t row, char name[],
uint8_t attrib,
uint32_t cluster,
uint32_t length);
extern uint8_t fat_loadRowOfSector(uint16_t); // läd reihe des geladen sektors auf struct:file
extern uint8_t fat_loadFileDataFromCluster(uint32_t sec, char name[]); // durchsucht die reihen des geladenen sektors
extern void fat_setClusterChain(uint32_t newOffsetCluster,
uint16_t length);
extern char *fat_str(char *str); // wandelt einen string so, dass er der fat konvention entspricht !
// **************************************************************************************************************************
// variablen
extern struct Fat { // fat daten (1.cluster, root-dir, dir usw.)
uint8_t sector[512]; // der puffer für sektoren !
uint8_t bufferDirty; // puffer wurde beschrieben, sector muss geschrieben werden bevor er neu geladen wird
uint32_t currentSectorNr; // aktuell geladener Sektor (in sector) //beschleunigt wenn z.b 2* 512 byte puffer vorhanden, oder
// bei fat operationen im gleichen sektor
uint32_t dir; // Direktory zeiger rootDir=='0' sonst(1.Cluster des dir; start auf root)
uint32_t rootDir; // Sektor(f16)/Cluster(f32) nr root directory
uint32_t dataDirSec; // Sektor nr data area
uint32_t fatSec; // Sektor nr fat area
uint32_t startSectors; // der erste sektor in einer reihe (freie oder verkettete)
uint32_t endSectors;
uint8_t secPerClust; // anzahl der sektoren pro cluster
uint8_t fatType; // fat16 oder fat32 (16 oder 32)
} fat;
extern struct File { // datei infos
uint16_t cntOfBytes; // -nicht direkt aus dem dateisystem- zäht geschriebene bytes eines sektors
uint8_t name[13]; // 0,10 datei Name.ext (8.3 = max 11)(MUSS uint8_t weil E5)
uint8_t attrib; // 11,1 datei Attribut: 8=value name, 32=datei, 16=Verzeichniss, 15=linux kleingeschrieben eintrag
uint8_t row; // reihe im sektor in der die datei infos stehen (reihe 0-15)
uint32_t firstCluster; // 20,2 /26,2 datei 1.cluster hi,low(möglicherweise der einzige) (4-byte)
uint32_t length; // 28,4 datei Länge (4-byte)
uint32_t lastCluster; // -nicht direkt aus dem dateisystem- letzter cluster der ersten kette
uint32_t seek; // schreib position in der datei
} file;
#endif

525
avr/usbload/file.c Normal file
View File

@@ -0,0 +1,525 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "mmc.h"
#include "fat.h"
#include "file.h"
#include "dir.h"
#include "config.h"
// *******************************************************************************************************************************
// 2 möglichkeiten beim öffnen, datei existiert(return 1) oder muss angelegt werden(return 2)
// zuerst wird geprüft ob es die datei im verzeichniss gibt. danach wird entschieden, ob die datei geöffnet wird oder angelegt.
// -beim offnen werden die bekannten cluster gesucht maximal MAX_CLUSTERS_IN_ROW in reihe. dann wird der 1. sektor der datei auf
// den puffer fat.sector geladen. jetzt kann man ffread lesen...
// -beim anlegen werden freie cluster gesucht, maximal MAX_CLUSTERS_IN_ROW in reihe. dann wird das struct file gefüllt.
// danach wird der dateieintrag gemacht(auf karte). dort wird auch geprüft ob genügend platz im aktuellen verzeichniss existiert.
// möglicherweise wird der 1. cluster der datei nochmal geändert. jetzt ist der erste frei sektor bekannt und es kann geschrieben werden.
//*******************************************************************************************************************************
unsigned char ffopen(char name[]){
unsigned char file_flag=fat_loadFileDataFromDir(name); //prüfung ob datei vorhanden und evetuelles laden des file struct
if( file_flag==0 ){ /** Datei existiert, anlegen nicht nötig! **/
fat_getFatChainClustersInRow( file.firstCluster ); // verkettete cluster aus der fat-chain suchen.
fat_loadSector( fat_clustToSec(file.firstCluster) ); // lät die ersten 512 bytes der datei auf puffer:sector.
file.lastCluster=fat_secToClust(fat.endSectors); // letzter bekannter cluster der datei
return 1;
}
#if (WRITE==1) // anlegen ist schreiben !
else{ /** Datei existiert nicht, also anlegen ! (nur wenn schreiben option an ist)**/
fat_getFreeClustersInRow(2); // leere cluster suchen, ab cluster 2.
strcpy((char*)file.name,(char*)name); // --- füllen des file struct, zum abschließenden schreiben.
file.firstCluster=fat_secToClust(fat.startSectors); // 1. cluster der datei
file.lastCluster=file.firstCluster;//fat_secToClust(fat.endSectors); // letzter bekannter cluster der datei
file.attrib=32; // --- file.row wird in der funktion fat_getFreeRowOfDir geschrieben !!
file.length=0; // damit da nix drin steht ^^
fat_makeFileEntry((char *)file.name,file.attrib,0); // DATEI ANLEGEN auf karte
fat.currentSectorNr=fat_clustToSec(file.firstCluster); // setzen des ersten sektors
return 2;
}
#endif
}
//*******************************************************************************************************************************
// schließt die datei operation ab. eigentlich nur nötig wenn geschrieben wurde. es gibt 2 möglichkeiten :
// 1. die datei wird geschlossen und es wurde über die alte datei länge hinaus geschrieben.
// 2. die datei wird geschlossen und man war innerhalb der datei größe, dann muss nur der aktuelle sektor geschrieben werden.
// der erste fall ist komplizierter, weil ermittelt werden muss wie viele sektoren neu beschrieben wurden um diese zu verketten
// und die neue datei länge muss ermitt weden. abschließend wird entweder (fall 2) nur der aktuelle sektor geschrieben, oder
// der aktuallisierte datei eintrag und die cluster (diese werden verkettet, siehe fileUpdate() ).
// *******************************************************************************************************************************
uint8_t ffclose(void)
{
#if (WRITE==1) /** 2 möglichkeiten beim schließen !! (lesend spielt keine rolle, nichts muss geupdatet werden) **/
if (file.length < (file.seek + file.cntOfBytes))
fileUpdate(); /** 1.) es wurde über die alte datei größe hinaus geschrieben **/
else if (fat.bufferDirty == 1)
fat_writeSector(fat.currentSectorNr); /** 2.) nicht über alte datei länge hinaus **/
#endif
file.cntOfBytes = 0; // init werte der nötigen zähler
file.seek = 0;
return (0);
}
// *******************************************************************************************************************************
// updatet datei eintrag auf der karte und verkettet die dazugehörigen fat cluster.
// füllt den aktuell beschriebenen sektor mit 0x00, da sonst die datei nicht richtig angezeigt wird.
// darf nur während schreibe operationen aufgerufen werden !
// *******************************************************************************************************************************
#if (WRITE==1)
void fileUpdate(void){
unsigned int comp_cntOfBytes=file.cntOfBytes; // sicher nötig wegen schleife...
while( comp_cntOfBytes < 512 ){ // sektor ist beschrieben worden, daher nötigenfalls mit 00 füllen
fat.sector[comp_cntOfBytes]=0x00; // beschreibt ungenutzte bytes mit 0x00
comp_cntOfBytes++;
}
char name[13]; // zum sichern des dateinamens
unsigned long int save_length = file.cntOfBytes + file.seek; // muss gesichert werden, wird sonst von der karte geladen und verändert !
strcpy(name,(char *)file.name); // muss gesichert werden, wird sonst von der karte geladen und verändert !
fat_setClusterChain(fat_secToClust(fat.startSectors),fat_secToClust(fat.currentSectorNr)); // verketten der geschriebenen cluster
fat_loadFileDataFromDir(name); // läd sektor, des datei eintrags, und läd daten von karte auf struct file!
fat_makeRowDataEntry(file.row,name,32,file.firstCluster,save_length); // macht eintrag im puffer
fat_writeSector(fat.currentSectorNr);
}
#endif
// *******************************************************************************************************************************
// offset byte wird übergeben. es wird durch die sektoren der datei gespult (gerechnet), bis der sektor mit dem offset byte erreicht
// ist, dann wird der sektor geladen und der zähler für die bytes eines sektors gesetzt. wenn das byte nicht in den sektoren ist,
// die "vorgesucht" wurden, müssen noch weitere sektoren der datei gesucht werden (sec > fat.endSectors).
// *******************************************************************************************************************************
void ffseek(unsigned long int offset){
#if (WRITE==1)
#if (OVER_WRITE==1) // man muss den dateieintrag updaten, um die daten zu retten !!
if( file.seek > file.length ) fileUpdate(); // fat verketten und datei update auf der karte !
#endif
#endif
fat_getFatChainClustersInRow(file.firstCluster); // suchen von anfang der cluster chain aus !
unsigned long int sec=fat.startSectors; // sektor variable zum durchgehen durch die sektoren
file.seek=0; // weil auch von anfang an der chain gesucht wird mit 0 initialisiert
while(offset>=512){ /** suchen des sektors in dem offset ist **/
sec++; // da byte nicht in diesem sektor ist, muss hochgezählt werden
offset-=512; // ein sektor weniger in dem das byte sein kann
file.seek+=512; // file.seek update, damit bei ffclose() die richtige file.length herauskommt
if ( sec > fat.endSectors ){ // es müssen mehr sektoren der datei gesucht werden
fat_getFatChainClustersInRow(fat_getNextCluster( file.lastCluster ) ); // nachladen von clustern in der chain
sec=fat.startSectors; // setzen des 1. sektors der neu geladenen, zum weitersuchen !
}
}
file.lastCluster=fat_secToClust(fat.endSectors); // letzter bekannter cluster der datei
fat_loadSector(sec); // sektor mit offset byte laden
file.cntOfBytes = offset; // setzen des lese zählers
}
#if (SMALL_FILE_SYSTEM==0)
// *******************************************************************************************************************************
// wechselt verzeichniss. start immer im root Dir.
// MUSS in das direktory gewechselt werden, in dem die datei zum lesen/schreiben ist !
// *******************************************************************************************************************************
uint8_t ffcd(char name[])
{
return (fat_cd(name));
}
// *******************************************************************************************************************************
// zeigt reihen eines clusters an, wird für ffls benötigt !
// es wird ab dem start sektor start_sec, der dazugehörige cluster angezeigt. geprüft wird ob es ein richtiger
// eintrag in der reihe ist (nicht gelöscht, nicht frei usw). die sektoren des clusters werden nachgeladen.
// die dateien werden mit namen und datei größe angezeigt.
// *******************************************************************************************************************************
void lsRowsOfClust(uint32_t start_sec)
{
uint8_t row; // reihen
uint8_t sec = 0; // sektoren
do {
fat_loadSector(start_sec + sec); // sektoren des clusters laden
for (row = 0; row < 16; row++) { // geht durch reihen des sektors
fat_loadRowOfSector(row); // reihe eines sektors (auf dem puffer) laden
if ((file.name[0] != 0xE5 && file.name[0] != 0x00)) {
if (file.attrib == 0x20)
printf("Name: %s Size:%li\n", file.name, file.length);
if (file.attrib == 0x10)
printf("Dir: %s\n", file.name);
}
}
} while (++sec < fat.secPerClust);
}
void ffls(void)
{
uint32_t clust; // cluster
uint16_t s; // fat16 root dir sektoren
if (fat.dir == 0 && fat.fatType == 16) { // IM ROOTDIR. fat16
for (s = 0; s < (uint16_t) (fat.dataDirSec + 2 - fat.rootDir); s++) { // zählt durch RootDir sektoren (errechnet anzahl
lsRowsOfClust(fat.rootDir + s); // zeigt reihen eines root dir clust an
}
printf("Fat16\n");
} else {
if (fat.dir == 0 && fat.fatType == 32)
clust = fat.rootDir; // IM ROOTDIR. fat32
else
clust = fat.dir; // NICHT ROOT DIR
while (!((clust == 0xfffffff && fat.fatType == 32) || (clust == 0xffff && fat.fatType == 16))) { // prüft ob weitere
lsRowsOfClust(fat_clustToSec(clust)); // zeigt reihen des clusters an
clust = fat_getNextCluster(clust); // liest nächsten cluster des dir-eintrags
}
printf("Fat32\n");
}
}
void lsRowsOfClust_smc(uint32_t start_sec)
{
uint8_t row; // reihen
uint8_t sec = 0; // sektoren
do {
fat_loadSector(start_sec + sec); // sektoren des clusters laden
for (row = 0; row < 16; row++) { // geht durch reihen des sektors
fat_loadRowOfSector(row); // reihe eines sektors (auf dem puffer) laden
if ((file.name[0] != 0xE5 && file.name[0] != 0x00)) {
if (file.attrib == 0x20)
dir_entry_add(file.firstCluster, file.name, file.length ,file.attrib);
}
}
} while (++sec < fat.secPerClust);
}
void ffls_smc(void)
{
uint32_t clust; // cluster
uint16_t s; // fat16 root dir sektoren
if (fat.dir == 0 && fat.fatType == 16) { // IM ROOTDIR. fat16
for (s = 0; s < (uint16_t) (fat.dataDirSec + 2 - fat.rootDir); s++) { // zählt durch RootDir sektoren (errechnet anzahl
lsRowsOfClust_smc(fat.rootDir + s); // zeigt reihen eines root dir clust an
}
printf("Fat16\n");
} else {
if (fat.dir == 0 && fat.fatType == 32)
clust = fat.rootDir; // IM ROOTDIR. fat32
else
clust = fat.dir; // NICHT ROOT DIR
while (!((clust == 0xfffffff && fat.fatType == 32) || (clust == 0xffff && fat.fatType == 16))) { // prüft ob weitere
lsRowsOfClust_smc(fat_clustToSec(clust)); // zeigt reihen des clusters an
clust = fat_getNextCluster(clust); // liest nächsten cluster des dir-eintrags
}
printf("Fat32\n");
}
}
// *******************************************************************************************************************************
// wechselt in das parent verzeichniss (ein verzeichniss zurück !)
// die variable fat.dir enthält den start cluster des direktory in dem man sich grade befindet, anhand diesem,
// kann der "." bzw ".." eintrag im ersten sektor des direktory ausgelesen und das parent direktory bestimmt werden.
// *******************************************************************************************************************************
uint8_t ffcdLower(void)
{
if (fat.dir == 0)
return (1); // im root dir, man kann nicht höher !
fat_loadSector(fat_clustToSec(fat.dir)); // läd 1. sektor des aktuellen direktory.
fat_loadRowOfSector(1); // ".." eintrag (parent dir) ist 0 wenn parent == root
fat.dir = file.firstCluster; // dir setzen
return (0);
}
#ifndef __AVR_ATmega8__
// *******************************************************************************************************************************
// erstellt einen dir eintrag im aktuellen verzeichniss.
// prüft ob es den den dir-namen schon gibt, dann wird nichts angelegt.
// wenn ok, dann wird ein freier cluster gesucht, als ende markiert, der eintrag ins dir geschrieben.
// dann wird der cluster des dirs aufbereitet. der erste sektor des clusters enthält den "." und ".." eintrag.
// der "." hat den 1. cluster des eigenen dirs. der ".." eintrag ist der 1. cluster des parent dirs.
// ein dir wird immer mit 0x00 initialisiert ! also alle einträge der sektoren des clusters ( bis auf . und .. einträge)!
// *******************************************************************************************************************************
#if (WRITE==1)
void ffmkdir(char name[]){
unsigned char i;
unsigned int j;
if(0==fat_loadFileDataFromDir(name))return ; // prüft ob dirname im dir schon vorhanden, wenn ja, abbruch !
// cluster in fat setzen, und ordner eintrg im aktuellen verzeichniss machen.
fat_getFreeClustersInRow(2); // holt neue freie cluster, ab cluster 2 ...
fat_setCluster(fat_secToClust(fat.startSectors),0x0fffffff); // fat16/32 cluster chain ende setzen. (neuer ordner in fat)
file.firstCluster=fat_secToClust(fat.startSectors); // dammit fat_makeFileEntry den cluster richtig setzen kann
fat_makeFileEntry(name,0x10,0); // macht dir eintrag im aktuellen verzeichniss (legt ordner im partent verzeichniss an)
// aufbereiten des puffers
j=511;
do{
fat.sector[j]=0x00; //schreibt puffer fat.sector voll mit 0x00==leer
}while(j--);
// aufbereiten des clusters
for(i=1;i<fat.secPerClust;i++){ // ein dir cluster muss mit 0x00 initialisiert werden !
fat_writeSector(fat.startSectors+i); // löschen des cluster (überschreibt mit 0x00), wichtig bei ffls!
}
// aufbereiten des neuen dir sektors mit "." und ".." eintraegen !
fat_makeRowDataEntry(0,". ",0x10,file.firstCluster,0); // macht "." eintrag des dirs
fat_makeRowDataEntry(1,".. ",0x10,fat.dir,0); // macht ".." eintrag des dirs
fat_writeSector(fat_clustToSec(file.firstCluster)); // schreibt einträge auf karte !
}
#endif //WRITE
#endif // ffmkdir wegen atmega8
#endif
#if (WRITE==1)
// *******************************************************************************************************************************
// löscht datei/ordner aus aktuellem verzeichniss, wenn es die datei gibt.
// löscht dateien und ordner rekursiv !
// *******************************************************************************************************************************
uint8_t ffrm(char name[])
{
if (0 == fat_loadFileDataFromDir(name)) { // datei oder ordner ist vorhanden, nur dann lösch operation
if (file.attrib != 0x10) { // ist datei.
fat.sector[file.row << 5] = 0xE5; // datei gelöscht markieren (file.row*32, damit man auf reihen anfang kommt)
if ((file.row - 1) >= 0) { // gibt es einen eintrag davor ?
if (fat.sector[(file.row << 5) - 21] == 0x0f)
fat.sector[(file.row << 5) - 32] = 0xE5; // langer datei eintag auch gelöscht.
}
fat.bufferDirty = 1; // eintrag in puffer gemacht.
if (0 == fat_getNextCluster(file.firstCluster))
return (0); // 1.cluster ist leer ?!?
fat_delClusterChain(file.firstCluster); // löscht die zu der datei gehörige cluster-chain aus der fat.
return (0);
}
// TODO noch nicht optimal. zu viele schreib vorgänge beim löschen von datei einträgen. max bis zu 16/sektor !
else { // ist ordner, dann rekursiv löschen !!
#ifndef __AVR_ATmega8__ // mega8 zu klein für die funktionalität....
uint32_t parent;
uint32_t own;
uint32_t clustsOfDir; // um durch die cluster chain eines dirs zu gehen.
uint8_t cntSecOfClust = 0;
uint8_t i = 0;
fat.sector[file.row << 5] = 0xE5; // löscht dir eintrag
if ((file.row - 1) >= 0) { // gibt es einen eintrag davor (langer datei eintrag)?
if (fat.sector[(file.row << 5) - 21] == 0x0f)
fat.sector[(file.row << 5) - 32] = 0xE5; // langer datei eintag auch gelöscht
}
fat.bufferDirty = 1; // puffer eintrag gemacht
parent = fat.dir; // der ordner in dem der zu löschende ordner ist.
own = file.firstCluster; // der 1. cluster des ordners der zu löschen ist.
clustsOfDir = file.firstCluster; // die "cluster" des zu löschenden ordners
do { // geht durch cluster des dirs
fat_loadSector(fat_clustToSec(clustsOfDir)); // sektor des dirs laden
do { // geht durch sektoren des clusters
do { // geht durch reihen des sektors
fat_loadRowOfSector(i);
if (file.attrib != 0x10 && file.attrib != 0x00 && file.name[0] != 0xE5) { // ist kein ordner,noch nicht
// gelöscht, kein freier eintrag
fat.sector[i << 5] = 0xE5; // erster eintrag der reihe als gelöscht markiert
fat.bufferDirty = 1; // puffer eintrag gemacht
if (file.attrib == 0x20) { // ist datei!
fat_delClusterChain(file.firstCluster); // ist datei, dann cluster-chain der datei löschen
fat_loadSector(fat_clustToSec(clustsOfDir) + cntSecOfClust); // sektor neu laden, weil löschen der
// chain, den puffer nutzt.
}
}
if (file.attrib == 0x10 && file.name[0] == '.') { // "." oder ".." eintrag erkannt, löschen !
fat.sector[i << 5] = 0xE5; // eintrag als gelöscht markiert
fat.bufferDirty = 1; // puffer eintrag gemacht
}
if (file.attrib == 0x10 && file.name[0] != '.' && file.name[0] != 0xE5 && file.name[0] != 0) { // ordner erkannt !
fat.sector[i << 5] = 0xE5; // dir eintrag als gelöscht markiert
fat.bufferDirty = 1; // puffer eintrag gemacht
fat_loadSector(fat_clustToSec(file.firstCluster)); // sektor des dirs laden
clustsOfDir = file.firstCluster; // eigenes dir ist file.firstCluster
own = file.firstCluster; // eigener start cluster/dir
fat_loadRowOfSector(1); // ".." laden um parent zu bestimmen
parent = file.firstCluster; // parent sichern.
cntSecOfClust = 0; // init von gelesenen sektoren und reihen !
i = 0;
continue;
}
if (file.name[0] == 0x00) { // ende des dirs erreicht, wenn nicht voll !!
if (parent == fat.dir) { // erfolgreich alles gelöscht
fat_delClusterChain(own); // cluster chain des ordners löschen
return (0);
}
fat_delClusterChain(own); // cluster chain des ordners löschen
clustsOfDir = parent; // parent ist jetzt wieder arbeisverzeichniss.
own = parent; // arbeitsverzeichniss setzten
fat_loadSector(fat_clustToSec(own)); // sektor des dirs laden
fat_loadRowOfSector(1); // ".." laden um parent zu bestimmen
parent = file.firstCluster; // parent sichern.
cntSecOfClust = 0; // init von gelesenen sektoren und reihen !
i = 0;
continue;
}
i++;
} while (i < 16); // geht durch reihen des sektors.
i = 0; // neuer sektor -> reihen von vorne.
cntSecOfClust++;
fat_loadSector(fat_clustToSec(clustsOfDir) + cntSecOfClust); // läd sektoren des clusters nach
} while (cntSecOfClust < fat.secPerClust); // geht durch sektoren des clusters.
cntSecOfClust = 0; // neuer cluster -> sektoren von vorne.
clustsOfDir = fat_getNextCluster(clustsOfDir); // sucht neuen cluster der cluster-chain.
} while (!((clustsOfDir == 0xfffffff && fat.fatType == 32) || (clustsOfDir == 0xffff && fat.fatType == 16))); // geht
// durch
// cluster
// des
// dirs.
fat_delClusterChain(own); // hier landet man, wenn der ordner voll war (auf cluster "ebene")!!
#endif
}
}
return (1); // fehler, nicht gefunden?
}
#endif
// *******************************************************************************************************************************
// liest 512 bytes aus dem puffer fat.sector. dann werden neue 512 bytes der datei geladen, sind nicht genügend verkettete
// sektoren in einer reihe bekannt, wird in der fat nachgeschaut. dann werden weiter bekannte nachgeladen...
// *******************************************************************************************************************************
inline uint8_t ffread(void)
{
if (file.cntOfBytes == 512) { /** EINEN SEKTOR GLESEN (ab hier 2 möglichkeiten !) **/
file.cntOfBytes = 0; // byte zähler zurück setzen
if (fat.currentSectorNr == fat.endSectors) { /** 1.) nötig mehr sektoren der chain zu laden (mit ein bisschen glück nur alle 512*MAX_CLUSTERS_IN_ROW bytes)**/
fat_getFatChainClustersInRow(fat_getNextCluster(fat_secToClust(fat.endSectors))); // nachladen von clustern in der chain
fat.currentSectorNr = fat.startSectors - 1; // setzen des nächsten sektors um weiter lesen zu können..
}
fat_loadSector(fat.currentSectorNr + 1); /** 2.) die bekannten in einer reihe reichen noch.(nur alle 512 bytes)**/
}
return fat.sector[file.cntOfBytes++]; // rückgabe, byte des sektors (NACH rückgabe erhöhen von zähler ! )
}
#if (WRITE==1)
#if (OVER_WRITE==0) // nicht überschreibende write funktion
// *******************************************************************************************************************************
// schreibt 512 byte blöcke auf den puffer fat.sector. dann wird dieser auf die karte geschrieben. wenn genügend feie
// sektoren zum beschreiben bekannt sind(datenmenge zu groß), muss nicht in der fat nachgeschaut werden. sollten nicht genügend
// zusammenhängende sektoren bekannt sein, werden die alten verkettet und neue gesucht. es ist nötig sich den letzten bekannten
// einer kette zu merken -> file.lastCluster, um auch nicht zusammenhängende cluster verketten zu können (fat_setClusterChain macht das)!
// *******************************************************************************************************************************
inline void ffwrite(uint8_t c)
{
fat.sector[file.cntOfBytes++] = c; // schreiben des chars auf den puffer sector und zähler erhöhen (pre-increment)
fat.bufferDirty = 1; // puffer dirty weil geschrieben und noch nicht auf karte.
if (file.cntOfBytes == 512) { /** SEKTOR VOLL ( 2 möglichkeiten ab hier !) **/
file.cntOfBytes = 0; // rücksetzen des sektor byte zählers
mmc_write_sector(fat.currentSectorNr, fat.sector); /** 1.) vollen sektor auf karte schreiben **/
fat.bufferDirty = 0; // puffer jetzt clear, weil grade alles geschrieben.
file.seek += 512; // position in der datei erhöhen, weil grade 512 bytes geschrieben
if (fat.currentSectorNr == fat.endSectors) { /** 2.) es ist nötig, neue freie zu suchen und die alten zu verketten (mit ein bischen glück nur alle 512*MAX_CLUSTERS_IN_ROW bytes) **/
fat_setClusterChain(fat_secToClust(fat.startSectors), fat_secToClust(fat.endSectors)); // verketten der beschriebenen
fat_getFreeClustersInRow(file.lastCluster); // suchen von leeren sektoren.
fat.currentSectorNr = fat.startSectors - 1; // setzen des 1. sektors der neuen reihe zum schreiben.
}
fat.currentSectorNr++; // nächsten sektor zum beschreiben.
}
}
#endif
#if (OVER_WRITE==1) // überschreibende write funktion, nicht performant, weil immer auch noch ein sektor geladen werden muss
// *******************************************************************************************************************************
// schreibt 512 byte blöcke auf den puffer fat.sector. dann wird dieser auf die karte geschrieben. wenn genügend feie
// sektoren zum beschreiben bekannt sind, muss nicht in der fat nachgeschaut werden. sollten nicht genügend zusammenhängende
// sektoren bekannt sein(datenmenge zu groß), werden die alten verkettet und neue gesucht. es ist nötig sich den letzten bekannten einer
// kette zu merken -> file.lastCluster, um auch nicht zusammenhängende cluster verketten zu können (fat_setClusterChain macht das)!
// es ist beim überschreiben nötig, die schon beschriebenen sektoren der datei zu laden, damit man die richtigen daten
// hat. das ist blöd, weil so ein daten overhead von 50% entsteht. da lesen aber schneller als schreiben geht, verliert man nicht 50% an
// geschwindigkeit.
// *******************************************************************************************************************************
inline void ffwrite(uint8_t c)
{
fat.sector[file.cntOfBytes++] = c; // schreiben des chars auf den puffer sector und zähler erhöhen (pre-increment)
fat.bufferDirty = 1; // puffer dirty weil geschrieben und noch nicht auf karte.
if (file.cntOfBytes == 512) { /** SEKTOR VOLL ( 2 möglichkeiten ab hier !) **/
file.cntOfBytes = 0; // rücksetzen des sektor byte zählers.
mmc_write_sector(fat.currentSectorNr, fat.sector); /** 1.) vollen sektor auf karte schreiben**/
fat.bufferDirty = 0; // puffer jetzt clear, weil grade alles geschrieben.
file.seek += 512; // position in der datei erhöhen, weil grade 512 bytes geschrieben.
if (fat.currentSectorNr == fat.endSectors) { /** 2.) es ist nötig, neue freie zu suchen und die alten zu verketten (mit ein bischen glück nur alle 512*MAX_CLUSTERS_IN_ROW bytes) **/
if (file.seek > file.length) { // außerhalb der datei !!
fat_setClusterChain(fat_secToClust(fat.startSectors), fat_secToClust(fat.endSectors)); // verketten der beschriebenen.
fat_getFreeClustersInRow(file.lastCluster); // neue leere sektoren benötigt, also suchen.
} else {
fat_getFatChainClustersInRow(fat_getNextCluster(file.lastCluster)); // noch innerhalb der datei, deshlab verkettete
// suchen.
}
fat.currentSectorNr = fat.startSectors - 1; // setzen des 1. sektors der neuen reihe zum schreiben.
}
fat.currentSectorNr++; // nächsten sektor zum beschreiben.
mmc_read_sector(fat.currentSectorNr, fat.sector); // wegen überschreiben, muss der zu beschreibende sektor geladen werden...
}
}
#endif
// *******************************************************************************************************************************
// schreibt string auf karte, siehe ffwrite()
// *******************************************************************************************************************************
inline void ffwrites(const char *s)
{
while (*s)
ffwrite(*s++);
}
#endif

33
avr/usbload/file.h Normal file
View File

@@ -0,0 +1,33 @@
#ifndef _FILE_H
#define _FILE_H
// **************************************************************************************************************************
// funktionen
extern inline uint8_t ffread(void); // liest byte-weise aus der datei (puffert immer 512 bytes zwischen)
extern inline void ffwrite(uint8_t c); // schreibt ein byte in die geöffnete datei
extern inline void ffwrites(const char *s); // schreibt string auf karte
extern uint8_t ffopen(char name[]); // kann immer nur 1 datei bearbeiten.
extern uint8_t ffclose(void); // muss aufgerufen werden bevor neue datei bearbeitet wird.
extern void ffseek(uint32_t offset); // setzt zeiger:bytesOfSec auf position in der geöffneten datei.
extern uint8_t ffcd(char name[]); // wechselt direktory
extern void ffls(void); // zeigt direktory inhalt an
extern void ffls_smc(void); // zeigt direktory inhalt an
extern uint8_t ffcdLower(void); // geht ein direktory zurück, also cd.. (parent direktory)
extern uint8_t ffrm(char name[]); // löscht datei aus aktuellem verzeichniss.
extern void ffmkdir(char name[]); // legt ordner in aktuellem verzeichniss an.
void lsRowsOfClust(uint32_t start_sec); // zeigt reihen eines clusters an, ab start_sec
void fileUpdate(void); // updatet datei eintrag auf karte
// **************************************************************************************************************************//
// #######################################################################################################################
#endif

12
avr/usbload/hardware.h Executable file
View File

@@ -0,0 +1,12 @@
#ifndef _HARDWARE_H
/*
hier sind die beiden hardware abhängigen bibliotheken zu includen !
welchen umfang diese haben müssen (an funktionen), muss man in den bibliotheken nachsehen.
*/
#define _HARDWARE_H
#include "uart.h"
#include "mmc.h"
#endif

View File

@@ -1,267 +0,0 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
*
* =====================================================================================
*/
#include "huffman-decode.h"
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "info.h"
#include "debug.h"
#ifdef DEBUG
#undef DEBUG
#endif
#define DEBUG 1
#if DEBUG
#include <avr/pgmspace.h>
#endif
#define V_NODE (-2)
#define V_EOF (-1)
#define PREFIX_SIZE_B 32
#define ALLOC_ERROR {}
#undef BLOCK_ALLOC
typedef struct {
int16_t value;
void* left;
void* right;
} node_t;
#if HUFFMAN_USE_ADDR_16
void huffman_dec_init(huffman_dec_ctx_t* ctx, uint16_t(*rb_func)(uint16_t)){
#else
void huffman_dec_init(huffman_dec_ctx_t* ctx, uint16_t(*rb_func)(uint32_t)){
#endif
ctx->tree = NULL;
ctx->addr = 0;
ctx->read_byte = rb_func;
ctx->rbuffer_index = 8;
}
#if HUFFMAN_USE_ADDR_16
void huffman_dec_set_addr(huffman_dec_ctx_t* ctx, uint16_t addr){
#else
void huffman_dec_set_addr(huffman_dec_ctx_t* ctx, uint32_t addr){
#endif
ctx->addr = addr;
}
static inline void prefix_increment(uint8_t* prefix){
uint8_t i;
for(i=0; i<PREFIX_SIZE_B; ++i){
prefix[i] += 1;
if(prefix[i]!=0)
return;
}
}
static inline void prefix_shiftleft(uint8_t* prefix){
uint8_t i;
uint8_t c[2]={0,0};
uint8_t ci=0;
for(i=0; i<PREFIX_SIZE_B; ++i){
c[ci] = (prefix[i])>>7;
prefix[i]<<=1;
ci ^= 1;
prefix[i]|=c[ci];
}
}
static inline void set_last_to_eof(node_t* start){
node_t* current = start;
while(current->value==V_NODE){
current=current->right;
}
current->value=V_EOF;
}
#if DEBUG
void print_tree(node_t* node){
if(node->value==V_NODE){
info("\n%p --> node->left=%p node->right=%p",node,node->left, node->right);
print_tree(node->left);
print_tree(node->right);
}else{
info("\n%p => %i",node,node->value);
}
}
#endif
uint8_t build_tree(huffman_dec_ctx_t* ctx){
uint16_t treesize;
uint16_t treeindex=1;
int8_t i,t;
if(ctx->read_byte(ctx->addr++)!=0xC0)
return 1;
if(((treesize=ctx->read_byte(ctx->addr++))&0xFE)!=0xDE)
return 1;
treesize = (treesize&1)<<8;
treesize += ctx->read_byte(ctx->addr++);
if(treesize>0x1ff)
return 2;
#if BLOCK_ALLOC
ctx->tree = malloc((2*treesize-1) * sizeof(node_t));
#else
ctx->tree = malloc(sizeof(node_t));
#endif
((node_t*)(ctx->tree))->value = V_NODE;
uint16_t depth=0;
uint16_t count=0;
uint16_t v;
uint8_t prefix[PREFIX_SIZE_B];
uint8_t cdepth=0;
node_t* current=ctx->tree;
current->value = V_NODE;
memset(prefix, 0, PREFIX_SIZE_B);
do{
while(count==0){
depth++;
count= ctx->read_byte(ctx->addr++);
if(count==255)
count += ctx->read_byte(ctx->addr++);
}
v = ctx->read_byte(ctx->addr++);
if(v>0xff)
return 3;
--count;
for(;cdepth<depth;++cdepth){
prefix_shiftleft(prefix);
}
#if DEBUG
printf("\n value %x => ",v);
#endif
current=ctx->tree;
for(i=depth-1; i>=0; --i){
t=(prefix[i/8])&(1<<(i%8));
if(t==0){
#if DEBUG
printf("0");
#endif
if(current->left==NULL){
#if BLOCK_ALLOC
current->left=&(((node_t*)(ctx->tree))[treeindex++]);
#else
current->left=malloc(sizeof(node_t));
#endif
((node_t*)(current->left))->value = V_NODE;
}
current = current->left;
} else {
#if DEBUG
printf("1");
#endif
if(current->right==NULL){
#if BLOCK_ALLOC
current->right=&(((node_t*)(ctx->tree))[treeindex++]);
#else
current->right=malloc( sizeof(node_t));
#endif
((node_t*)(current->right))->value=V_NODE;
}
current = current->right;
}
}
#if !BLOCK_ALLOC
if(current==NULL)
ALLOC_ERROR
#endif
current->value=v;
prefix_increment(prefix);
}while(!(prefix[depth/8]&(1<<(depth%8))));
#if DEBUG
print_tree(ctx->tree);
#endif
set_last_to_eof(ctx->tree);
return 0;
}
void free_tree(node_t* node){
#if !BLOCK_ALLOC
if(node->value==V_NODE){
free_tree(node->left);
free_tree(node->right);
}
#endif
free(node);
}
static uint8_t read_bit(huffman_dec_ctx_t* ctx){
uint16_t x;
uint8_t t;
if(ctx->rbuffer_index==8){
x=ctx->read_byte(ctx->addr);
ctx->addr++;
if(t>0xff)
return 0xFF;
ctx->rbuffer = (uint8_t)x;
ctx->rbuffer_index=0;
}
t=(ctx->rbuffer)>>7;
ctx->rbuffer<<=1;
ctx->rbuffer_index++;
return t;
}
uint16_t huffman_dec_byte(huffman_dec_ctx_t* ctx){
node_t* current=ctx->tree;
uint8_t t;
if(current==NULL){
#if DEBUG
printf("\nbuild tree");
#endif
t=build_tree(ctx);
if(t!=0){
#if DEBUG
printf("\n!!! building tree failed !!!\r\n");
#endif
return 0xFFFF;
}
#if DEBUG
printf("\ntree build successful");
#endif
current=ctx->tree;
}
while(current->value==V_NODE){
t=read_bit(ctx);
if(t==0xFF)
goto eof_detected;
if(t==0){
current=current->left;
} else {
current=current->right;
}
}
if(current->value!=V_EOF){
return current->value;
}
eof_detected:
free_tree(ctx->tree);
ctx->tree = NULL;
return 0xFFFF;
}

File diff suppressed because it is too large Load Diff

View File

@@ -2,8 +2,8 @@
#ifndef __FIFO_H__
#define __FIFO_H__
#define ROM_BUFFER_SIZE 27288
#define ROM_HUFFMAN_SIZE 27288
#define ROM_RLE_SIZE 30344
#define ROM_BUFFER_SIZE 31091
#define ROM_HUFFMAN_SIZE 0
#define ROM_RLE_SIZE 31091
#endif

View File

@@ -21,17 +21,16 @@
#include <avr/io.h>
#include <avr/interrupt.h> /* for sei() */
#include <util/delay.h> /* for _delay_ms() */
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdlib.h>
#include <avr/pgmspace.h> /* required by usbdrv.h */
#include <avr/eeprom.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include "usbdrv.h"
#include "oddebug.h" /* This is also an example for using debug
* macros */
#include "oddebug.h"
#include "config.h"
#include "requests.h" /* The custom request numbers we use */
#include "requests.h"
#include "uart.h"
#include "sram.h"
#include "debug.h"
@@ -41,16 +40,18 @@
#include "usb_bulk.h"
#include "timer.h"
#include "watchdog.h"
#include "huffman-decode.h"
#include "rle.h"
#include "loader.h"
#include "command.h"
#include "shared_memory.h"
#include "testing.h"
extern const char _rom[] PROGMEM;
extern FILE uart_stdout;
uint8_t debug_level = ( DEBUG | DEBUG_USB | DEBUG_CRC );
uint8_t debug_level = (DEBUG | DEBUG_USB | DEBUG_CRC | DEBUG_FAT);
uint8_t read_buffer[TRANSFER_BUFFER_SIZE];
uint32_t req_addr = 0;
@@ -59,6 +60,8 @@ uint32_t req_size;
uint8_t req_bank;
uint32_t req_bank_size;
uint16_t req_bank_cnt;
uint8_t req_percent;
uint8_t req_percent_last;
uint8_t req_state = REQ_STATUS_IDLE;
uint8_t rx_remaining = 0;
uint8_t tx_remaining = 0;
@@ -76,90 +79,30 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
usbRequest_t *rq = (void *) data;
uint8_t ret_len = 0;
/*
* -------------------------------------------------------------------------
*/
if (rq->bRequest == USB_UPLOAD_INIT) {
if (req_state != REQ_STATUS_IDLE){
debug(DEBUG_USB,"USB_UPLOAD_INIT: ERROR state is not REQ_STATUS_IDLE\n");
return 0;
}
if (rq->bRequest == USB_BULK_UPLOAD_INIT) {
req_bank = 0;
rx_remaining = 0;
req_bank_size = (uint32_t)1 << rq->wValue.word;
sync_errors = 0;
crc = 0;
debug(DEBUG_USB,"USB_UPLOAD_INIT: bank_size=0x%08lx\n", req_bank_size);
/*
* -------------------------------------------------------------------------
*/
} else if (rq->bRequest == USB_UPLOAD_ADDR) {
req_state = REQ_STATUS_UPLOAD;
req_addr = rq->wValue.word;
req_addr = req_addr << 16;
req_addr = req_addr | rq->wIndex.word;
if (rx_remaining) {
sync_errors++;
debug
(DEBUG_USB,"USB_UPLOAD_ADDR: Out of sync addr=0x%lx remain=%i packet=%i sync_error=%i\n",
req_addr, rx_remaining, rq->wLength.word, sync_errors);
ret_len = 0;
}
rx_remaining = rq->wLength.word;
ret_len = USB_MAX_TRANS;
if (req_addr && (req_addr % 0x1000) == 0) {
debug(DEBUG_USB,"USB_UPLOAD_ADDR: bank=0x%02x addr=0x%08lx crc=%04x\n",
req_bank, req_addr,crc_check_bulk_memory(req_addr - 0x1000,req_addr,req_bank_size));
}
if (req_addr && req_addr % req_bank_size == 0) {
debug(DEBUG_USB,"USB_UPLOAD_ADDR: req_bank=0x%02x addr=0x%08lx\n",
req_bank, req_addr);
req_bank++;
//shared_memory_put(SHARED_MEM_CMD_UPLOAD_PROGESS,req_bank);
}
ret_len = USB_MAX_TRANS;
/*
* -------------------------------------------------------------------------
*/
} else if (rq->bRequest == USB_DOWNLOAD_INIT) {
debug(DEBUG_USB,"USB_DOWNLOAD_INIT\n");
/*
* -------------------------------------------------------------------------
*/
} else if (rq->bRequest == USB_DOWNLOAD_ADDR) {
debug(DEBUG_USB,"USB_DOWNLOAD_ADDR\n");
/*
* -------------------------------------------------------------------------
*/
} else if (rq->bRequest == USB_BULK_UPLOAD_INIT) {
req_bank = 0;
rx_remaining = 0;
debug(DEBUG_USB,"USB_BULK_UPLOAD_INIT: %i %i\n",rq->wValue.word, rq->wIndex.word);
req_bank_size = (uint32_t)(1L << rq->wValue.word);
debug(DEBUG_USB, "USB_BULK_UPLOAD_INIT: %i %i\n", rq->wValue.word,
rq->wIndex.word);
req_bank_size = (uint32_t) (1L << rq->wValue.word);
req_bank_cnt = rq->wIndex.word;
req_addr_end = (uint32_t)req_bank_size * req_bank_cnt;
req_addr_end = (uint32_t) req_bank_size *req_bank_cnt;
req_percent = 0;
req_percent_last = 0;
sync_errors = 0;
debug(DEBUG_USB,"USB_BULK_UPLOAD_INIT: bank_size=0x%08lx bank_cnt=0x%x end_addr=0x%08lx\n",
req_bank_size, req_bank_cnt, req_addr_end);
shared_memory_put(SHARED_MEM_CMD_BANK_COUNT,req_bank_cnt);
if (req_addr == 0x000000){
debug(DEBUG_USB,
"USB_BULK_UPLOAD_INIT: bank_size=0x%08lx bank_cnt=0x%x end_addr=0x%08lx\n",
req_bank_size, req_bank_cnt, req_addr_end);
shared_memory_write(SHARED_MEM_TX_CMD_BANK_COUNT, req_bank_cnt);
if (req_addr == 0x000000) {
timer_start();
}
/*
* -------------------------------------------------------------------------
*/
/*
* -------------------------------------------------------------------------
*/
} else if (rq->bRequest == USB_BULK_UPLOAD_ADDR) {
req_state = REQ_STATUS_BULK_UPLOAD;
@@ -167,28 +110,31 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
req_addr = req_addr << 16;
req_addr = req_addr | rq->wIndex.word;
rx_remaining = rq->wLength.word;
if (req_addr && req_addr % req_bank_size == 0) {
#ifdef FLT_DEBUG
debug(DEBUG_USB,"USB_BULK_UPLOAD_ADDR: req_bank=0x%02x addr=0x%08lx time=%.4f\n",
req_bank, req_addr,timer_stop());
#else
debug(DEBUG_USB,"USB_BULK_UPLOAD_ADDR: req_bank=0x%02x addr=0x%08lx time=%i\n",
req_bank, req_addr,timer_stop_int());
#endif
#ifdef FLT_DEBUG
debug(DEBUG_USB,
"USB_BULK_UPLOAD_ADDR: req_bank=0x%02x addr=0x%08lx time=%.4f\n",
req_bank, req_addr, timer_stop());
#else
debug(DEBUG_USB,
"USB_BULK_UPLOAD_ADDR: req_bank=0x%02x addr=0x%08lx time=%i\n",
req_bank, req_addr, timer_stop_int());
#endif
req_bank++;
shared_memory_put(SHARED_MEM_CMD_UPLOAD_PROGESS,req_bank);
shared_memory_write(SHARED_MEM_TX_CMD_UPLOAD_PROGESS, req_bank);
sram_bulk_write_start(req_addr);
timer_start();
} else {
sram_bulk_write_start(req_addr);
}
ret_len = USB_MAX_TRANS;
/*
* -------------------------------------------------------------------------
*/
/*
* -------------------------------------------------------------------------
*/
} else if (rq->bRequest == USB_BULK_UPLOAD_NEXT) {
req_state = REQ_STATUS_BULK_UPLOAD;
@@ -196,89 +142,106 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
req_addr = req_addr << 16;
req_addr = req_addr | rq->wIndex.word;
rx_remaining = rq->wLength.word;
req_percent = (uint32_t)( 100 * req_addr ) / req_addr_end;
if (req_percent!=req_percent_last){
//debug(DEBUG_USB,
// "USB_BULK_UPLOAD_ADDR: precent=%i\n", req_percent);
shared_memory_write(SHARED_MEM_TX_CMD_UPLOAD_PROGESS, req_percent);
sram_bulk_write_start(req_addr);
}
req_percent_last = req_percent;
#if 0
if (req_addr && (req_addr % 0x1000) == 0) {
debug(DEBUG_USB,"USB_BULK_UPLOAD_NEXT: bank=0x%02x addr=0x%08lx crc=%04x\n",
req_bank, req_addr,crc_check_bulk_memory(req_addr - 0x1000,req_addr,req_bank_size));
debug(DEBUG_USB,
"USB_BULK_UPLOAD_NEXT: bank=0x%02x addr=0x%08lx crc=%04x\n",
req_bank, req_addr, crc_check_bulk_memory(req_addr - 0x1000,
req_addr,
req_bank_size));
}
sram_bulk_write_start(req_addr);
#endif
if (req_addr && ( req_addr % req_bank_size) == 0) {
#ifdef FLT_DEBUG
debug(DEBUG_USB,"USB_BULK_UPLOAD_NEXT: req_bank=0x%02x addr=0x%08lx time=%.4f\n",
req_bank, req_addr,timer_stop());
#else
debug(DEBUG_USB,"USB_BULK_UPLOAD_NEXT: req_bank=0x%02x addr=0x%08lx time=%i\n",
req_bank, req_addr,timer_stop_int());
#endif
if (req_addr && (req_addr % req_bank_size) == 0) {
#ifdef FLT_DEBUG
debug(DEBUG_USB,
"USB_BULK_UPLOAD_NEXT: req_bank=0x%02x addr=0x%08lx time=%.4f\n",
req_bank, req_addr, timer_stop());
#else
debug(DEBUG_USB,
"USB_BULK_UPLOAD_NEXT: req_bank=0x%02x addr=0x%08lx time=%i\n",
req_bank, req_addr, timer_stop_int());
#endif
req_bank++;
timer_start();
shared_memory_put(SHARED_MEM_CMD_BANK_CURRENT,req_bank);
shared_memory_write(SHARED_MEM_TX_CMD_BANK_CURRENT, req_bank);
sram_bulk_write_start(req_addr);
}
ret_len = USB_MAX_TRANS;
/*
* -------------------------------------------------------------------------
*/
/*
* -------------------------------------------------------------------------
*/
} else if (rq->bRequest == USB_BULK_UPLOAD_END) {
if (req_state != REQ_STATUS_BULK_UPLOAD){
debug(DEBUG_USB,"USB_BULK_UPLOAD_END: ERROR state is not REQ_STATUS_BULK_UPLOAD\n");
if (req_state != REQ_STATUS_BULK_UPLOAD) {
debug(DEBUG_USB,
"USB_BULK_UPLOAD_END: ERROR state is not REQ_STATUS_BULK_UPLOAD\n");
return 0;
}
debug(DEBUG_USB,"USB_BULK_UPLOAD_END:\n");
debug(DEBUG_USB, "USB_BULK_UPLOAD_END:\n");
req_state = REQ_STATUS_IDLE;
sram_bulk_write_end();
shared_memory_put(SHARED_MEM_CMD_UPLOAD_END,0);
shared_memory_write(SHARED_MEM_TX_CMD_UPLOAD_END, 0);
ret_len = 0;
/*
* -------------------------------------------------------------------------
*/
/*
* -------------------------------------------------------------------------
*/
} else if (rq->bRequest == USB_CRC) {
req_addr = rq->wValue.word;
req_addr = req_addr << 16;
req_addr = req_addr | rq->wIndex.word;
debug(DEBUG_USB,"USB_CRC: addr=0x%08lx \n", req_addr);
debug(DEBUG_USB, "USB_CRC: addr=0x%08lx \n", req_addr);
crc_check_bulk_memory(0x000000, req_addr, req_bank_size);
ret_len = 0;
/*
* -------------------------------------------------------------------------
*/
/*
* -------------------------------------------------------------------------
*/
} else if (rq->bRequest == USB_MODE_SNES) {
req_state = REQ_STATUS_SNES;
debug(DEBUG_USB,"USB_MODE_SNES:\n");
debug(DEBUG_USB, "USB_MODE_SNES:\n");
ret_len = 0;
/*
* -------------------------------------------------------------------------
*/
/*
* -------------------------------------------------------------------------
*/
} else if (rq->bRequest == USB_MODE_AVR) {
req_state = REQ_STATUS_AVR;
debug(DEBUG_USB,"USB_MODE_AVR:\n");
debug(DEBUG_USB, "USB_MODE_AVR:\n");
ret_len = 0;
/*
* -------------------------------------------------------------------------
*/
/*
* -------------------------------------------------------------------------
*/
} else if (rq->bRequest == USB_AVR_RESET) {
debug(DEBUG_USB,"USB_AVR_RESET:\n");
debug(DEBUG_USB, "USB_AVR_RESET:\n");
soft_reset();
ret_len = 0;
/*
* -------------------------------------------------------------------------
*/
/*
* -------------------------------------------------------------------------
*/
} else if (rq->bRequest == USB_CRC_ADDR) {
req_state = REQ_STATUS_CRC;
req_addr = rq->wValue.word;
req_addr = req_addr << 16;
req_addr = req_addr | rq->wIndex.word;
debug(DEBUG_USB,"USB_CRC_ADDR: addr=0x%lx size=%i\n", req_addr,
rq->wLength.word);
debug(DEBUG_USB, "USB_CRC_ADDR: addr=0x%lx size=%i\n", req_addr,
rq->wLength.word);
req_size = rq->wLength.word;
req_size = req_size << 2;
tx_remaining = 2;
debug(DEBUG_USB,"USB_CRC_ADDR: addr=0x%lx size=%li\n", req_addr, req_size);
debug(DEBUG_USB, "USB_CRC_ADDR: addr=0x%lx size=%li\n", req_addr,
req_size);
crc = crc_check_memory_range(req_addr, req_size, read_buffer);
tx_buffer[0] = crc & 0xff;
@@ -288,8 +251,7 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
}
usbMsgPtr = data_buffer;
return ret_len; /* default for not implemented requests: return
* no data back to host */
return ret_len; /* default for not implemented requests: return no data back to host */
}
@@ -297,140 +259,17 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
* -------------------------------------------------------------------------
*/
void test_read_write(){
uint8_t i;
uint32_t addr;
avr_bus_active();
addr = 0x000000;
i = 1;
while (addr++ <= 0x0000ff){
sram_write(addr,i++);
}
addr = 0x000000;
while (addr++ <= 0x0000ff){
info("read addr=0x%08lx %x\n",addr,sram_read(addr));
}
}
void test_bulk_read_write(){
uint8_t i;
uint32_t addr;
avr_bus_active();
addr = 0x000000;
i = 0;
sram_bulk_write_start(addr);
while (addr++ <= 0x8000){
sram_bulk_write(i++);
sram_bulk_write_next();
}
sram_bulk_write_end();
addr = 0x000000;
sram_bulk_read_start(addr);
while (addr <= 0x8000){
info("addr=0x%08lx %x\n",addr,sram_bulk_read());
sram_bulk_read_next();
addr++;
}
sram_bulk_read_end();
}
void test_non_zero_memory(uint32_t bottom_addr,uint32_t top_addr)
void usb_connect()
{
uint32_t addr = 0;
uint8_t c;
sram_bulk_read_start(bottom_addr);
for (addr = bottom_addr; addr < top_addr; addr++) {
c = sram_bulk_read();
if (c!=0xff)
info("addr=0x%08lx c=0x%x\n",addr,c);
sram_bulk_read_next();
}
sram_bulk_read_end();
}
void test_crc(){
info("test_crc: clear\n");
avr_bus_active();
sram_bulk_set(0x000000,0x10000,0xff);
info("test_crc: crc\n");
crc_check_bulk_memory(0x000000,0x10000,0x8000);
info("test_crc: check\n");
test_non_zero_memory(0x000000,0x10000);
}
uint16_t read_byte_pgm(uint16_t addr){
return pgm_read_byte((PGM_VOID_P)addr);
}
void decompress_huffman(PGM_VOID_P addr, uint16_t(*fp)(uint16_t)){
uint16_t c;
uint32_t i = 0;
huffman_dec_ctx_t ctx;
info("ok1\n");
huffman_dec_init(&ctx, fp);
info("ok2\n");
huffman_dec_set_addr(&ctx, (uint16_t)addr);
info("ok3\n");
while(1){
info("ok4\n");
i++;
c=huffman_dec_byte(&ctx);
if (i%1024==0)
info(".");
if(c>0xff){
return;
}
c&=0xff;
sram_bulk_write(c);
}
}
void send_reset(){
info("Reset Snes\n");
snes_reset_on();
snes_reset_lo();
_delay_ms(2);
snes_reset_hi();
snes_reset_off();
}
void send_irq(){
snes_irq_on();
snes_irq_lo();
_delay_us(20);
snes_irq_hi();
snes_irq_off();
}
void set_rom_mode(){
if (req_bank_size == 0x8000){
snes_lorom();
info("Set Snes lowrom \n");
} else {
snes_hirom();
info("Set Snes hirom \n");
}
}
void usb_connect(){
uint8_t i = 0;
info("USB init\n");
usbDeviceDisconnect(); /* enforce re-enumeration, do this while */
cli();
cli();
info("USB disconnect\n");
i = 10;
while (--i) { /* fake USB disconnect for > 250 ms */
led_on();
led_on();
_delay_ms(35);
led_off();
_delay_ms(65);
@@ -441,77 +280,68 @@ void usb_connect(){
}
void boot_startup_rom(){
void boot_startup_rom()
{
info("Activate AVR bus\n");
avr_bus_active();
info("IRQ off\n");
snes_irq_lo();
snes_irq_off();
snes_lorom();
info("Set Snes lowrom \n");
info("Huffman decompress to 0x010000\n",(void*)_rom);
sram_bulk_write_start(0x010000);
decompress_huffman(&_rom,read_byte_pgm);
sram_bulk_write_end();
info("RLE decompress to 0x000000\n",(void*)_rom);
rle_decode_sram(0x010000, ROM_RLE_SIZE, 0x000000);
rle_decode(&_rom, ROM_BUFFER_SIZE, 0x000000);
dump_memory(0x10000 - 0x100, 0x10000);
snes_reset_hi();
snes_reset_off();
snes_irq_lo();
snes_irq_off();
info("IRQ off\n");
snes_hirom();
snes_wr_disable();
snes_wr_disable();
info("Disable snes WR\n");
snes_bus_active();
info("Activate Snes bus\n");
_delay_ms(100);
info("Reset Snes\n");
_delay_ms(20);
send_reset();
_delay_ms(100);
#if 0
uint8_t i = 0;
i = 20;
info("Wait");
while (--i){
_delay_ms(500);
info(".");
}
info("\n");
#endif
_delay_ms(200);
}
int main(void)
{
uart_init();
stdout = &uart_stdout;
info("Sytem start\n");
system_init();
#if 0
test_read_write();
test_bulk_read_write();
test_crc();
while(1);
#if 1
avr_bus_active();
info("Activate AVR bus\n");
info("IRQ off\n");
snes_irq_lo();
snes_irq_off();
info("Set Snes lowrom\n");
snes_lorom();
info("Disable snes WR\n");
snes_wr_disable();
test_sdcard();
#endif
info("Boot startup rom\n");
boot_startup_rom();
usbInit();
usb_connect();
while (1){
while (1) {
avr_bus_active();
info("Activate AVR bus\n");
info("IRQ off\n");
@@ -520,70 +350,64 @@ int main(void)
info("Set Snes lowrom\n");
snes_lorom();
info("Disable snes WR\n");
snes_wr_disable();
snes_wr_disable();
sei();
info("USB poll\n");
while (req_state != REQ_STATUS_SNES){
while (req_state != REQ_STATUS_SNES) {
usbPoll();
}
shared_memory_put(SHARED_MEM_CMD_TERMINATE,0);
shared_memory_write(SHARED_MEM_TX_CMD_TERMINATE, 0);
info("USB poll done\n");
snes_reset_hi();
snes_reset_off();
snes_irq_lo();
snes_irq_off();
info("IRQ off\n");
set_rom_mode();
snes_wr_disable();
snes_wr_disable();
info("Disable snes WR\n");
snes_bus_active();
info("Activate Snes bus\n");
_delay_ms(100);
info("Reset Snes\n");
send_reset();
info("Poll\n");
while (req_state != REQ_STATUS_AVR){
while (req_state != REQ_STATUS_AVR) {
usbPoll();
#ifdef DO_IRQ
#ifdef DO_IRQ
uint8_t i;
uint16_t irq_count = 0;
i = 10;
while (--i) {
_delay_ms(100);
}
info("Send IRQ %i\n",++irq_count);
info("Send IRQ %i\n", ++irq_count);
send_irq();
#endif
#ifdef DO_BUS_STEALING
#ifdef DO_BUS_STEALING
avr_bus_active();
sram_bulk_read_start(0x003000);
c = sram_bulk_read();
i = 5;
while (--i) {
while (--i) {
_delay_ms(500);
info("Wait to switch to snes mode %i\n", i);
}
if (req_bank_size == 0x8000){
if (req_bank_size == 0x8000) {
snes_lorom();
info("Set Snes lowrom \n");
} else {
snes_hirom();
info("Set Snes hirom \n");
}
snes_wr_disable();
snes_wr_disable();
info("Disable snes WR\n");
snes_bus_active();
info("Activate Snes bus\n");
info("Read 0x3000=%c\n",c);
info("Read 0x3000=%c\n", c);
#endif
}
info("Boot startup rom\n");
boot_startup_rom();
}
return 0;
}

220
avr/usbload/mmc.c Normal file
View File

@@ -0,0 +1,220 @@
/*
* ####################################################################################### Connect AVR to MMC/SD
*
* Copyright (C) 2004 Ulrich Radig
*
* Bei Fragen und Verbesserungen wendet euch per EMail an
*
* mail@ulrichradig.de
*
* oder im Forum meiner Web Page : www.ulrichradig.de
*
* Dieses Programm ist freie Software. Sie können es unter den Bedingungen der GNU General Public License, wie von der Free Software
* Foundation veröffentlicht, weitergeben und/oder modifizieren, entweder gemäß Version 2 der Lizenz oder (nach Ihrer Option) jeder
* späteren Version.
*
* Die Veröffentlichung dieses Programms erfolgt in der Hoffnung, daß es Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE,
* sogar ohne die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Details finden Sie in der GNU
* General Public License.
*
* Sie sollten eine Kopie der GNU General Public License zusammen mit diesem Programm erhalten haben. Falls nicht, schreiben Sie an die
* Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
* #######################################################################################
*/
#include <avr/io.h>
#include <util/delay.h>
#include "mmc.h"
uint8_t mmc_init()
{
uint16_t Timeout = 0, i;
MMC_REG |= ((1 << MMC_DO) | (1 << MMC_CS) | (1 << MMC_CLK));
MMC_REG &= ~(1 << MMC_DI);
MMC_WRITE |= ((1 << MMC_DO) | (1 << MMC_DI) | (1 << MMC_CS));
_delay_ms(20);
for (i = 0; i < 250; i++) {
MMC_WRITE ^= (1 << MMC_CLK);
_delay_us(4);
}
MMC_WRITE &= ~(1 << MMC_CLK);
_delay_us(10);
MMC_WRITE &= ~(1 << MMC_CS);
_delay_us(3);
uint8_t CMD[] = { 0x40, 0x00, 0x00, 0x00, 0x00, 0x95 };
while (mmc_write_command(CMD) != 1) {
if (Timeout++ > 20) {
mmc_disable();
return (1);
}
}
Timeout = 0;
CMD[0] = 0x41;
CMD[5] = 0xFF;
while (mmc_write_command(CMD) != 0) {
if (Timeout++ > 800) {
mmc_disable();
return (9);
}
}
return (0);
}
uint8_t mmc_write_command(uint8_t * cmd)
{
uint8_t tmp = 0xff;
uint16_t Timeout = 0;
uint8_t a;
for (a = 0; a < 0x06; a++) {
mmc_write_byte(*cmd++);
}
while (tmp == 0xff) {
tmp = mmc_read_byte();
if (Timeout++ > 50) {
break;
}
}
return (tmp);
}
uint8_t mmc_read_byte(void)
{
uint8_t Byte = 0, j;
for (j = 0; j < 8; j++) {
Byte = (Byte << 1);
MMC_WRITE |= (1 << MMC_CLK);
_delay_us(4);
if (PINB & (1 << MMC_DI)) {
Byte |= 1;
}
else {
Byte &= ~1;
}
MMC_WRITE &= ~(1 << MMC_CLK);
_delay_us(4);
}
return (Byte);
}
void mmc_write_byte(uint8_t Byte)
{
uint8_t i;
for (i = 0; i < 8; i++) {
if (Byte & 0x80) {
MMC_WRITE |= (1 << MMC_DO);
}
else {
MMC_WRITE &= ~(1 << MMC_DO);
}
Byte = (Byte << 1);
MMC_WRITE |= (1 << MMC_CLK);
_delay_us(4);
MMC_WRITE &= ~(1 << MMC_CLK);
_delay_us(4);
}
MMC_WRITE |= (1 << MMC_DO);
}
uint8_t mmc_write_sector(uint32_t addr, uint8_t * Buffer)
{
uint8_t tmp;
uint8_t cmd[] = { 0x58, 0x00, 0x00, 0x00, 0x00, 0xFF };
uint8_t a;
uint16_t i;
addr = addr << 9;
cmd[1] = ((addr & 0xFF000000) >> 24);
cmd[2] = ((addr & 0x00FF0000) >> 16);
cmd[3] = ((addr & 0x0000FF00) >> 8);
tmp = mmc_write_command(cmd);
if (tmp != 0) {
return (tmp);
}
for (a = 0; a < 100; a++) {
mmc_read_byte();
}
mmc_write_byte(0xFE);
for (a = 0; i < 512; i++) {
mmc_write_byte(*Buffer++);
}
mmc_write_byte(0xFF);
mmc_write_byte(0xFF);
if ((mmc_read_byte() & 0x1F) != 0x05)
return (1);
while (mmc_read_byte() != 0xff) {
};
return (0);
}
void mmc_read_block(uint8_t * cmd, uint8_t * Buffer, uint16_t Bytes)
{
uint16_t a;
if (mmc_write_command(cmd) != 0) {
return;
}
while (mmc_read_byte() != 0xfe) {
};
for (a = 0; a < Bytes; a++) {
*Buffer++ = mmc_read_byte();
}
mmc_read_byte();
mmc_read_byte();
return;
}
uint8_t mmc_read_sector(uint32_t addr, uint8_t * Buffer)
{
uint8_t cmd[] = { 0x51, 0x00, 0x00, 0x00, 0x00, 0xFF };
addr = addr << 9;
cmd[1] = ((addr & 0xFF000000) >> 24);
cmd[2] = ((addr & 0x00FF0000) >> 16);
cmd[3] = ((addr & 0x0000FF00) >> 8);
mmc_read_block(cmd, Buffer, 512);
return (0);
}
uint8_t mmc_read_cid(uint8_t * Buffer)
{
uint8_t cmd[] = { 0x4A, 0x00, 0x00, 0x00, 0x00, 0xFF };
mmc_read_block(cmd, Buffer, 16);
return (0);
}
uint8_t mmc_read_csd(uint8_t * Buffer)
{
uint8_t cmd[] = { 0x49, 0x00, 0x00, 0x00, 0x00, 0xFF };
mmc_read_block(cmd, Buffer, 16);
return (0);
}

44
avr/usbload/mmc.h Normal file
View File

@@ -0,0 +1,44 @@
/*
* ####################################################################################### Connect ARM to MMC/SD
*
* Copyright (C) 2004 Ulrich Radig #######################################################################################
*/
#ifndef _MMC_H
#define _MMC_H
#define SPI_Mode 0 // 1 = Hardware SPI | 0 = Software SPI
#define MMC_WRITE PORTB
#define MMC_READ PINB
#define MMC_REG DDRB
#define MMC_CS PB4
#define MMC_DO PB6
#define MMC_DI PB5
#define MMC_CLK PB7
#define MMC_WRITE PORTB // Port an der die MMC/SD-Karte angeschlossen ist also des SPI
#define MMC_READ PINB
#define MMC_REG DDRB
extern uint8_t mmc_read_byte(void);
extern void mmc_write_byte(uint8_t);
extern void mmc_read_block(uint8_t *, uint8_t *, unsigned in);
extern uint8_t mmc_init(void);
extern uint8_t mmc_read_sector(unsigned long, uint8_t *);
extern uint8_t mmc_write_sector(unsigned long, uint8_t *);
extern uint8_t mmc_write_command(uint8_t *);
#define mmc_disable() MMC_WRITE|= (1<<MMC_CS);
#define mmc_enable() MMC_WRITE&=~(1<<MMC_CS);
#define nop() __asm__ __volatile__ ("nop" ::)
#endif

View File

@@ -18,7 +18,7 @@
* =====================================================================================
*/
#include <avr/io.h>
#include <stdlib.h>
#include <stdio.h>
@@ -34,12 +34,12 @@
uint8_t rle_decode(PGM_VOID_P in_addr, int32_t in_len, uint32_t out_addr)
{
uint8_t in_byte, in_repeat, last_byte;
uint32_t out_len, out_len_left;
info("RLE decode len=%li addr=0x%08lx\n",in_len,out_addr);
uint8_t in_byte, in_repeat, last_byte;
uint32_t out_len, out_len_left;
info("RLE decode len=%li addr=0x%08lx\n", in_len, out_addr);
last_byte = 0;
out_len_left = out_len;
out_len_left = out_len;
sram_bulk_write_start(out_addr);
#define INBYTE(b) \
do { \
@@ -58,100 +58,46 @@ uint8_t rle_decode(PGM_VOID_P in_addr, int32_t in_len, uint32_t out_addr)
out_addr++;\
} while(0)
INBYTE(in_byte);
INBYTE(in_byte);
if (in_byte == RUNCHAR) {
INBYTE(in_repeat);
if (in_repeat != 0) {
info("Orphaned RLE code at start\n");
return 1;
}
OUTBYTE(RUNCHAR);
} else {
OUTBYTE(in_byte);
}
if (in_byte == RUNCHAR) {
INBYTE(in_repeat);
if (in_repeat != 0) {
info("Orphaned RLE code at start\n");
return 1;
}
OUTBYTE(RUNCHAR);
} else {
OUTBYTE(in_byte);
}
while( in_len > 0 ) {
INBYTE(in_byte);
if (in_len%1024==0)
while (in_len > 0) {
INBYTE(in_byte);
if (in_len % 1024 == 0)
info(".");
if (in_byte == RUNCHAR) {
INBYTE(in_repeat);
if ( in_repeat == 0 ) {
/* Just an escaped RUNCHAR value */
OUTBYTE(RUNCHAR);
} else {
/* Pick up value and output a sequence of it */
in_byte = last_byte; //;out_data[-1];
while ( --in_repeat > 0 )
OUTBYTE(in_byte);
}
} else {
/* Normal byte */
OUTBYTE(in_byte);
}
if (in_byte == RUNCHAR) {
INBYTE(in_repeat);
if (in_repeat == 0) {
/*
* Just an escaped RUNCHAR value
*/
OUTBYTE(RUNCHAR);
} else {
/*
* Pick up value and output a sequence of it
*/
in_byte = last_byte; // ;out_data[-1];
while (--in_repeat > 0)
OUTBYTE(in_byte);
}
} else {
/*
* Normal byte
*/
OUTBYTE(in_byte);
}
last_byte = in_byte;
}
}
sram_bulk_write_end();
return 0;
}
uint8_t rle_decode_sram(uint32_t in_addr, int32_t in_len, uint32_t out_addr)
{
uint8_t in_byte, in_repeat, last_byte;
uint32_t out_len, out_len_left;
info("RLE decode len=%li addr=0x%08lx\n",in_len,out_addr);
last_byte = 0;
out_len_left = out_len;
#define INBYTE(b) \
do { \
if ( --in_len < 0 ) { \
return 1; \
} \
b = sram_read(in_addr);\
in_addr++;\
} while(0)
#define OUTBYTE(b) \
do { \
sram_write(out_addr,b);\
out_addr++;\
} while(0)
INBYTE(in_byte);
if (in_byte == RUNCHAR) {
INBYTE(in_repeat);
if (in_repeat != 0) {
info("Orphaned RLE code at start\n");
return 1;
}
OUTBYTE(RUNCHAR);
} else {
OUTBYTE(in_byte);
}
while( in_len > 0 ) {
INBYTE(in_byte);
if (in_len%1024==0)
info(".");
if (in_byte == RUNCHAR) {
INBYTE(in_repeat);
if ( in_repeat == 0 ) {
/* Just an escaped RUNCHAR value */
OUTBYTE(RUNCHAR);
} else {
/* Pick up value and output a sequence of it */
in_byte = last_byte; //;out_data[-1];
while ( --in_repeat > 0 )
OUTBYTE(in_byte);
}
} else {
/* Normal byte */
OUTBYTE(in_byte);
}
last_byte = in_byte;
}
return 0;
return 0;
}

View File

@@ -18,12 +18,11 @@
* =====================================================================================
*/
#ifndef __RLE_H__
#define __RLE_H__
#include <avr/pgmspace.h>
#ifndef __RLE_H__
#define __RLE_H__
uint8_t rle_decode(PGM_VOID_P in_addr,uint32_t in_len, uint32_t out_addr);
uint8_t rle_decode_sram(uint32_t in_addr, int32_t in_len, uint32_t out_addr);
#include <avr/pgmspace.h>
uint8_t rle_decode(PGM_VOID_P in_addr, uint32_t in_len, uint32_t out_addr);
#endif

View File

@@ -19,11 +19,11 @@
*
* =====================================================================================
*/
#include <stdlib.h>
#include <stdint.h>
#include <util/delay.h>
#include <util/delay.h>
#include "shared_memory.h"
#include "config.h"
@@ -38,55 +38,125 @@ uint8_t scratchpad_state;
uint8_t scratchpad_cmd;
uint8_t scratchpad_payload;
void shared_memory_scratchpad_save(){
scratchpad_state = sram_read(SHARED_MEM_LOC_STATE);
scratchpad_cmd = sram_read(SHARED_MEM_LOC_CMD);
scratchpad_payload = sram_read(SHARED_MEM_LOC_PAYLOAD);
void shared_memory_scratchpad_tx_save()
{
scratchpad_state = sram_read(SHARED_MEM_TX_LOC_STATE);
scratchpad_cmd = sram_read(SHARED_MEM_TX_LOC_CMD);
scratchpad_payload = sram_read(SHARED_MEM_TX_LOC_PAYLOAD);
}
void shared_memory_scratchpad_restore(){
sram_write(SHARED_MEM_LOC_STATE, scratchpad_state);
sram_write(SHARED_MEM_LOC_CMD, scratchpad_cmd);
sram_write(SHARED_MEM_LOC_PAYLOAD, scratchpad_payload);
void shared_memory_scratchpad_tx_restore()
{
sram_write(SHARED_MEM_TX_LOC_STATE, scratchpad_state);
sram_write(SHARED_MEM_TX_LOC_CMD, scratchpad_cmd);
sram_write(SHARED_MEM_TX_LOC_PAYLOAD, scratchpad_payload);
}
void shared_memory_irq_hook(){
void shared_memory_irq_hook()
{
irq_addr_lo = sram_read(SHARED_IRQ_LOC_LO);
irq_addr_hi = sram_read(SHARED_IRQ_LOC_HI);
sram_write(SHARED_IRQ_HANDLER_LO, 0);
sram_write(SHARED_IRQ_HANDLER_HI, 0);
}
void shared_memory_irq_restore(){
void shared_memory_irq_restore()
{
sram_write(SHARED_IRQ_LOC_LO, irq_addr_lo);
sram_write(SHARED_IRQ_LOC_HI, irq_addr_hi);
}
void shared_memory_put(uint8_t cmd, uint8_t value){
info("Write shared memory 0x%04x=0x%02x 0x%04x=0x%02x \n",SHARED_MEM_LOC_CMD,cmd,SHARED_MEM_LOC_PAYLOAD,value);
void shared_memory_write(uint8_t cmd, uint8_t value)
{
shared_memory_scratchpad_save();
debug(DEBUG_SHM,"shared_memory_write: 0x%04x=0x%02x 0x%04x=0x%02x \n",
SHARED_MEM_TX_LOC_CMD, cmd, SHARED_MEM_TX_LOC_PAYLOAD, value);
sram_bulk_addr_save();
shared_memory_scratchpad_tx_save();
shared_memory_irq_hook();
sram_write(SHARED_MEM_LOC_STATE,SHARED_MEM_SNES_ACK);
sram_write(SHARED_MEM_LOC_CMD,cmd);
sram_write(SHARED_MEM_LOC_PAYLOAD,value);
sram_write(SHARED_MEM_TX_LOC_STATE, SHARED_MEM_TX_SNES_ACK);
sram_write(SHARED_MEM_TX_LOC_CMD, cmd);
sram_write(SHARED_MEM_TX_LOC_PAYLOAD, value);
snes_hirom();
snes_wr_disable();
snes_wr_disable();
snes_bus_active();
_delay_ms(50);
#if SHARED_MEM_SWITCH_IRQ
snes_irq_on();
snes_irq_lo();
_delay_us(20);
snes_irq_hi();
snes_irq_off();
#else
_delay_ms(SHARED_MEM_SWITCH_DELAY);
#endif
avr_bus_active();
snes_irq_lo();
snes_irq_off();
snes_lorom();
snes_wr_disable();
shared_memory_scratchpad_restore();
snes_wr_disable();
shared_memory_scratchpad_tx_restore();
shared_memory_irq_restore();
sram_bulk_addr_restore();
}
void shared_memory_yield()
{
snes_hirom();
snes_wr_disable();
snes_bus_active();
_delay_ms(SHARED_MEM_SWITCH_DELAY);
avr_bus_active();
snes_lorom();
snes_wr_disable();
}
int shared_memory_read(uint8_t *cmd, uint8_t *len,uint8_t *buffer)
{
uint8_t state;
state = sram_read(SHARED_MEM_RX_LOC_STATE);
if (state != SHARED_MEM_RX_AVR_ACK){
return 1;
}
sram_bulk_addr_save();
*cmd = sram_read(SHARED_MEM_RX_LOC_CMD);
*len = sram_read(SHARED_MEM_RX_LOC_LEN);
debug(DEBUG_SHM,"shared_memory_read: 0x%04x=0x%02x 0x%04x=0x%02x \n",
SHARED_MEM_RX_LOC_CMD, *cmd, SHARED_MEM_RX_LOC_LEN, *len);
sram_bulk_read_buffer(SHARED_MEM_RX_LOC_PAYLOAD,buffer, *len);
sram_write(SHARED_MEM_RX_LOC_STATE, SHARED_MEM_RX_AVR_RTS);
snes_hirom();
snes_wr_disable();
snes_bus_active();
#if SHARED_MEM_SWITCH_IRQ
snes_irq_on();
snes_irq_lo();
_delay_us(20);
snes_irq_hi();
snes_irq_off();
#else
_delay_ms(SHARED_MEM_SWITCH_DELAY);
#endif
avr_bus_active();
snes_lorom();
snes_wr_disable();
sram_bulk_addr_restore();
return 0;
}

View File

@@ -17,35 +17,50 @@
*
* =====================================================================================
*/
#ifndef __SHARED_MEMORY_H__
#define __SHARED_MEMORY_H__
#define SHARED_MEM_SNES_ACK 0xa5
#define SHARED_MEM_SNES_RTS 0x5a
#define SHARED_MEM_SWITCH_IRQ 0
#define SHARED_MEM_SWITCH_DELAY 20
#define SHARED_MEM_TX_SNES_ACK 0xa5
#define SHARED_MEM_TX_SNES_RTS 0x5a
#define SHARED_MEM_TX_CMD_BANK_COUNT 0x00
#define SHARED_MEM_TX_CMD_BANK_CURRENT 0x01
#define SHARED_MEM_TX_CMD_UPLOAD_START 0x03
#define SHARED_MEM_TX_CMD_UPLOAD_END 0x04
#define SHARED_MEM_TX_CMD_UPLOAD_PROGESS 0x05
#define SHARED_MEM_TX_CMD_TERMINATE 0x06
#define SHARED_MEM_TX_LOC_STATE 0x000000
#define SHARED_MEM_TX_LOC_CMD 0x000001
#define SHARED_MEM_TX_LOC_PAYLOAD 0x000002
#define SHARED_MEM_RX_AVR_ACK 0xa5
#define SHARED_MEM_RX_AVR_RTS 0x5a
#define SHARED_MEM_RX_CMD_PRINFT 0x00
#define SHARED_MEM_RX_CMD_FILESEL 0x01
#define SHARED_MEM_RX_LOC_STATE 0x001000
#define SHARED_MEM_RX_LOC_CMD 0x001001
#define SHARED_MEM_RX_LOC_LEN 0x001002
#define SHARED_MEM_RX_LOC_PAYLOAD 0x001003
#define SHARED_IRQ_LOC_LO 0x00fffe
#define SHARED_IRQ_LOC_HI 0x00ffff
/* Use COP IRQ LOC for hooked IRQ handler */
#define SHARED_IRQ_HANDLER_LO 0x0ffe4
#define SHARED_IRQ_HANDLER_HI 0x0ffe5
#define SHARED_MEM_CMD_BANK_COUNT 0
#define SHARED_MEM_CMD_BANK_CURRENT 1
#define SHARED_MEM_CMD_UPLOAD_START 3
#define SHARED_MEM_CMD_UPLOAD_END 4
#define SHARED_MEM_CMD_UPLOAD_PROGESS 5
#define SHARED_MEM_CMD_TERMINATE 6
#define SHARED_MEM_LOC_STATE 0x000000
#define SHARED_MEM_LOC_CMD 0x000001
#define SHARED_MEM_LOC_PAYLOAD 0x000002
#define SHARED_IRQ_LOC_LO 0x00fffe
#define SHARED_IRQ_LOC_HI 0x00ffff
#define SHARED_IRQ_HANDLER_LO 0x00
#define SHARED_IRQ_HANDLER_HI 0x10
void shared_memory_put(uint8_t cmd, uint8_t value);
void shared_memory_write(uint8_t cmd, uint8_t value);
int shared_memory_read(uint8_t *cmd, uint8_t *len,uint8_t *buffer);
#endif

View File

@@ -22,8 +22,7 @@
#include <stdlib.h>
#include <stdint.h>
#include <avr/io.h>
#include <util/delay.h> /* for _delay_ms() */
#include <util/delay.h>
#include "config.h"
#include "sram.h"
@@ -31,6 +30,10 @@
#include "debug.h"
#include "info.h"
uint32_t addr_current = 0;
uint32_t addr_stash = 0;
void system_init(void)
{
/*-------------------------------------------------*/
@@ -93,19 +96,19 @@ void system_init(void)
void sreg_set(uint32_t addr)
{
uint8_t i = 24;
debug(DEBUG_SREG,"sreg_set: addr=0x%08lx",addr);
debug(DEBUG_SRAM,"sreg_set: addr=0x%08lx\n",addr);
while(i--) {
if ((addr & ( 1L << i))){
debug(DEBUG_SREG,"1");
debug(DEBUG_SRAM,"1");
AVR_ADDR_SER_PORT |= ( 1 << AVR_ADDR_SER_PIN);
} else {
AVR_ADDR_SER_PORT &= ~( 1 << AVR_ADDR_SER_PIN);
debug(DEBUG_SREG,"0");
debug(DEBUG_SRAM,"0");
}
AVR_ADDR_SCK_PORT |= (1 << AVR_ADDR_SCK_PIN);
AVR_ADDR_SCK_PORT &= ~(1 << AVR_ADDR_SCK_PIN);
}
debug(DEBUG_SREG,"\n");
debug(DEBUG_SRAM,"\n");
AVR_ADDR_LATCH_PORT |= (1 << AVR_ADDR_LATCH_PIN);
AVR_ADDR_LATCH_PORT &= ~(1 << AVR_ADDR_LATCH_PIN);
@@ -113,11 +116,23 @@ void sreg_set(uint32_t addr)
}
inline void sram_bulk_addr_save()
{
addr_stash = addr_current;
}
inline void sram_bulk_addr_restore()
{
sreg_set(addr_stash);
}
void sram_bulk_read_start(uint32_t addr)
{
debug(DEBUG_SRAM,"sram_bulk_read_start: addr=0x%08lx\n\r", addr);
addr_current = addr;
avr_data_in();
AVR_CS_PORT &= ~(1 << AVR_CS_PIN);
@@ -138,6 +153,7 @@ void sram_bulk_read_start(uint32_t addr)
inline void sram_bulk_read_next(void)
{
addr_current++;
AVR_RD_PORT |= (1 << AVR_RD_PIN);
counter_up();
AVR_RD_PORT &= ~(1 << AVR_RD_PIN);
@@ -309,48 +325,3 @@ void sram_bulk_set(uint32_t addr, uint32_t len,uint8_t value){
sram_bulk_write_end();
}
void sram_setr(uint32_t addr, uint32_t len,uint8_t value)
{
uint32_t i;
debug(DEBUG_SRAM,"sram_clear: addr=0x%08lx len=%li\n\r", addr,len);
for (i = addr; i < (addr + len); i++) {
if (0 == i % 0xfff)
debug(DEBUG_SRAM,"sram_clear: addr=0x%08lx\n\r", i);
sram_write(i, value);
}
}
void sram_copy(uint32_t addr, uint8_t * src, uint32_t len)
{
uint32_t i;
uint8_t *ptr = src;
debug(DEBUG_SRAM,"sram_copy: addr=0x%08lx src=0x%p len=%li\n\r", addr,src,len);
for (i = addr; i < (addr + len); i++)
sram_write(i, *ptr++);
}
void sram_read_buffer(uint32_t addr, uint8_t * dst, uint32_t len)
{
uint32_t i;
uint8_t *ptr = dst;
debug(DEBUG_SRAM,"sram_read_buffer: addr=0x%08lx dst=0x%p len=%li\n\r", addr,dst,len);
for (i = addr; i < (addr + len); i++) {
*ptr = sram_read(i);
ptr++;
}
}
uint8_t sram_check(uint8_t * buffer, uint32_t len)
{
uint16_t cnt;
debug(DEBUG_SRAM,"sram_check: len=%li\n\r",len);
for (cnt = 0; cnt < len; cnt++)
if (buffer[cnt])
return 1;
return 0;
}

View File

@@ -186,9 +186,6 @@ void sreg_set(uint32_t addr);
uint8_t sram_read(uint32_t addr);
void sram_write(uint32_t addr, uint8_t data);
void sram_set(uint32_t addr, uint32_t len, uint8_t value);
void sram_copy(uint32_t addr,uint8_t *src, uint32_t len);
void sram_read_buffer(uint32_t addr,uint8_t *dst, uint32_t len);
void sram_bulk_read_start(uint32_t addr);
inline void sram_bulk_read_next(void);
@@ -204,4 +201,9 @@ void sram_bulk_copy(uint32_t addr, uint8_t * src, uint32_t len);
void sram_bulk_read_buffer(uint32_t addr, uint8_t * dst, uint32_t len);
void sram_bulk_set(uint32_t addr, uint32_t len,uint8_t value);
inline void sram_bulk_addr_save();
inline void sram_bulk_addr_restore();
#endif

156
avr/usbload/testing.c Normal file
View File

@@ -0,0 +1,156 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <util/delay.h>
#include "shared_memory.h"
#include "config.h"
#include "sram.h"
#include "debug.h"
#include "crc.h"
#include "config.h"
#include "info.h"
#include "mmc.h"
#include "fat.h"
#include "file.h"
#include "dir.h"
void test_read_write()
{
uint8_t i;
uint32_t addr;
avr_bus_active();
addr = 0x000000;
i = 1;
while (addr++ <= 0x0000ff) {
sram_write(addr, i++);
}
addr = 0x000000;
while (addr++ <= 0x0000ff) {
info("read addr=0x%08lx %x\n", addr, sram_read(addr));
}
}
void test_bulk_read_write()
{
uint8_t i;
uint32_t addr;
avr_bus_active();
addr = 0x000000;
i = 0;
sram_bulk_write_start(addr);
while (addr++ <= 0x8000) {
sram_bulk_write(i++);
sram_bulk_write_next();
}
sram_bulk_write_end();
addr = 0x000000;
sram_bulk_read_start(addr);
while (addr <= 0x8000) {
info("addr=0x%08lx %x\n", addr, sram_bulk_read());
sram_bulk_read_next();
addr++;
}
sram_bulk_read_end();
}
void test_non_zero_memory(uint32_t bottom_addr, uint32_t top_addr)
{
uint32_t addr = 0;
uint8_t c;
sram_bulk_read_start(bottom_addr);
for (addr = bottom_addr; addr < top_addr; addr++) {
c = sram_bulk_read();
if (c != 0xff)
info("addr=0x%08lx c=0x%x\n", addr, c);
sram_bulk_read_next();
}
sram_bulk_read_end();
}
void test_crc()
{
info("test_crc: clear\n");
avr_bus_active();
sram_bulk_set(0x000000, 0x10000, 0xff);
info("test_crc: crc\n");
crc_check_bulk_memory(0x000000, 0x10000, 0x8000);
info("test_crc: check\n");
test_non_zero_memory(0x000000, 0x10000);
}
void test_sdcard(void){
while (mmc_init() !=0){ //ist der Rückgabewert ungleich NULL ist ein Fehler aufgetreten
printf("no sdcard\n");
}
if (fat_initfat()==0){
printf("fatinit ok\n");
} else {
printf("fatinit failed\n");
return;
}
printf("Root dirlist\n");
ffls_smc();
dump_memory(DIR_ENTRY_LOC , DIR_ENTRY_LOC + (64 * 2));
dir_entry_loop();
while(1);
#if (WRITE==1)
char datei[12]="test.txt"; // hier muss platz für 11 zeichen sein (8.3), da fat_str diesen string benutzt !!
fat_str(datei);
ffrm( datei ); // löschen der datei/ordner falls vorhanden
printf("open %s\n",datei);
ffopen( datei );
printf("write %s\n",datei);
ffwrites((char*)"Hallo Datei :)");
ffwrite(0x0D);
ffwrite(0x0A);
printf("close %s\n",datei);
ffclose();
printf("open %s\n",datei);
ffopen( datei );
printf("open %s\n",datei);
unsigned long int seek=file.length; // eine variable setzen und runterzählen bis 0 geht am schnellsten !
do{
printf("%c",ffread()); // liest ein zeichen und gibt es über uart aus !
}while(--seek); // liest solange bytes da sind (von datei länge bis 0)
ffclose(); // schließt datei
#endif
}

32
avr/usbload/testing.h Normal file
View File

@@ -0,0 +1,32 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#ifndef __TESTING_H__
#define __TESTING_H__
void test_read_write();
void test_bulk_read_write();
void test_non_zero_memory(uint32_t bottom_addr, uint32_t top_addr);
void test_crc();
void test_sdcard();
#endif

View File

@@ -37,3 +37,4 @@ static int uart_stream(char c, FILE *stream);
#endif

View File

@@ -60,16 +60,7 @@ uint8_t usbFunctionWrite(uint8_t * data, uint8_t len)
rx_remaining, len);
len = rx_remaining;
}
if (req_state == REQ_STATUS_UPLOAD) {
rx_remaining -= len;
debug(DEBUG_USB_TRANS,"usbFunctionWrite REQ_STATUS_UPLOAD addr: 0x%08lx len: %i rx_remaining=%i\n",
req_addr, len, rx_remaining);
debug(DEBUG_USB_TRANS,"usbFunctionWrite %02x %02x %02x %02x %02x %02x %02x %x\n",
data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[7]);
sram_copy(req_addr, data, len);
req_addr += len;
} else if (req_state == REQ_STATUS_BULK_UPLOAD) {
if (req_state == REQ_STATUS_BULK_UPLOAD) {
rx_remaining -= len;
debug(DEBUG_USB_TRANS,"usbFunctionWrite REQ_STATUS_BULK_UPLOAD addr: 0x%08lx len: %i rx_remaining=%i\n",

File diff suppressed because it is too large Load Diff

View File

@@ -5,7 +5,7 @@ import time
LEN = 2**16
huffman = False
TARGET="/Users/david/Devel/arch/avr/code/quickdev16/avr/usbload"
HUFFMAN_ENCODER="/Users/david/Devel/arch/avr/code/quickdev16/tools/huffman/huffman-encode"
data = open(sys.argv[1],"r").read()
@@ -15,19 +15,21 @@ print "Use %i bytes" % (len(data))
data = binascii.rlecode_hqx(data)
print "RLE crunch (%i) bytes" % (len(data))
binfile = open("/tmp/loader.rle","w")
binfile.write(data)
binfile.close()
rle_size = len(data)
huffman_size = 0
cmd = "%s /tmp/loader.rle" % HUFFMAN_ENCODER
os.system(cmd)
data = open("/tmp/loader.rle.hfm","r").read()
print "HUFFMAN crunch (%i) bytes" % (len(data))
huffman_size = len(data)
if huffman == True:
binfile = open("/tmp/loader.rle","w")
binfile.write(data)
binfile.close()
os.unlink("/tmp/loader.rle")
os.unlink("/tmp/loader.rle.hfm")
cmd = "%s /tmp/loader.rle" % HUFFMAN_ENCODER
os.system(cmd)
data = open("/tmp/loader.rle.hfm","r").read()
print "HUFFMAN crunch (%i) bytes" % (len(data))
huffman_size = len(data)
os.unlink("/tmp/loader.rle")
os.unlink("/tmp/loader.rle.hfm")
cfile = open("/tmp/loader.c","w")
hfile = open("/tmp/loader.h","w")