mirror of
https://github.com/nippur72/apple1-videocard-lib.git
synced 2024-06-18 03:29:27 +00:00
Compare commits
12 Commits
1ae7ed5ac5
...
7dec136a98
Author | SHA1 | Date | |
---|---|---|---|
|
7dec136a98 | ||
|
823f21ea26 | ||
|
6a8d18e89d | ||
|
51bd39ac8c | ||
|
c795bc7946 | ||
|
cfce31a8b0 | ||
|
6269887461 | ||
|
cf126ede50 | ||
|
9e0651061c | ||
|
ae4f61cf28 | ||
|
7852ff37c2 | ||
|
a2105f88c6 |
|
@ -12,12 +12,14 @@ indicates the file type (two characters) and the hex loading address (4 characte
|
|||
|
||||
`#06` for plain binary files
|
||||
`#F1` for BASIC programs
|
||||
`#F8` for Applesoft BASIC lite programs
|
||||
|
||||
E.g.:
|
||||
`BASIC#06E000` is binary file named `BASIC` that loads at address `$E000`.
|
||||
`STARTREK#F10300` is a BASIC program named `STARTREK` that loads at address `$0300`.
|
||||
`LEMO#F80801` is a AppleSoft BASIC program named `LEMO` that loads at address `$0801`.
|
||||
|
||||
Tagged file names are used by the `LOAD`, `RUN`, `SAVE` and `DIR` commands to simplify working with files. For example to execute the above files, it's enough to type:
|
||||
Tagged file names are used by the `LOAD`, `RUN`, `SAVE`, `ASAVE` and `DIR` commands to simplify working with files. For example to execute the above files, it's enough to type:
|
||||
|
||||
```
|
||||
LOAD BASIC
|
||||
|
@ -51,6 +53,10 @@ RUN STARTREK
|
|||
Saves a file to the SD card. If `start` and `end` are specified, a binary file with tag `#06` will be created with the memory content from the address range `start`-`end` (included).
|
||||
If `start` and `end` are not specified, the BASIC program currently loaded in memory will be created with the corresponding `#F1` tag.
|
||||
|
||||
`ASAVE filename`
|
||||
|
||||
Saves a AppleSoft BASIC lite file to the SD card. The program currently loaded in memory will be created with the corresponding `#F8` tag.
|
||||
|
||||
`RUN filename`
|
||||
|
||||
Same as `LOAD` but runs the file after loading it. Binary files are exectuted at the starting address specified in the file name tag; BASIC files are `RUN` from the BASIC interpreter.
|
||||
|
@ -87,9 +93,14 @@ RUN STARTREK
|
|||
|
||||
Prints `LOMEM` and `HIMEM` pointers from the BASIC program currently loaded in memory.
|
||||
|
||||
`JMP address`
|
||||
`address R`
|
||||
|
||||
Makes the CPU jump at the specified address.
|
||||
Runs the program loaded at the specified memory address. Useful addresses:
|
||||
`6000R` AppleSoft BASIC cold start (needed at least once)
|
||||
`6003R` AppleSoft BASIC warm start (do not destroy the BASIC program in RAM)
|
||||
`E000R` Integer BASIC cold start
|
||||
`EFECR` Integer BASIC "RUN" command (can be used as a warm entry point)
|
||||
`8000R` SD card OS command prompt
|
||||
|
||||
`TIME value`
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ in Verilog syntax: data = { PORTB[1:0], PORTD[7:2] };
|
|||
|
||||
*/
|
||||
|
||||
// FASTWRITE not working (yet)
|
||||
// #define FASTWRITE 1
|
||||
|
||||
#ifdef FASTWRITE
|
||||
|
@ -46,9 +47,6 @@ in Verilog syntax: data = { PORTB[1:0], PORTD[7:2] };
|
|||
#define set_mcu_strobe(c) digitalWrite(MCU_STROBE,(c))
|
||||
#endif
|
||||
|
||||
|
||||
// #include <Regexp.h>
|
||||
|
||||
#include <SPI.h>
|
||||
#include "SdFat.h"
|
||||
|
||||
|
@ -218,6 +216,7 @@ const byte CMD_MKDIR = 14;
|
|||
const byte CMD_PWD = 19;
|
||||
const byte CMD_RMDIR = 15;
|
||||
const byte CMD_TEST = 20;
|
||||
const byte CMD_MOUNT = 23;
|
||||
|
||||
const byte ERR_RESPONSE = 255;
|
||||
const byte WAIT_RESPONSE = 1;
|
||||
|
@ -229,6 +228,7 @@ char tmp[32];
|
|||
char cd_path[64];
|
||||
|
||||
// fixed messages
|
||||
const char *NOT_A_FILE = "?NOT A FILE";
|
||||
const char *FILE_NOT_FOUND = "?FILE NOT FOUND";
|
||||
const char *CANT_OPEN_FILE = "?CAN'T OPEN FILE";
|
||||
const char *ALREADY_EXISTS = "?FILE ALREADY EXISTS";
|
||||
|
@ -244,6 +244,8 @@ const char *CANT_MAKE_DIR = "?CAN'T MAKE DIR";
|
|||
const char *DIR_CREATED = " (DIR) CREATED";
|
||||
const char *CANT_CD_DIR = "?CAN'T CHANGE DIR";
|
||||
const char *NOT_A_DIRECTORY = "?NOT A DIRECTORY";
|
||||
const char *MOUNT_OK = "MOUNTING SDCARD...\rOK";
|
||||
const char *MOUNT_FAILED = "?SD CARD ERROR";
|
||||
|
||||
// file structures used to operate with the SD card
|
||||
File myFile;
|
||||
|
@ -254,9 +256,7 @@ void setup() {
|
|||
Serial.begin(9600);
|
||||
Serial.println(F("SDCARD library: SDFat.h"));
|
||||
|
||||
// initialize SD card
|
||||
if (!SD.begin(SD_CS_PIN)) Serial.println(F("SD card initialization failed"));
|
||||
else Serial.println(F("SD card initialized"));
|
||||
mount_sdcard();
|
||||
|
||||
// control pins setup
|
||||
pinMode(CPU_STROBE, INPUT);
|
||||
|
@ -267,21 +267,21 @@ void setup() {
|
|||
last_dir = -1; // no previous data direction
|
||||
set_data_port_direction(DIR_INPUT);
|
||||
|
||||
/*
|
||||
// regex disabled for now
|
||||
MatchState ms;
|
||||
char buf [100] = { "The quick " };
|
||||
ms.Target (buf);
|
||||
char result = ms.Match ("f.x");
|
||||
if(result >0) {
|
||||
Serial.println("match!");
|
||||
}
|
||||
*/
|
||||
|
||||
// set working directory to root
|
||||
strcpy(cd_path, "/");
|
||||
}
|
||||
|
||||
bool mount_sdcard() {
|
||||
// initialize SD card
|
||||
if(!SD.begin(SD_CS_PIN)) {
|
||||
Serial.println(F("SD card initialization failed"));
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
Serial.println(F("SD card initialized"));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// **************************************************************************************
|
||||
// **************************************************************************************
|
||||
|
@ -419,8 +419,15 @@ void send_directory_entry(byte command) {
|
|||
strcpy(type,"BAS ");
|
||||
strcpy(address,x+2);
|
||||
}
|
||||
else if(x[0]=='F' && x[1]=='8') {
|
||||
strcpy(type,"ASB ");
|
||||
strcpy(address,x+2);
|
||||
}
|
||||
else {
|
||||
strcpy(type,"??? ");
|
||||
type[0] = '#';
|
||||
type[1] = x[0];
|
||||
type[2] = x[1];
|
||||
strcpy(address,x+2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -477,6 +484,15 @@ void comando_read() {
|
|||
send_string_to_cpu(CANT_OPEN_FILE);
|
||||
return;
|
||||
}
|
||||
|
||||
if(myFile.isDirectory()) {
|
||||
myFile.close();
|
||||
Serial.println(F("not a file"));
|
||||
send_byte_to_cpu(ERR_RESPONSE);
|
||||
send_string_to_cpu(NOT_A_FILE);
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.println(F("file opened on the SD card"));
|
||||
|
||||
// ok response
|
||||
|
@ -649,6 +665,15 @@ void comando_load() {
|
|||
send_string_to_cpu(CANT_OPEN_FILE);
|
||||
return;
|
||||
}
|
||||
|
||||
if(myFile.isDirectory()) {
|
||||
myFile.close();
|
||||
Serial.println(F("not a file"));
|
||||
send_byte_to_cpu(ERR_RESPONSE);
|
||||
send_string_to_cpu(NOT_A_FILE);
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.println(F("file opened on the SD card"));
|
||||
|
||||
// ok response
|
||||
|
@ -775,11 +800,11 @@ byte matchname(char *filename, char *dest) {
|
|||
Serial.println(dest);
|
||||
|
||||
// verify the match
|
||||
int len = strlen(filename);
|
||||
int len = strlen(file_name);
|
||||
bool match_found = strncmp(file_name, dest, len) == 0;
|
||||
|
||||
// enforce exact match
|
||||
if(scanmode == 0) match_found = match_found && dest[strlen(filename)] == '#';
|
||||
if(scanmode == 0) match_found = match_found && dest[strlen(file_name)] == '#';
|
||||
|
||||
if(match_found) {
|
||||
if(scanmode==0) Serial.println(F("found an exact match"));
|
||||
|
@ -794,6 +819,9 @@ byte matchname(char *filename, char *dest) {
|
|||
strcpy(filename, dest);
|
||||
if(file_path[0]=='/' && file_path[1]==0) sprintf(dest,"/%s", filename); // case of root folder
|
||||
else sprintf(dest,"%s/%s", file_path, filename); // case of normal nested folder
|
||||
//Serial.println(filename);
|
||||
//Serial.println(file_path);
|
||||
//Serial.println(dest);
|
||||
}
|
||||
myDir.close();
|
||||
return 1;
|
||||
|
@ -1067,6 +1095,11 @@ void loop() {
|
|||
send_byte_to_cpu(data ^ 0xFF);
|
||||
}
|
||||
}
|
||||
else if(data == CMD_MOUNT) {
|
||||
bool mount = mount_sdcard();
|
||||
if(mount) send_string_to_cpu(MOUNT_OK);
|
||||
else send_string_to_cpu(MOUNT_FAILED);
|
||||
}
|
||||
else {
|
||||
Serial.print(F("unknown command "));
|
||||
Serial.print(data);
|
||||
|
|
23
demos/sdcard/cmd_asave.h
Normal file
23
demos/sdcard/cmd_asave.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
// AppleSoft BASIC lite definitions
|
||||
|
||||
word const *TXTTAB = (word *) 0x0067;
|
||||
word const *VARTAB = (word *) 0x0069;
|
||||
word const *PRGEND = (word *) 0x00AF;
|
||||
|
||||
void comando_asave() {
|
||||
VIA_init(); // needed when called from Applesoft basic after a RESET
|
||||
|
||||
woz_puts("SAVING\r");
|
||||
|
||||
// appends #F8 + start address (normally: "0801")
|
||||
tmpword = (word) *TXTTAB;
|
||||
strcat(filename, "#F8");
|
||||
append_hex_tmpword(filename);
|
||||
|
||||
// launches a normal file write from start_address to end_address
|
||||
start_address = (word) *TXTTAB;
|
||||
end_address = (word) *PRGEND;
|
||||
end_address--;
|
||||
|
||||
comando_write();
|
||||
}
|
|
@ -16,12 +16,12 @@ void comando_help() {
|
|||
}
|
||||
}
|
||||
|
||||
// builds the name of the help file
|
||||
strcpy((char *)KEYBUFSTART, "/HELP/");
|
||||
strcat((char *)KEYBUFSTART, filename);
|
||||
strcat((char *)KEYBUFSTART, ".TXT");
|
||||
// builds the name of the help file using the input buffer as buffer
|
||||
strcpy(KEYBUF, "/HELP/");
|
||||
strcat(KEYBUF, filename);
|
||||
strcat(KEYBUF, ".TXT");
|
||||
|
||||
strcpy(filename, (char *)KEYBUFSTART);
|
||||
strcpy(filename, KEYBUF);
|
||||
|
||||
comando_type();
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
// global cmd
|
||||
|
||||
void comando_load_bas() {
|
||||
VIA_init(); // needed when called from Applesoft basic after a RESET
|
||||
|
||||
// send command byte
|
||||
send_byte_to_MCU(CMD_LOAD);
|
||||
|
@ -41,13 +42,14 @@ void comando_load_bas() {
|
|||
if(*token_ptr == '#') {
|
||||
if(token_ptr[1] == '0' && token_ptr[2] == '6') { filetype = 0x06; break; }
|
||||
if(token_ptr[1] == 'F' && token_ptr[2] == '1') { filetype = 0xF1; break; }
|
||||
if(token_ptr[1] == 'F' && token_ptr[2] == '8') { filetype = 0xF8; break; }
|
||||
}
|
||||
if(*token_ptr == 0) break;
|
||||
token_ptr++;
|
||||
}
|
||||
|
||||
// calculate start address for 0x06 binary file
|
||||
if(filetype == 0x06) {
|
||||
if(filetype == 0x06 || filetype == 0xF8) {
|
||||
token_ptr+=2;
|
||||
hex_to_word(token_ptr);
|
||||
start_address = tmpword;
|
||||
|
@ -57,7 +59,7 @@ void comando_load_bas() {
|
|||
receive_word_from_mcu();
|
||||
if(TIMEOUT) return;
|
||||
|
||||
if(filetype != 0x06 && filetype != 0xF1) {
|
||||
if(filetype == 0) {
|
||||
woz_puts("?INVALID FILE NAME TAG #");
|
||||
for(word t=0;t!=tmpword;t++) receive_byte_from_MCU(); // empty buffer
|
||||
return;
|
||||
|
@ -74,10 +76,6 @@ void comando_load_bas() {
|
|||
byte data = receive_byte_from_MCU();
|
||||
if(TIMEOUT) return;
|
||||
*token_ptr++ = data;
|
||||
|
||||
#ifdef LOADING_DOTS
|
||||
if(((byte)t) == 0) woz_putc('.');
|
||||
#endif
|
||||
}
|
||||
|
||||
// decrease by one for display result
|
||||
|
@ -107,6 +105,49 @@ void comando_load_bas() {
|
|||
return;
|
||||
}
|
||||
|
||||
if(filetype == 0xF8) {
|
||||
// 0xF8 APPLESOFT BASIC LITE
|
||||
|
||||
*TXTTAB = start_address;
|
||||
|
||||
// get file bytes
|
||||
token_ptr = (byte *) start_address;
|
||||
for(word t=0;t!=tmpword;t++) {
|
||||
byte data = receive_byte_from_MCU();
|
||||
if(TIMEOUT) return;
|
||||
*token_ptr++ = data;
|
||||
}
|
||||
|
||||
*VARTAB = (word) token_ptr;
|
||||
*PRGEND = (word) token_ptr;
|
||||
|
||||
// decrease by one for display result
|
||||
token_ptr--;
|
||||
|
||||
// print feedback to user
|
||||
woz_putc('\r');
|
||||
woz_puts(filename);
|
||||
woz_puts("\r$");
|
||||
woz_print_hexword(start_address);
|
||||
woz_puts("-$");
|
||||
woz_print_hexword((word)token_ptr);
|
||||
woz_puts(" (");
|
||||
utoa(tmpword, filename, 10); // use filename as string buffer
|
||||
woz_puts(filename);
|
||||
woz_puts(" BYTES)\rOK");
|
||||
|
||||
// executes machine language program at start address
|
||||
//if(cmd == CMD_RUN) {
|
||||
// woz_putc('\r');
|
||||
// tmpword = start_address;
|
||||
// asm {
|
||||
// jmp (tmpword)
|
||||
// }
|
||||
//}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// 0xF1 BASIC FILE TYPE
|
||||
|
||||
// get file bytes
|
||||
|
@ -142,9 +183,6 @@ void comando_load_bas() {
|
|||
}
|
||||
|
||||
token_ptr++;
|
||||
#ifdef LOADING_DOTS
|
||||
if(((byte)t) == 0) woz_putc('.');
|
||||
#endif
|
||||
}
|
||||
|
||||
bas_file_info();
|
||||
|
|
8
demos/sdcard/cmd_mount.h
Normal file
8
demos/sdcard/cmd_mount.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
void comando_mount() {
|
||||
// send command byte
|
||||
send_byte_to_MCU(CMD_MOUNT);
|
||||
if(TIMEOUT) return;
|
||||
|
||||
print_string_response();
|
||||
return;
|
||||
}
|
|
@ -38,10 +38,6 @@ void comando_read() {
|
|||
byte data = receive_byte_from_MCU();
|
||||
if(TIMEOUT) return;
|
||||
*token_ptr++ = data;
|
||||
|
||||
#ifdef LOADING_DOTS
|
||||
if(((byte)t) == 0) woz_putc('.');
|
||||
#endif
|
||||
}
|
||||
|
||||
// decrease by one for display result
|
||||
|
|
|
@ -66,10 +66,6 @@ void comando_save_bas() {
|
|||
for(token_ptr=*BASIC_LOMEM; token_ptr<(byte *)tmpword; token_ptr++) {
|
||||
send_byte_to_MCU(*token_ptr);
|
||||
if(TIMEOUT) return;
|
||||
|
||||
#ifdef LOADING_DOTS
|
||||
if(((byte)token_ptr) == 0) woz_putc('.');
|
||||
#endif
|
||||
}
|
||||
|
||||
// get second response
|
||||
|
|
|
@ -42,10 +42,6 @@ void comando_write() {
|
|||
for(word t=0;t<tmpword;t++) {
|
||||
send_byte_to_MCU(*token_ptr++);
|
||||
if(TIMEOUT) return;
|
||||
|
||||
#ifdef LOADING_DOTS
|
||||
if(((byte)t) == 0) woz_putc('.');
|
||||
#endif
|
||||
}
|
||||
|
||||
// get second response
|
||||
|
|
|
@ -3,17 +3,18 @@
|
|||
|
||||
byte **const BASIC_LOMEM = (byte **) 0x004a; // lomem pointer used by integer BASIC
|
||||
byte **const BASIC_HIMEM = (byte **) 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 (79)
|
||||
|
||||
// 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
|
||||
byte *const filename = (byte *) (KEYBUFSTART ); // $0200-$021F [33] stores a filename or pattern
|
||||
byte *const KEYBUF = (byte *) 0x0220; // $0220-$026F [80] keyboard input
|
||||
byte *const hex1 = (byte *) (KEYBUFSTART+33+KEYBUFLEN ); // $0270-$0274 [5] stores a hex parameter
|
||||
byte *const hex2 = (byte *) (KEYBUFSTART+33+KEYBUFLEN+5 ); // $0275-$0279 [5] stores a hex parameter
|
||||
byte *const command = (byte *) (KEYBUFSTART+33+KEYBUFLEN+5+5); // $027A-$027F [6] stores a 5 character command
|
||||
|
||||
const byte OK_RESPONSE = 0x00;
|
||||
const byte WAIT_RESPONSE = 0x01;
|
||||
|
@ -29,7 +30,7 @@ const byte CMD_RUN = 5;
|
|||
const byte CMD_SAVE = 6;
|
||||
const byte CMD_TYPE = 7;
|
||||
const byte CMD_DUMP = 8;
|
||||
const byte CMD_JMP = 9;
|
||||
const byte CMD_ASAVE = 9;
|
||||
const byte CMD_BAS = 10;
|
||||
const byte CMD_DEL = 11;
|
||||
const byte CMD_LS = 12;
|
||||
|
@ -43,7 +44,8 @@ const byte CMD_PWD = 19;
|
|||
const byte CMD_TEST = 20;
|
||||
const byte CMD_HELP = 21;
|
||||
const byte CMD_QMARK = 22;
|
||||
const byte CMD_EXIT = 23;
|
||||
const byte CMD_MOUNT = 23;
|
||||
const byte CMD_EXIT = 25;
|
||||
|
||||
// the list of recognized commands
|
||||
byte *DOS_COMMANDS[] = {
|
||||
|
@ -56,7 +58,7 @@ byte *DOS_COMMANDS[] = {
|
|||
"SAVE",
|
||||
"TYPE",
|
||||
"DUMP",
|
||||
"JMP",
|
||||
"ASAVE",
|
||||
"BAS",
|
||||
"DEL",
|
||||
"LS",
|
||||
|
@ -70,12 +72,13 @@ byte *DOS_COMMANDS[] = {
|
|||
"TEST",
|
||||
"HELP",
|
||||
"?",
|
||||
"MOUNT",
|
||||
"EXIT"
|
||||
};
|
||||
|
||||
// chesum table
|
||||
// checksum table
|
||||
byte chksum_table[] = {
|
||||
0xa7,0xe9,0xf8,0xef,0xeb,0xfe,0xef,0xee,0x8a,0xe8,0xf3,0xa7,0xa7,0xeb,0xe4,0xfe,0xe5,0xe4,0xe3,0xe4,0xe5,0x8a,0xfa,0xe5,0xf8,0xe9,0xe3,0xe4,0xe5,0x8a,0x8a,0x8a,0x82,0xf9,0xe5,0xec,0xfe,0xfd,0xeb,0xf8,0xef,0x83,0xa7,0xe9,0xe6,0xeb,0xff,0xee,0xe3,0xe5,0x8a,0xfa,0xeb,0xf8,0xe7,0xe3,0xed,0xe3,0xeb,0xe4,0xe3,0x8a,0x82,0xe2,0xeb,0xf8,0xee,0xfd,0xeb,0xf8,0xef,0x83,0xa7,0x00
|
||||
0x80,0x80,0x80,0x8a,0xf3,0xe5,0xff,0x8a,0xe0,0xff,0xf9,0xfe,0x8a,0xec,0xe5,0xff,0xe4,0xee,0x8a,0xeb,0xe4,0x8a,0xef,0xeb,0xf9,0xfe,0xef,0xf8,0x8a,0xef,0xed,0xed,0x8b,0x8b,0x8a,0x80,0x80,0x80,0xa7,0xa7,0xeb,0xff,0xfe,0xe2,0xe5,0xf8,0xf9,0x90,0xa7,0xa7,0xeb,0xe4,0xfe,0xe5,0xe4,0xe3,0xe4,0xe5,0x8a,0xfa,0xe5,0xf8,0xe9,0xe3,0xe4,0xe5,0x8a,0x8a,0x8a,0x82,0xf9,0xe5,0xec,0xfe,0xfd,0xeb,0xf8,0xef,0x83,0xa7,0xe9,0xe6,0xeb,0xff,0xee,0xe3,0xe5,0x8a,0xfa,0xeb,0xf8,0xe7,0xe3,0xed,0xe3,0xeb,0xe4,0xe3,0x8a,0x82,0xe2,0xeb,0xf8,0xee,0xfd,0xeb,0xf8,0xef,0x83,0xa7,0x00
|
||||
};
|
||||
|
||||
// parse a string, get the first string delimited by space or end of string
|
||||
|
@ -165,8 +168,9 @@ void append_hex_tmpword(char *dest) {
|
|||
|
||||
#include "cmd_read.h"
|
||||
#include "cmd_write.h"
|
||||
#include "cmd_load.h"
|
||||
#include "cmd_save.h"
|
||||
#include "cmd_asave.h"
|
||||
#include "cmd_load.h"
|
||||
#include "cmd_type.h"
|
||||
#include "cmd_dump.h"
|
||||
#include "cmd_del.h"
|
||||
|
@ -177,12 +181,13 @@ void append_hex_tmpword(char *dest) {
|
|||
#include "cmd_pwd.h"
|
||||
#include "cmd_test.h"
|
||||
#include "cmd_help.h"
|
||||
#include "cmd_mount.h"
|
||||
|
||||
void console() {
|
||||
|
||||
VIA_init();
|
||||
|
||||
woz_puts("\r\r*** SD CARD OS 1.0\r\r");
|
||||
woz_puts("\r\r*** SD CARD OS 1.1\r\r");
|
||||
|
||||
cmd = 0;
|
||||
|
||||
|
@ -322,6 +327,14 @@ void console() {
|
|||
comando_save_bas();
|
||||
}
|
||||
}
|
||||
else if(cmd == CMD_ASAVE) {
|
||||
get_token(filename, 32); // parse filename
|
||||
if(filename[0] == 0) {
|
||||
woz_puts("?MISSING FILENAME");
|
||||
continue;
|
||||
}
|
||||
comando_asave();
|
||||
}
|
||||
else if(cmd == CMD_TYPE) {
|
||||
get_token(filename, 32); // parse filename
|
||||
if(filename[0] == 0) {
|
||||
|
@ -353,17 +366,6 @@ void console() {
|
|||
}
|
||||
comando_dump();
|
||||
}
|
||||
else if(cmd == CMD_JMP) {
|
||||
get_token(hex1, 4); // parse hex
|
||||
hex_to_word(hex1);
|
||||
if(!hex_to_word_ok) {
|
||||
woz_puts("?BAD ARGUMENT");
|
||||
continue;
|
||||
}
|
||||
asm {
|
||||
jmp (tmpword)
|
||||
}
|
||||
}
|
||||
else if(cmd == CMD_BAS) {
|
||||
woz_puts("BAS ");
|
||||
bas_info();
|
||||
|
@ -406,12 +408,26 @@ void console() {
|
|||
get_token(filename, 32); // parse filename
|
||||
comando_help();
|
||||
}
|
||||
else if(cmd == CMD_MOUNT) {
|
||||
comando_mount();
|
||||
}
|
||||
else if(cmd == CMD_EXIT) {
|
||||
woz_puts("BYE\r");
|
||||
woz_mon();
|
||||
}
|
||||
else {
|
||||
if(strlen(command)!=0) {
|
||||
byte l = strlen(command);
|
||||
if(l!=0) {
|
||||
// attempt to parse XXXXR
|
||||
if(command[l-1] == 'R') {
|
||||
command[l-1] = 0;
|
||||
hex_to_word(command);
|
||||
if(hex_to_word_ok) {
|
||||
asm {
|
||||
jmp (tmpword)
|
||||
}
|
||||
}
|
||||
}
|
||||
woz_puts(command);
|
||||
woz_puts("??");
|
||||
}
|
||||
|
|
|
@ -197,8 +197,6 @@ void send_word_to_mcu() {
|
|||
send_byte_to_MCU( *((byte *)(&tmpword+1)) );
|
||||
}
|
||||
|
||||
// #define LOADING_DOTS 0
|
||||
|
||||
#include "console.h"
|
||||
|
||||
void main() {
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
@call ..\..\tools\build viatimer
|
||||
rem @call ..\..\tools\build viatimer
|
||||
@call ..\..\tools\build viaclock
|
||||
|
||||
|
|
BIN
demos/viatimer/out/viaclock#060280
Normal file
BIN
demos/viatimer/out/viaclock#060280
Normal file
Binary file not shown.
99
demos/viatimer/viaclock.c
Normal file
99
demos/viatimer/viaclock.c
Normal file
|
@ -0,0 +1,99 @@
|
|||
#define APPLE1_USE_WOZ_MONITOR 1
|
||||
|
||||
#define INPUT_LINE_PROMPT_CHAR '?'
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <utils.h>
|
||||
#include <apple1.h>
|
||||
#include <via.h>
|
||||
#include <interrupt.h>
|
||||
#include <stdlib.h>
|
||||
#include <division.h>
|
||||
|
||||
#include "..\..\lib\c64font.h"
|
||||
|
||||
const word ONE_TICK = 16666; // timer constant for 1/60 second
|
||||
|
||||
void enable_timer_interrupt() {
|
||||
|
||||
// install the interrupt handler
|
||||
install_interrupt((word) &time_interrupt_handler);
|
||||
|
||||
*VIA_IER = 0b11000000; // enable T1 interrupts
|
||||
*VIA_ACR = 0b01000000; // T1 continous, PB7 disabled
|
||||
*VIA_T1CL = BYTE0(ONE_TICK); // programs the counter to 1/60
|
||||
*VIA_T1CH = BYTE1(ONE_TICK); // and starts counting
|
||||
}
|
||||
|
||||
void disable_timer_interrupt() {
|
||||
*VIA_IER = 0b01000000; // disable T1 interrupts
|
||||
*VIA_ACR = 0; // stop T1 (makes it one-shot)
|
||||
}
|
||||
|
||||
byte last_min = 0xFF;
|
||||
|
||||
void print_digit_scanline(byte c, byte y) {
|
||||
word index = ((word) c-32) * 8 + (word) y;
|
||||
byte *ptr = FONT + index;
|
||||
|
||||
byte mask = 128;
|
||||
for(byte t=0;t<8;t++) {
|
||||
if(*ptr & mask) woz_putc('@');
|
||||
else woz_putc(' ');
|
||||
mask = mask >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
void print_clock() {
|
||||
byte c1,c2,c3,c4;
|
||||
|
||||
if(last_min != _minutes) {
|
||||
last_min = _minutes;
|
||||
|
||||
c1 = divr8u(_hours, 10, 0); c2 = rem8u;
|
||||
c3 = divr8u(_minutes, 10, 0); c4 = rem8u;
|
||||
|
||||
woz_puts("\r\r\r\r\r\r\r\r");
|
||||
for(byte t=0;t<8;t++) {
|
||||
print_digit_scanline(c1+'0',t);
|
||||
print_digit_scanline(c2+'0',t);
|
||||
print_digit_scanline( ':',t);
|
||||
print_digit_scanline(c3+'0',t);
|
||||
print_digit_scanline(c4+'0',t);
|
||||
}
|
||||
woz_puts("\r\r\r\r\r\r\r\r");
|
||||
}
|
||||
}
|
||||
|
||||
void bye() {
|
||||
disable_timer_interrupt();
|
||||
woz_puts("BYE!\r");
|
||||
woz_mon();
|
||||
}
|
||||
|
||||
byte *const KEYBUF = (byte *) 0x0200; // use the same keyboard buffer as in WOZ monitor
|
||||
|
||||
void main() {
|
||||
enable_timer_interrupt();
|
||||
|
||||
woz_puts("\r\r*** APPLE1 CLOCK ***\r\r");
|
||||
|
||||
woz_puts("\r\rREQUIRES A VIA 6522 AT $A000\r\r");
|
||||
|
||||
woz_puts("\rWHAT TIME IS IT (HOURS ) "); apple1_input_line_prompt(KEYBUF, 2);
|
||||
_hours = (byte) atoi(KEYBUF);
|
||||
woz_puts("\rWHAT TIME IS IT (MINUTES) "); apple1_input_line_prompt(KEYBUF, 2);
|
||||
_minutes = (byte) atoi(KEYBUF);
|
||||
|
||||
woz_putc('\r');
|
||||
|
||||
while(1) {
|
||||
byte k = apple1_readkey();
|
||||
if(k=='X') break;
|
||||
print_clock();
|
||||
}
|
||||
|
||||
bye();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user