SD card early prototype
This commit is contained in:
parent
8ea8231ac5
commit
10ce1dfd31
|
@ -0,0 +1,31 @@
|
|||
# SD CARD COMMANDS
|
||||
|
||||
## I/O
|
||||
READ,WRITE for pure binaries,
|
||||
LOAD,BSAVE,RUN for basic/prodos format and .PRG
|
||||
TYPE
|
||||
DUMP
|
||||
|
||||
## FILE
|
||||
DEL
|
||||
REN
|
||||
COPY
|
||||
|
||||
## DIR
|
||||
DIR
|
||||
CD
|
||||
MKDIR
|
||||
RMDIR
|
||||
|
||||
## MISC
|
||||
HELP
|
||||
JMP
|
||||
STAT
|
||||
MOUNT
|
||||
TIME
|
||||
EXIT
|
||||
|
||||
/*
|
||||
1234567890123456789012345678901234567890
|
||||
0000: 00 00 00 00 00 00 00 00 12345678
|
||||
*/
|
|
@ -1,57 +1,65 @@
|
|||
// 1 per SD card normale, 0 per SDFat
|
||||
|
||||
#include <Regexp.h>
|
||||
|
||||
#define USE_SD_H 0
|
||||
|
||||
#include <SPI.h>
|
||||
|
||||
#if USE_SD_H
|
||||
#include <SD.h>
|
||||
#else
|
||||
#include "SdFat.h"
|
||||
SdFat SD;
|
||||
#endif
|
||||
|
||||
#define SD_CS_PIN SS
|
||||
|
||||
/*
|
||||
+-----------+ +-----------------+
|
||||
| | | ARDUINO |
|
||||
| VIA 6522 | | NANO |
|
||||
| | | |
|
||||
| PA0 |<------ bit 0 ------>| D2 | +-------\
|
||||
| PA1 |<------ bit 1 ------>| D3 D10 |----- SS ------>| \
|
||||
| PA2 |<------ bit 2 ------>| D4 D11 |----- MOSI ---->| SD |
|
||||
| PA3 |<------ bit 3 ------>| D5 D12 |<---- MISO -----| CARD |
|
||||
| PA4 |<------ bit 4 ------>| D6 D13 |----- SCK ----->| |
|
||||
| PA5 |<------ bit 5 ------>| D7 | +--------+
|
||||
| PA6 |<------ bit 6 ------>| D8 |
|
||||
| PA7 |<------ bit 7 ------>| D9 |
|
||||
| | | |
|
||||
| PB7 |<---- MCU_STROBE ----| D14/A0 |
|
||||
| PB0 |--- CPU_STROBE ----->| D15/A1 |
|
||||
| | | |
|
||||
+-----------+ +-----------------+
|
||||
*/
|
||||
|
||||
// pin definitions
|
||||
|
||||
// VIA 6522 connections
|
||||
#define BIT0 2
|
||||
#define BIT1 3
|
||||
#define BIT2 4
|
||||
#define BIT3 5
|
||||
#define BIT4 6
|
||||
#define BIT5 7
|
||||
#define BIT6 8
|
||||
#define BIT7 9
|
||||
|
||||
#define D0 1 /* I/O data bit 0, connects to PA0 on the VIA */
|
||||
#define D1 2 /* I/O data bit 1, connects to PA1 on the VIA */
|
||||
#define D2 3 /* I/O data bit 2, connects to PA2 on the VIA */
|
||||
#define D3 4 /* I/O data bit 3, connects to PA3 on the VIA */
|
||||
#define D4 5 /* I/O data bit 4, connects to PA4 on the VIA */
|
||||
#define D5 6 /* I/O data bit 5, connects to PA5 on the VIA */
|
||||
#define D6 7 /* I/O data bit 6, connects to PA6 on the VIA */
|
||||
#define D7 8 /* I/O data bit 7, connects to PA7 on the VIA */
|
||||
/* 10,11,12,13 reserved for SD card */
|
||||
|
||||
#define CPU_STROBE 9 /* PB0 => MCU 1=cpu byte is available on the data port; 0 cpu is waiting */
|
||||
#define MCU_STROBE 10 /* PB1 <= MCU 1=mcu byte is available on the data port; 0 mcu is waiting */
|
||||
#define MCU_STROBE 14
|
||||
#define CPU_STROBE 15
|
||||
|
||||
// indicates that a timeout occurred during wait()
|
||||
int TIMEOUT = 0;
|
||||
|
||||
void setup() {
|
||||
// debug on serial
|
||||
Serial.begin(9600);
|
||||
|
||||
pinMode(CPU_STROBE, INPUT);
|
||||
pinMode(MCU_STROBE, OUTPUT);
|
||||
|
||||
digitalWrite(MCU_STROBE, LOW);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// applicazione di esempio: manda un messaggio quando riceve il comando 42
|
||||
TIMEOUT = 0;
|
||||
|
||||
int data = receive_byte_from_cpu();
|
||||
|
||||
if(data == 42 && !TIMEOUT) {
|
||||
|
||||
Serial.println("command 42 received from CPU");
|
||||
char *msg = "HELLO WORLD!\r\n";
|
||||
for(int t=0; t<strlen(msg); t++) {
|
||||
send_byte_to_cpu(msg[t]);
|
||||
}
|
||||
send_byte_to_cpu(0); // terminatore stringa
|
||||
if(!TIMEOUT) Serial.println("message sent to CPU");
|
||||
else Serial.println("timeout during send to CPU");
|
||||
}
|
||||
}
|
||||
|
||||
void wait(int pin, int value) {
|
||||
|
||||
unsigned long start_time = millis();
|
||||
unsigned long elapsed;
|
||||
|
||||
if(TIMEOUT) break;
|
||||
if(TIMEOUT) return;
|
||||
|
||||
while(digitalRead(pin) != value) {
|
||||
elapsed = millis() - start_time;
|
||||
|
@ -62,18 +70,46 @@ void wait(int pin, int value) {
|
|||
}
|
||||
}
|
||||
|
||||
int receive_byte_from_cpu() {
|
||||
|
||||
// set data port as input
|
||||
pinMode(D0, INPUT);
|
||||
pinMode(D1, INPUT);
|
||||
pinMode(D2, INPUT);
|
||||
pinMode(D3, INPUT);
|
||||
pinMode(D4, INPUT);
|
||||
pinMode(D5, INPUT);
|
||||
pinMode(D6, INPUT);
|
||||
pinMode(D7, INPUT);
|
||||
const int DIR_INPUT = 0;
|
||||
const int DIR_OUTPUT = 1;
|
||||
|
||||
int last_dir; // remember last data port pins direction
|
||||
|
||||
void set_data_port_direction(int dir) {
|
||||
|
||||
// check if no need to set pins
|
||||
if(dir == last_dir) return;
|
||||
|
||||
if(dir == DIR_INPUT) {
|
||||
pinMode(BIT0, INPUT);
|
||||
pinMode(BIT1, INPUT);
|
||||
pinMode(BIT2, INPUT);
|
||||
pinMode(BIT3, INPUT);
|
||||
pinMode(BIT4, INPUT);
|
||||
pinMode(BIT5, INPUT);
|
||||
pinMode(BIT6, INPUT);
|
||||
pinMode(BIT7, INPUT);
|
||||
}
|
||||
else {
|
||||
pinMode(BIT0, OUTPUT);
|
||||
pinMode(BIT1, OUTPUT);
|
||||
pinMode(BIT2, OUTPUT);
|
||||
pinMode(BIT3, OUTPUT);
|
||||
pinMode(BIT4, OUTPUT);
|
||||
pinMode(BIT5, OUTPUT);
|
||||
pinMode(BIT6, OUTPUT);
|
||||
pinMode(BIT7, OUTPUT);
|
||||
}
|
||||
|
||||
// remember direction
|
||||
last_dir = dir;
|
||||
}
|
||||
|
||||
int receive_byte_from_cpu() {
|
||||
|
||||
// set data port pins as INPUT pins
|
||||
set_data_port_direction(DIR_INPUT);
|
||||
|
||||
// both strobes are 0
|
||||
|
||||
// CPU deposits data byte and sets strobe high
|
||||
|
@ -81,14 +117,14 @@ int receive_byte_from_cpu() {
|
|||
|
||||
// read the data byte
|
||||
int data =
|
||||
(digitalRead(D0) << 0) |
|
||||
(digitalRead(D1) << 1) |
|
||||
(digitalRead(D2) << 2) |
|
||||
(digitalRead(D3) << 3) |
|
||||
(digitalRead(D4) << 4) |
|
||||
(digitalRead(D5) << 5) |
|
||||
(digitalRead(D6) << 6) |
|
||||
(digitalRead(D7) << 7);
|
||||
(digitalRead(BIT0) << 0) |
|
||||
(digitalRead(BIT1) << 1) |
|
||||
(digitalRead(BIT2) << 2) |
|
||||
(digitalRead(BIT3) << 3) |
|
||||
(digitalRead(BIT4) << 4) |
|
||||
(digitalRead(BIT5) << 5) |
|
||||
(digitalRead(BIT6) << 6) |
|
||||
(digitalRead(BIT7) << 7);
|
||||
|
||||
// after reading the byte, MCU sets strobe high
|
||||
digitalWrite(MCU_STROBE, HIGH);
|
||||
|
@ -103,28 +139,21 @@ int receive_byte_from_cpu() {
|
|||
}
|
||||
|
||||
void send_byte_to_cpu(int data) {
|
||||
|
||||
// set data port as output
|
||||
pinMode(D0, OUTPUT);
|
||||
pinMode(D1, OUTPUT);
|
||||
pinMode(D2, OUTPUT);
|
||||
pinMode(D3, OUTPUT);
|
||||
pinMode(D4, OUTPUT);
|
||||
pinMode(D5, OUTPUT);
|
||||
pinMode(D6, OUTPUT);
|
||||
pinMode(D7, OUTPUT);
|
||||
|
||||
// set data port pins as OUTPUT pins
|
||||
set_data_port_direction(DIR_OUTPUT);
|
||||
|
||||
// both strobes are 0
|
||||
|
||||
// put byte on the data port
|
||||
digitalWrite(D0, data & 1);
|
||||
digitalWrite(D1, data & 2);
|
||||
digitalWrite(D2, data & 4);
|
||||
digitalWrite(D3, data & 8);
|
||||
digitalWrite(D4, data & 16);
|
||||
digitalWrite(D5, data & 32);
|
||||
digitalWrite(D6, data & 64);
|
||||
digitalWrite(D7, data & 128);
|
||||
digitalWrite(BIT0, data & 1);
|
||||
digitalWrite(BIT1, data & 2);
|
||||
digitalWrite(BIT2, data & 4);
|
||||
digitalWrite(BIT3, data & 8);
|
||||
digitalWrite(BIT4, data & 16);
|
||||
digitalWrite(BIT5, data & 32);
|
||||
digitalWrite(BIT6, data & 64);
|
||||
digitalWrite(BIT7, data & 128);
|
||||
|
||||
// after depositing data byte, MCU sets strobe high
|
||||
digitalWrite(MCU_STROBE, HIGH);
|
||||
|
@ -138,3 +167,312 @@ void send_byte_to_cpu(int data) {
|
|||
// wait for CPU to set strobe low
|
||||
wait(CPU_STROBE, LOW);
|
||||
}
|
||||
|
||||
// *********************************************************************************************
|
||||
// *********************************************************************************************
|
||||
// *********************************************************************************************
|
||||
// *********************************************************************************************
|
||||
// *********************************************************************************************
|
||||
// *********************************************************************************************
|
||||
// *********************************************************************************************
|
||||
// *********************************************************************************************
|
||||
|
||||
void setup() {
|
||||
// debug on serial
|
||||
Serial.begin(9600);
|
||||
|
||||
#if USE_SD_H
|
||||
Serial.println(F("SDCARD library: SD.h"));
|
||||
#else // USE_SD_H
|
||||
Serial.println(F("SDCARD library: SDFat.h"));
|
||||
#endif // USE_SD_H
|
||||
|
||||
// initialize SD card
|
||||
if (!SD.begin(SD_CS_PIN)) Serial.println("SD card initialization failed");
|
||||
else Serial.println("SD card initialized");
|
||||
|
||||
// control pins setup
|
||||
pinMode(CPU_STROBE, INPUT);
|
||||
pinMode(MCU_STROBE, OUTPUT);
|
||||
digitalWrite(MCU_STROBE, LOW);
|
||||
|
||||
// data pins setup
|
||||
last_dir = -1; // no previous data direction
|
||||
set_data_port_direction(DIR_INPUT);
|
||||
|
||||
MatchState ms;
|
||||
char buf [100] = { F("The quick brown fox jumps over the lazy wolf") };
|
||||
ms.Target (buf);
|
||||
char result = ms.Match ("f.x");
|
||||
if(result >0) {
|
||||
Serial.println("match!");
|
||||
}
|
||||
}
|
||||
|
||||
const int CMD_READ = 0;
|
||||
const int CMD_WRITE = 1;
|
||||
const int CMD_DIR = 2;
|
||||
|
||||
const int ERR_RESPONSE = 255;
|
||||
const int OK_RESPONSE = 0;
|
||||
|
||||
char filename[64];
|
||||
|
||||
// **************************************************************************************
|
||||
// **************************************************************************************
|
||||
// ********************************* DIR ***********************************************
|
||||
// **************************************************************************************
|
||||
// **************************************************************************************
|
||||
|
||||
void printDirectory(File dir, int numTabs) {
|
||||
|
||||
while (true) {
|
||||
if(TIMEOUT) break;
|
||||
|
||||
File entry = dir.openNextFile();
|
||||
if (! entry) {
|
||||
// no more files
|
||||
break;
|
||||
}
|
||||
|
||||
// indentazione delle sottodirectory
|
||||
for (uint8_t i = 0; i < numTabs; i++) {
|
||||
Serial.print('\t');
|
||||
send_byte_to_cpu(32);
|
||||
send_byte_to_cpu(32);
|
||||
send_byte_to_cpu(32);
|
||||
}
|
||||
|
||||
// nome del file
|
||||
char *msg;
|
||||
#if USE_SD_H
|
||||
msg = entry.name();
|
||||
#else
|
||||
entry.getName(filename, 64);
|
||||
msg = filename;
|
||||
#endif
|
||||
Serial.print(msg);
|
||||
for(int t=0; t<strlen(msg); t++) {
|
||||
send_byte_to_cpu(msg[t]);
|
||||
}
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
Serial.println("/");
|
||||
send_byte_to_cpu('/');
|
||||
send_byte_to_cpu('\r');
|
||||
printDirectory(entry, numTabs + 1);
|
||||
} else {
|
||||
// files have sizes, directories do not
|
||||
Serial.print("\t\t");
|
||||
send_byte_to_cpu(' ');
|
||||
send_byte_to_cpu(' ');
|
||||
|
||||
/*
|
||||
// file size
|
||||
Serial.println(entry.size(), DEC);
|
||||
msg = itoa(entry.size());
|
||||
for(int t=0; t<strlen(msg); t++) {
|
||||
send_byte_to_cpu(msg[t]);
|
||||
}
|
||||
*/
|
||||
send_byte_to_cpu('\r');
|
||||
|
||||
}
|
||||
entry.close();
|
||||
}
|
||||
}
|
||||
|
||||
// **************************************************************************************
|
||||
// **************************************************************************************
|
||||
// ********************************* CMD_READ ******************************************
|
||||
// **************************************************************************************
|
||||
// **************************************************************************************
|
||||
|
||||
void comando_read() {
|
||||
Serial.println("command CMD_READ received from CPU");
|
||||
|
||||
// reads filename as 0 terminated string
|
||||
receive_string_from_cpu(filename);
|
||||
if(TIMEOUT) return;
|
||||
Serial.print("file to read: ");
|
||||
Serial.println(filename);
|
||||
|
||||
if(!SD.exists(filename)) {
|
||||
Serial.println("error opening file");
|
||||
send_byte_to_cpu(ERR_RESPONSE);
|
||||
send_string_to_cpu("?FILE NOT FOUND");
|
||||
return;
|
||||
}
|
||||
|
||||
// open the file
|
||||
File myFile = SD.open(filename);
|
||||
if(!myFile) {
|
||||
Serial.println("error opening file");
|
||||
send_byte_to_cpu(ERR_RESPONSE);
|
||||
send_string_to_cpu("?CAN'T OPEN FILE");
|
||||
return;
|
||||
}
|
||||
Serial.println("file opened on the SD card");
|
||||
|
||||
// ok response
|
||||
send_byte_to_cpu(OK_RESPONSE);
|
||||
if(TIMEOUT) return;
|
||||
Serial.println("ok response sent to CPU");
|
||||
|
||||
// sends size as low and high byte
|
||||
int size = myFile.size();
|
||||
send_byte_to_cpu(size & 0xFF);
|
||||
send_byte_to_cpu((size >> 8) & 0xFF);
|
||||
if(TIMEOUT) return;
|
||||
Serial.println("file size sent to CPU");
|
||||
|
||||
int bytes_sent = 0;
|
||||
while(myFile.available() && !TIMEOUT) {
|
||||
send_byte_to_cpu(myFile.read());
|
||||
if(!TIMEOUT) bytes_sent++;
|
||||
}
|
||||
myFile.close();
|
||||
|
||||
if(TIMEOUT) {
|
||||
Serial.print("timeout, bytes sent: ");
|
||||
Serial.println(bytes_sent);
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.println("file read ok");
|
||||
}
|
||||
|
||||
void send_string_to_cpu(char *msg) {
|
||||
while(1) {
|
||||
int c = *msg++;
|
||||
send_byte_to_cpu(c);
|
||||
if(TIMEOUT) break;
|
||||
if(c==0) break;
|
||||
}
|
||||
}
|
||||
|
||||
void receive_string_from_cpu(char *msg) {
|
||||
while(1) {
|
||||
int c = receive_byte_from_cpu();
|
||||
if(TIMEOUT) break;
|
||||
*msg++ = c;
|
||||
if(c==0) break;
|
||||
}
|
||||
}
|
||||
|
||||
// **************************************************************************************
|
||||
// **************************************************************************************
|
||||
// ********************************* CMD_WRITE *****************************************
|
||||
// **************************************************************************************
|
||||
// **************************************************************************************
|
||||
|
||||
int receive_word_from_cpu() {
|
||||
int lo = receive_byte_from_cpu();
|
||||
int hi = receive_byte_from_cpu();
|
||||
int data = lo | (hi << 8);
|
||||
return data;
|
||||
}
|
||||
|
||||
void comando_write() {
|
||||
Serial.println("command CMD_WRITE received from CPU");
|
||||
|
||||
// reads filename as 0 terminated string
|
||||
receive_string_from_cpu(filename);
|
||||
if(TIMEOUT) return;
|
||||
Serial.print("file to write: ");
|
||||
Serial.println(filename);
|
||||
|
||||
if(SD.exists(filename)) {
|
||||
Serial.println("file already exist");
|
||||
send_byte_to_cpu(ERR_RESPONSE);
|
||||
send_string_to_cpu("?ALREADY EXISTS");
|
||||
return;
|
||||
}
|
||||
|
||||
// open the file
|
||||
File myFile = SD.open(filename, FILE_WRITE);
|
||||
if(!myFile) {
|
||||
Serial.println("error opening file for write");
|
||||
send_byte_to_cpu(ERR_RESPONSE);
|
||||
send_string_to_cpu("?CAN'T CREATE FILE");
|
||||
return;
|
||||
}
|
||||
Serial.println("file opened for write on the SD card");
|
||||
|
||||
// ok response
|
||||
send_byte_to_cpu(OK_RESPONSE);
|
||||
if(TIMEOUT) return;
|
||||
Serial.println("first ok response sent to CPU");
|
||||
|
||||
// get file size low and high byte
|
||||
int size = receive_word_from_cpu();
|
||||
if(TIMEOUT) return;
|
||||
Serial.print("received file size: ");
|
||||
Serial.println(size);
|
||||
|
||||
int error = 0;
|
||||
for(int t=0;t<size;t++) {
|
||||
int data = receive_byte_from_cpu();
|
||||
if(TIMEOUT) break;
|
||||
int n = myFile.write((unsigned char)data);
|
||||
if(n!=1) error = 1;
|
||||
}
|
||||
|
||||
// close the file
|
||||
myFile.close();
|
||||
|
||||
if(TIMEOUT) return;
|
||||
|
||||
// report write issues
|
||||
if(error) {
|
||||
Serial.println("file write error");
|
||||
send_byte_to_cpu(ERR_RESPONSE);
|
||||
if(TIMEOUT) return;
|
||||
send_string_to_cpu("?WRITE ERROR");
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.println("file read ok");
|
||||
send_byte_to_cpu(OK_RESPONSE);
|
||||
}
|
||||
|
||||
// **************************************************************************************
|
||||
// **************************************************************************************
|
||||
// ********************************* LOOP **********************************************
|
||||
// **************************************************************************************
|
||||
// **************************************************************************************
|
||||
|
||||
void loop() {
|
||||
TIMEOUT = 0;
|
||||
|
||||
int data = receive_byte_from_cpu();
|
||||
if(TIMEOUT) return;
|
||||
|
||||
if(data == CMD_READ) {
|
||||
comando_read();
|
||||
if(TIMEOUT) Serial.println("TIMEOUT during CMD_READ");
|
||||
}
|
||||
else if(data == CMD_WRITE) {
|
||||
comando_write();
|
||||
if(TIMEOUT) Serial.println("TIMEOUT during CMD_WRITE");
|
||||
}
|
||||
else if(data == CMD_DIR) {
|
||||
Serial.println("command DIR received from CPU");
|
||||
|
||||
File root = SD.open("/");
|
||||
printDirectory(root, 0);
|
||||
root.close();
|
||||
|
||||
// terminates
|
||||
send_byte_to_cpu(0);
|
||||
|
||||
if(TIMEOUT) Serial.println("TIMEOUT during DIR");
|
||||
|
||||
Serial.println("command DIR ended");
|
||||
}
|
||||
else {
|
||||
Serial.print("unknown command ");
|
||||
Serial.print(data);
|
||||
Serial.println(" received");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
void comando_dir() {
|
||||
send_byte_to_MCU(CMD_DIR);
|
||||
if(TIMEOUT) return;
|
||||
print_string_response();
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
void comando_dump(char *filename, word start, word end) {
|
||||
|
||||
// send command byte
|
||||
send_byte_to_MCU(CMD_READ);
|
||||
if(TIMEOUT) return;
|
||||
|
||||
// send filename
|
||||
send_string_to_MCU(filename);
|
||||
if(TIMEOUT) return;
|
||||
|
||||
// response
|
||||
byte response = receive_byte_from_MCU();
|
||||
if(TIMEOUT) return;
|
||||
|
||||
if(response == ERR_RESPONSE) {
|
||||
// error with file, print message
|
||||
print_string_response();
|
||||
return;
|
||||
}
|
||||
|
||||
// get file length
|
||||
word len = receive_word_from_mcu();
|
||||
if(TIMEOUT) return;
|
||||
|
||||
// 1234567890123456789012345678901234567890
|
||||
// 0000: 00 00 00 00 00 00 00 00
|
||||
|
||||
// get file bytes
|
||||
byte row = 0;
|
||||
for(word t=0;t!=len;t++) {
|
||||
byte data = receive_byte_from_MCU();
|
||||
if(TIMEOUT) return;
|
||||
|
||||
if(!(t>=start && t<=end)) continue;
|
||||
|
||||
if(row == 0) {
|
||||
woz_putc('\r');
|
||||
woz_print_hexword(t);
|
||||
woz_puts(": ");
|
||||
}
|
||||
|
||||
woz_print_hex(data);
|
||||
woz_putc(' ');
|
||||
|
||||
row++;
|
||||
row &= 7;
|
||||
|
||||
if(apple1_readkey()) {
|
||||
woz_puts("*BRK*\r");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
// LOAD: for basic files in prodos format
|
||||
// it is like a normal CMD_READ
|
||||
|
||||
// PRODOS format:
|
||||
// "A","1", 510 bytes low memory, basic program
|
||||
|
||||
void comando_load(char *filename, byte cmd) {
|
||||
|
||||
// send command byte
|
||||
send_byte_to_MCU(CMD_READ);
|
||||
if(TIMEOUT) return;
|
||||
|
||||
// send filename
|
||||
send_string_to_MCU(filename);
|
||||
if(TIMEOUT) return;
|
||||
|
||||
// response
|
||||
byte response = receive_byte_from_MCU();
|
||||
if(TIMEOUT) return;
|
||||
|
||||
if(response == ERR_RESPONSE) {
|
||||
// error with file, print message
|
||||
print_string_response();
|
||||
return;
|
||||
}
|
||||
|
||||
// get file length
|
||||
word len = receive_word_from_mcu();
|
||||
if(TIMEOUT) return;
|
||||
|
||||
// get file bytes
|
||||
byte *dest = (byte *) 0;
|
||||
for(word t=0;t!=len;t++) {
|
||||
byte data = receive_byte_from_MCU();
|
||||
if(TIMEOUT) return;
|
||||
|
||||
if((t==0 && data!=0x41) || (t==1 && data!=0x31)) {
|
||||
woz_puts("?NOT CFFA1/PRODOS FORMAT");
|
||||
return;
|
||||
}
|
||||
else if(t<0x004a) {
|
||||
// skip zone $00-$49
|
||||
}
|
||||
else if(t<0x0100) {
|
||||
// writes in the zone $4a-$ff (BASIC pointers)
|
||||
*dest = data;
|
||||
}
|
||||
else if(t<0x1ff) {
|
||||
// skip zone $100-$1ff (stack)
|
||||
}
|
||||
else if(t==0x1ff) {
|
||||
// basic program chuck follows, move the pointer
|
||||
dest = (byte *) ((*BASIC_LOMEM) -1); // compensate for the increment in the loop
|
||||
}
|
||||
else {
|
||||
// writes in the BASIC program zone
|
||||
*dest = data;
|
||||
}
|
||||
|
||||
dest++;
|
||||
if(((byte)t) == 0) woz_putc('.');
|
||||
}
|
||||
|
||||
// print feedback to user
|
||||
woz_putc('\r');
|
||||
woz_puts(filename);
|
||||
woz_puts(": LOMEM=");
|
||||
woz_print_hexword(*BASIC_LOMEM);
|
||||
woz_puts(" HIMEM=");
|
||||
woz_print_hexword(*BASIC_HIMEM);
|
||||
woz_puts("\rOK");
|
||||
|
||||
// executes basic program $EFEC = RUN entry point
|
||||
if(cmd == CMD_RUN) {
|
||||
woz_putc('\r');
|
||||
asm {
|
||||
jmp $EFEC
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
// READ:
|
||||
// CPU sends CMD_READ + filename as 0 terminated string
|
||||
// MCU sends $00 + 2 bytes file length (MSB first) + file data bytes (if OK)
|
||||
// MCU sends $FF + string error description (if error)
|
||||
//
|
||||
void comando_read(char *filename, word start) {
|
||||
|
||||
// send command byte
|
||||
send_byte_to_MCU(CMD_READ);
|
||||
if(TIMEOUT) return;
|
||||
|
||||
// send filename
|
||||
send_string_to_MCU(filename);
|
||||
if(TIMEOUT) return;
|
||||
|
||||
// response
|
||||
byte response = receive_byte_from_MCU();
|
||||
if(TIMEOUT) return;
|
||||
|
||||
if(response == ERR_RESPONSE) {
|
||||
// error with file, print message
|
||||
print_string_response();
|
||||
return;
|
||||
}
|
||||
|
||||
// get file length
|
||||
word len = receive_word_from_mcu();
|
||||
if(TIMEOUT) return;
|
||||
|
||||
// get file bytes
|
||||
byte *dest = (byte *) start;
|
||||
for(word t=0;t!=len;t++) {
|
||||
byte data = receive_byte_from_MCU();
|
||||
if(TIMEOUT) return;
|
||||
*dest++ = data;
|
||||
if(((byte)t) == 0) woz_putc('.');
|
||||
}
|
||||
|
||||
// print feedback to user
|
||||
woz_putc('\r');
|
||||
woz_puts(filename);
|
||||
woz_puts(": ");
|
||||
woz_print_hexword(start);
|
||||
woz_putc('.');
|
||||
woz_print_hexword(start+len-1);
|
||||
woz_puts(" (");
|
||||
utoa(len, filename, 10); // use filename as string buffer
|
||||
woz_puts(filename);
|
||||
woz_puts(" BYTES)\rOK");
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
void comando_save(char *filename) {
|
||||
|
||||
// send command byte
|
||||
send_byte_to_MCU(CMD_WRITE);
|
||||
if(TIMEOUT) return;
|
||||
|
||||
// send filename
|
||||
send_string_to_MCU(filename);
|
||||
if(TIMEOUT) return;
|
||||
|
||||
// get first response
|
||||
byte response = receive_byte_from_MCU();
|
||||
if(TIMEOUT) return;
|
||||
if(response == ERR_RESPONSE) {
|
||||
// error with file, print message
|
||||
print_string_response();
|
||||
return;
|
||||
}
|
||||
|
||||
// send file size
|
||||
word len = ((word) *BASIC_HIMEM) - ((word)*BASIC_LOMEM) + 512;
|
||||
send_word_to_mcu(len);
|
||||
if(TIMEOUT) return;
|
||||
|
||||
// send actual bytes
|
||||
|
||||
// "A1" header
|
||||
send_byte_to_MCU('A');
|
||||
send_byte_to_MCU('1');
|
||||
if(TIMEOUT) return;
|
||||
|
||||
// lowmem + stack chuck
|
||||
for(byte *ptr=(byte *)2; ptr<=(byte *)0x1ff; ptr++) {
|
||||
send_byte_to_MCU(*ptr);
|
||||
if(TIMEOUT) return;
|
||||
}
|
||||
|
||||
// basic data
|
||||
for(word ptr=*BASIC_LOMEM; ptr<*BASIC_HIMEM; ptr++) {
|
||||
send_byte_to_MCU(*((byte *)ptr));
|
||||
if(TIMEOUT) return;
|
||||
if(((byte)ptr) == 0) woz_putc('.');
|
||||
}
|
||||
|
||||
// get second response
|
||||
response = receive_byte_from_MCU();
|
||||
if(TIMEOUT) return;
|
||||
if(response == ERR_RESPONSE) {
|
||||
// error with file, print message
|
||||
print_string_response();
|
||||
return;
|
||||
}
|
||||
|
||||
// print feedback to user
|
||||
woz_putc('\r');
|
||||
woz_puts(filename);
|
||||
woz_puts(": LOMEM=");
|
||||
woz_print_hexword(*BASIC_LOMEM);
|
||||
woz_puts(" HIMEM=");
|
||||
woz_print_hexword(*BASIC_HIMEM);
|
||||
woz_puts("\rOK");
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
void comando_type(char *filename) {
|
||||
|
||||
// send command byte
|
||||
send_byte_to_MCU(CMD_READ);
|
||||
if(TIMEOUT) return;
|
||||
|
||||
// send filename
|
||||
send_string_to_MCU(filename);
|
||||
if(TIMEOUT) return;
|
||||
|
||||
// response
|
||||
byte response = receive_byte_from_MCU();
|
||||
if(TIMEOUT) return;
|
||||
|
||||
if(response == ERR_RESPONSE) {
|
||||
// error with file, print message
|
||||
print_string_response();
|
||||
return;
|
||||
}
|
||||
|
||||
// get file length
|
||||
word len = receive_word_from_mcu();
|
||||
if(TIMEOUT) return;
|
||||
|
||||
// get file bytes
|
||||
for(word t=0;t!=len;t++) {
|
||||
byte data = receive_byte_from_MCU();
|
||||
if(TIMEOUT) return;
|
||||
woz_putc(data);
|
||||
if(apple1_readkey()) {
|
||||
woz_puts("*BRK*\r");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
void comando_write(char *filename, word start, word end) {
|
||||
|
||||
// send command byte
|
||||
send_byte_to_MCU(CMD_WRITE);
|
||||
if(TIMEOUT) return;
|
||||
|
||||
// send filename
|
||||
send_string_to_MCU(filename);
|
||||
if(TIMEOUT) return;
|
||||
|
||||
// get first response
|
||||
byte response = receive_byte_from_MCU();
|
||||
if(TIMEOUT) return;
|
||||
if(response == ERR_RESPONSE) {
|
||||
// error with file, print message
|
||||
print_string_response();
|
||||
return;
|
||||
}
|
||||
|
||||
// send file size
|
||||
word len = end-start + 1;
|
||||
send_word_to_mcu(len);
|
||||
if(TIMEOUT) return;
|
||||
|
||||
// send actual bytes
|
||||
byte *ptr = (byte *) start;
|
||||
for(word t=0;t<len;t++) {
|
||||
send_byte_to_MCU(*ptr++);
|
||||
if(TIMEOUT) return;
|
||||
if(((byte)t) == 0) woz_putc('.');
|
||||
}
|
||||
|
||||
// get second response
|
||||
response = receive_byte_from_MCU();
|
||||
if(TIMEOUT) return;
|
||||
if(response == ERR_RESPONSE) {
|
||||
// error with file, print message
|
||||
print_string_response();
|
||||
return;
|
||||
}
|
||||
|
||||
// print feedback to user
|
||||
woz_putc('\r');
|
||||
woz_puts(filename);
|
||||
woz_puts(": ");
|
||||
woz_print_hexword(start);
|
||||
woz_putc('.');
|
||||
woz_print_hexword(end);
|
||||
woz_puts(" (");
|
||||
utoa(len, filename, 10); // use filename as string buffer
|
||||
woz_puts(filename);
|
||||
woz_puts(" BYTES)\rOK");
|
||||
}
|
|
@ -0,0 +1,257 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
word *const BASIC_LOMEM = (word *) 0x004a; // lomem pointer used by integer BASIC
|
||||
word *const BASIC_HIMEM = (word *) 0x004c; // himem pointer used by integer BASIC
|
||||
byte *const KEYBUF = (byte *) 0x0200; // use the same keyboard buffer as in WOZ monitor
|
||||
|
||||
#define KEYBUFSTART (0x200)
|
||||
#define KEYBUFLEN (40)
|
||||
|
||||
// keyboard buffer 0x200-27F uses only the first 40 bytes, the rest is recycled for free mem
|
||||
|
||||
byte *const command = (byte *) (KEYBUFSTART+KEYBUFLEN ); // [6] stores a 5 character command
|
||||
byte *const filename = (byte *) (KEYBUFSTART+KEYBUFLEN+6 ); // [33] stores a filename or pattern
|
||||
byte *const hex1 = (byte *) (KEYBUFSTART+KEYBUFLEN+6+33 ); // [5] stores a hex parameter
|
||||
byte *const hex2 = (byte *) (KEYBUFSTART+KEYBUFLEN+6+33+5); // [5] stores a hex parameter
|
||||
|
||||
const byte ERR_RESPONSE = 0xFF;
|
||||
|
||||
// command constants, which are also byte commands to send to the MCU
|
||||
const byte CMD_READ = 0;
|
||||
const byte CMD_WRITE = 1;
|
||||
const byte CMD_DIR = 2;
|
||||
const byte CMD_TIME = 3;
|
||||
const byte CMD_LOAD = 4;
|
||||
const byte CMD_RUN = 5;
|
||||
const byte CMD_SAVE = 6;
|
||||
const byte CMD_TYPE = 7;
|
||||
const byte CMD_DUMP = 8;
|
||||
const byte CMD_EXIT = 9;
|
||||
|
||||
// the list of recognized commands
|
||||
byte *DOS_COMMANDS[] = {
|
||||
"READ",
|
||||
"WRITE",
|
||||
"DIR",
|
||||
"TIME",
|
||||
"LOAD",
|
||||
"RUN",
|
||||
"SAVE",
|
||||
"TYPE",
|
||||
"DUMP",
|
||||
"EXIT"
|
||||
};
|
||||
|
||||
// parse a string, get the first string delimited by space or end of string
|
||||
// returns the parsed string in dest
|
||||
// returns the number of character to advance the pointer
|
||||
// leading and trailing spaces are ignored
|
||||
// max is the (maximum) size of dest
|
||||
byte get_token(byte *source, byte *dest, byte max) {
|
||||
byte i = 0;
|
||||
byte j = 0;
|
||||
byte first_char_found = 0;
|
||||
|
||||
while(1) {
|
||||
byte c = source[i];
|
||||
if(c == 0) {
|
||||
break;
|
||||
}
|
||||
else if(c == 32) {
|
||||
if(first_char_found) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
first_char_found = 1;
|
||||
dest[j++] = c;
|
||||
}
|
||||
if(j<max) i++;
|
||||
else break;
|
||||
}
|
||||
dest[j] = 0;
|
||||
return i+1;
|
||||
}
|
||||
|
||||
// returns the command code or 0xff if not recognized
|
||||
byte find_command() {
|
||||
for(byte cmd=0; cmd<sizeof(DOS_COMMANDS); cmd++) {
|
||||
if(strcmp(command, DOS_COMMANDS[cmd]) == 0) return cmd;
|
||||
}
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
// converts the hexadecimal string argument to 16 bit word
|
||||
byte hex_to_word_ok;
|
||||
word hex_to_word(byte *str) {
|
||||
hex_to_word_ok = 1;
|
||||
word res=0;
|
||||
byte c;
|
||||
byte i;
|
||||
for(i=0; c=str[i]; ++i) {
|
||||
res = res << 4;
|
||||
if(c>='0' && c<='9') res += (c-'0');
|
||||
else if(c>='A' && c<='F') res += (c-65)+0x0A;
|
||||
else hex_to_word_ok = 0;
|
||||
}
|
||||
if(i>4 || i==0) hex_to_word_ok = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
#include "cmd_read.h"
|
||||
#include "cmd_write.h"
|
||||
#include "cmd_load.h"
|
||||
#include "cmd_save.h"
|
||||
#include "cmd_type.h"
|
||||
#include "cmd_dump.h"
|
||||
#include "cmd_dir.h"
|
||||
|
||||
void console() {
|
||||
|
||||
VIA_init();
|
||||
|
||||
// 1234567890123456789012345678901234567890
|
||||
woz_puts("\rREAD,WRITE,LOAD,RUN,SAVE,TYPE,DUMP,DIR\r"
|
||||
"TIME,EXIT\r");
|
||||
|
||||
woz_puts("\rSD CARD DOS 1.0\r");
|
||||
|
||||
// main loop
|
||||
while(1) {
|
||||
|
||||
// clear input buffer
|
||||
for(byte i=0; i<KEYBUFLEN; i++) KEYBUF[i] = 0;
|
||||
|
||||
// input from keyboard
|
||||
woz_puts("\r]");
|
||||
apple1_input_line(KEYBUF, KEYBUFLEN);
|
||||
woz_putc('\r');
|
||||
|
||||
// decode command
|
||||
byte *ptr = KEYBUF;
|
||||
ptr += get_token(ptr, command, 5);
|
||||
byte cmd = find_command();
|
||||
|
||||
if(cmd == CMD_READ) {
|
||||
ptr += get_token(ptr, filename, 32); // parse filename
|
||||
if(filename[0] == 0) {
|
||||
woz_puts("?MISSING FILENAME");
|
||||
continue;
|
||||
}
|
||||
|
||||
ptr += get_token(ptr, hex1, 4); // parse hex start address
|
||||
word start = hex_to_word(hex1);
|
||||
if(!hex_to_word_ok) {
|
||||
woz_puts("?BAD ADDRESS");
|
||||
continue;
|
||||
}
|
||||
comando_read(filename, start);
|
||||
}
|
||||
else if(cmd == CMD_WRITE) {
|
||||
// parse filename
|
||||
ptr += get_token(ptr, filename, 32);
|
||||
if(filename[0] == 0) {
|
||||
woz_puts("?MISSING FILENAME");
|
||||
continue;
|
||||
}
|
||||
|
||||
// parse hex start address
|
||||
ptr += get_token(ptr, hex1, 4);
|
||||
word start = hex_to_word(hex1);
|
||||
if(!hex_to_word_ok) {
|
||||
woz_puts("?BAD ADDRESS");
|
||||
continue;
|
||||
}
|
||||
|
||||
// parse hex end address
|
||||
ptr += get_token(ptr, hex2, 4);
|
||||
word end = hex_to_word(hex2);
|
||||
if(!hex_to_word_ok) {
|
||||
woz_puts("?BAD ADDRESS");
|
||||
continue;
|
||||
}
|
||||
|
||||
comando_write(filename, start, end);
|
||||
}
|
||||
else if(cmd == CMD_DIR) {
|
||||
comando_dir();
|
||||
}
|
||||
else if(cmd == CMD_TIME) {
|
||||
ptr += get_token(ptr, hex1, 4); // parse hex timeout value
|
||||
if(strlen(hex1)!=0) {
|
||||
TIMEOUT_MAX = hex_to_word(hex1);
|
||||
if(!hex_to_word_ok) {
|
||||
woz_puts("?BAD ARGUMENT");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
woz_puts("TIMEOUT_MAX: ");
|
||||
woz_print_hexword(TIMEOUT_MAX);
|
||||
}
|
||||
else if(cmd == CMD_LOAD || cmd == CMD_RUN) {
|
||||
ptr += get_token(ptr, filename, 32); // parse filename
|
||||
if(filename[0] == 0) {
|
||||
woz_puts("?MISSING FILENAME");
|
||||
continue;
|
||||
}
|
||||
comando_load(filename, cmd);
|
||||
}
|
||||
else if(cmd == CMD_SAVE) {
|
||||
ptr += get_token(ptr, filename, 32); // parse filename
|
||||
if(filename[0] == 0) {
|
||||
woz_puts("?MISSING FILENAME");
|
||||
continue;
|
||||
}
|
||||
comando_save(filename);
|
||||
}
|
||||
else if(cmd == CMD_TYPE) {
|
||||
ptr += get_token(ptr, filename, 32); // parse filename
|
||||
if(filename[0] == 0) {
|
||||
woz_puts("?MISSING FILENAME");
|
||||
continue;
|
||||
}
|
||||
comando_type(filename);
|
||||
}
|
||||
else if(cmd == CMD_DUMP) {
|
||||
ptr += get_token(ptr, filename, 32); // parse filename
|
||||
if(filename[0] == 0) {
|
||||
woz_puts("?MISSING FILENAME");
|
||||
continue;
|
||||
}
|
||||
|
||||
// parse hex start address
|
||||
ptr += get_token(ptr, hex1, 4);
|
||||
word start = hex_to_word(hex1);
|
||||
if(!hex_to_word_ok) {
|
||||
woz_puts("?BAD ADDRESS");
|
||||
continue;
|
||||
}
|
||||
|
||||
// parse hex end address
|
||||
ptr += get_token(ptr, hex2, 4);
|
||||
word end = hex_to_word(hex2);
|
||||
if(!hex_to_word_ok) {
|
||||
woz_puts("?BAD ADDRESS");
|
||||
continue;
|
||||
}
|
||||
if(end<start) end = 0xFFFF;
|
||||
comando_dump(filename, start, end);
|
||||
}
|
||||
else if(cmd == CMD_EXIT) {
|
||||
woz_puts("BYE\r");
|
||||
woz_mon();
|
||||
}
|
||||
else {
|
||||
if(strlen(command)!=0) {
|
||||
woz_puts(command);
|
||||
woz_puts("??");
|
||||
}
|
||||
}
|
||||
|
||||
if(TIMEOUT) {
|
||||
woz_puts("?I/O ERROR");
|
||||
TIMEOUT = 0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,40 @@
|
|||
// TODO comando CD
|
||||
// TODO comando MKDIR
|
||||
// TODO comando RMDIR
|
||||
// TODO comando DEL
|
||||
// TODO comando REN
|
||||
// TODO comando COPY
|
||||
// TODO comando JMP
|
||||
// TODO comando RUN a vuoto
|
||||
// TODO questione del puntino che va in timeout
|
||||
|
||||
#define APPLE1_USE_WOZ_MONITOR 1
|
||||
|
||||
#pragma start_address(0x8000)
|
||||
|
||||
#pragma zp_reserve(0x4a)
|
||||
#pragma zp_reserve(0x4b)
|
||||
#pragma zp_reserve(0x4c)
|
||||
#pragma zp_reserve(0x4d)
|
||||
#pragma zp_reserve(0x4e)
|
||||
#pragma zp_reserve(0x4f)
|
||||
|
||||
#pragma zp_reserve(0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f)
|
||||
#pragma zp_reserve(0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f)
|
||||
#pragma zp_reserve(0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f)
|
||||
#pragma zp_reserve(0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f)
|
||||
#pragma zp_reserve(0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f)
|
||||
#pragma zp_reserve(0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f)
|
||||
#pragma zp_reserve(0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf)
|
||||
#pragma zp_reserve(0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf)
|
||||
#pragma zp_reserve(0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf)
|
||||
#pragma zp_reserve(0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf)
|
||||
#pragma zp_reserve(0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef)
|
||||
#pragma zp_reserve(0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff)
|
||||
|
||||
#include <utils.h>
|
||||
#include <apple1.h>
|
||||
#include <string.h>
|
||||
|
||||
byte *const PORTB = (byte *) 0xA000; // port B register
|
||||
byte *const PORTA = (byte *) 0xA001; // port A register
|
||||
|
@ -9,19 +44,21 @@ byte *const DDRA = (byte *) 0xA003; // port B data direction register
|
|||
#define CPU_STROBE(v) (*PORTB = (v)) /* CPU strobe is bit 0 OUTPUT */
|
||||
#define MCU_STROBE (*PORTB & 128) /* MCU strobe is bit 7 INPUT */
|
||||
|
||||
byte TIMEOUT = 0;
|
||||
__address(3) byte TIMEOUT;
|
||||
__address(4) word TIMEOUT_MAX = 0x1388;
|
||||
__address(6) word TIMEOUT_CNT;
|
||||
|
||||
void wait_mcu_strobe(byte v) {
|
||||
if(TIMEOUT) return;
|
||||
|
||||
unsigned int time = 0;
|
||||
TIMEOUT_CNT = 0;
|
||||
while((v==0 && MCU_STROBE != 0) || (v!=0 && MCU_STROBE == 0)) {
|
||||
time++;
|
||||
if(time > 5000) {
|
||||
TIMEOUT_CNT++;
|
||||
if(TIMEOUT_CNT > TIMEOUT_MAX) {
|
||||
TIMEOUT = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void send_byte_to_MCU(byte data) {
|
||||
|
@ -33,6 +70,7 @@ void send_byte_to_MCU(byte data) {
|
|||
wait_mcu_strobe(0); // wait for the MCU to set strobe low
|
||||
}
|
||||
|
||||
// note: allocates 1 byte for return value
|
||||
byte receive_byte_from_MCU() {
|
||||
*DDRA = 0; // set port A as input
|
||||
CPU_STROBE(0); // set listen
|
||||
|
@ -49,47 +87,45 @@ void VIA_init() {
|
|||
CPU_STROBE(0); // initial state
|
||||
}
|
||||
|
||||
void messagio_test() {
|
||||
|
||||
TIMEOUT = 0; // resetta il timeout
|
||||
send_byte_to_MCU(42); // manda il comando 42
|
||||
|
||||
if(TIMEOUT) {
|
||||
woz_puts("\rTIMEOUT\r");
|
||||
return;
|
||||
// send a string to the MCY (0 terminator is sent as well)
|
||||
void send_string_to_MCU(char *msg) {
|
||||
while(1) {
|
||||
byte data = *msg++;
|
||||
send_byte_to_MCU(data);
|
||||
if(TIMEOUT) break;
|
||||
if(data == 0) break;
|
||||
}
|
||||
}
|
||||
|
||||
// legge la stringa di ritorno
|
||||
// print a string sent by the MCU
|
||||
void print_string_response() {
|
||||
while(1) {
|
||||
byte data = receive_byte_from_MCU();
|
||||
if(TIMEOUT) {
|
||||
woz_puts("\rTIMEOUT\r");
|
||||
break;
|
||||
}
|
||||
if(data == 0) break; // end of string
|
||||
woz_putc(data);
|
||||
if(TIMEOUT) break;
|
||||
if(data == 0) break; // string terminator
|
||||
else woz_putc(data);
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
|
||||
VIA_init();
|
||||
|
||||
woz_puts("\rMCU TEST\r\r");
|
||||
woz_puts("[4] SEND 42 TO MCU\r");
|
||||
woz_puts("[0] EXIT\r");
|
||||
|
||||
byte data;
|
||||
|
||||
// loop continuo
|
||||
while(1) {
|
||||
byte key = apple1_getkey();
|
||||
|
||||
if(key == '4') messagio_test();
|
||||
else if(key == '0') {
|
||||
woz_puts("BYE\r");
|
||||
woz_mon();
|
||||
}
|
||||
}
|
||||
word receive_word_from_mcu() {
|
||||
word data;
|
||||
*((byte *)&data) = receive_byte_from_MCU();
|
||||
*((byte *)(&data+1)) = receive_byte_from_MCU();
|
||||
return data;
|
||||
}
|
||||
|
||||
void send_word_to_mcu(word data) {
|
||||
send_byte_to_MCU( *((byte *)&data) );
|
||||
send_byte_to_MCU( *((byte *)(&data+1)) );
|
||||
}
|
||||
|
||||
#include "console.h"
|
||||
|
||||
void main() {
|
||||
//#ifdef APPLE1_JUKEBOX
|
||||
// apple1_eprom_init();
|
||||
//#endif
|
||||
|
||||
console();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue