apple1-videocard-lib/demos/viatimer/viaclock.c

163 lines
3.8 KiB
C

#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 = 15996; // timer constant for 1/60 second calculated as 14318180/14*61/65/60
word ONE_TICK;
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;
byte last_sec = 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;
for(byte t=0;t<24;t++) woz_putc('\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);
}
for(byte t=0;t<4;t++) woz_putc('\r');
last_sec = 0;
}
if(last_sec < _seconds) {
//if(last_sec > 20) woz_putc('>');
/*
if(last_sec < 10) { woz_puts("...10 "); last_sec = 10; }
else if(last_sec < 20) { woz_puts("...20 "); last_sec = 20; }
else if(last_sec < 30) { woz_puts("...30 "); last_sec = 30; }
else if(last_sec < 40) { woz_puts("...40 "); last_sec = 40; }
else if(last_sec < 50) { woz_puts("...50 "); last_sec = 50; }
*/
c1 = divr8u(last_sec, 10, 0); c2 = rem8u;
woz_putc(' ');
woz_putc(c1+'0');
woz_putc(c2+'0');
woz_putc(' ');
last_sec++;
}
}
void bye() {
disable_timer_interrupt();
woz_puts("BYE!\r");
woz_mon();
}
void detect_machine_type() {
// detect if VIA 6522 is present
*VIA_DDRB = 0xA5;
if(*VIA_DDRB != 0xA5) {
woz_puts("\r\rSORRY, THIS PROGRAM NEEDS A VIA 6522 \rMAPPED AT ADDRESS $A000\r\r");
bye();
}
// detect if genuine apple1 or replica-1
woz_puts("\r\rRUNNING ON ");
const word *ptr1 = (word *) 0xF000;
const word *ptr2 = (word *) 0xFF00;
if(*ptr1 == *ptr2) {
// genuine Apple1
ONE_TICK = 15996; // timer constant for 1/60 second calculated as 14318180/14*61/65/60
woz_puts("APPLE-1");
}
else {
// Replica-1
ONE_TICK = 16667; // timer constant for 1/60 second calculated as 5000000/5/60
woz_puts("REPLICA-1");
}
woz_puts("\r\r");
}
byte *const KEYBUF = (byte *) 0x0200; // use the same keyboard buffer as in WOZ monitor
void main() {
woz_puts("\r\r*** APPLE-1 CLOCK ***\r\r");
detect_machine_type();
woz_puts("\rWHAT TIME IS IT ?\r");
do {
woz_puts("\r(HOURS ) ");
apple1_input_line_prompt(KEYBUF, 2);
_hours = (byte) atoi(KEYBUF);
} while(_hours > 23);
do {
woz_puts("\r(MINUTES) ");
apple1_input_line_prompt(KEYBUF, 2);
_minutes = (byte) atoi(KEYBUF);
} while(_minutes > 59);
_seconds = 0;
enable_timer_interrupt();
woz_putc('\r');
while(1) {
byte k = apple1_readkey();
if(k=='X') break;
print_clock();
}
bye();
}