Base version of the floppicator

This commit is contained in:
hkz 2025-09-01 16:40:51 +02:00
commit 2abdb84acc
8 changed files with 181 additions and 22 deletions

View file

@ -12,8 +12,8 @@ PRG=master
# Libraries
LIBS=clib-6502.a
ASM_SRCS = tk2k_startup.s preserve_zero_pages.s disk2.s
C_SRCS = main.c graphics.c utility.c line_data.c
ASM_SRCS = tk2k_startup.s preserve_zero_pages.s disk2.s sound.s
C_SRCS = main.c graphics.c utility.c line_data.c input.c
# Object files
OBJS = $(ASM_SRCS:%.s=%.o) $(C_SRCS:%.c=%.o)

View file

@ -3,9 +3,9 @@
(section registers zpage zzpage))
(memory firstPage (address (#x100 . #x1ff)) (section stack))
(memory reserved (address (#x200 . #x7ff)) (type ram))
(memory program (address (#x800 . #x15ff)) (type ram)
(memory program (address (#x800 . #x187f)) (type ram)
(section (programStart #x800) (dii_critical_wr_code #x803) (dii_critical_rd_code #x90b) startup code switch idata cdata data_init_table))
(memory dataMem (address (#x1600 . #x1fff)) (type ram) (section cstack zdata data heap zpsave))
(memory dataMem (address (#x1880 . #x1fff)) (type ram) (section cstack zdata data heap zpsave))
(memory displayPage1 (address (#x2000 . #x3fff)) (type ram))
(memory upperMem (address (#x4000 . #xbbff)) (type ram))
(memory diskBuffer (address (#xbc00 . #xbeff)) (type ram)) ;;; This memory will be used by the disk II routines as buffer

View file

@ -67,3 +67,28 @@ void draw_chars(uint8_t x, uint8_t y, uint8_t invert, uint8_t *buf, uint8_t len
}
}
}
void draw_char(uint8_t x, uint8_t y, uint8_t invert, uint8_t ch) {
for(uint8_t row = 0; row < CHAR_HEIGHT && (row + y) < SCREEN_HEIGHT; row++) {
uint16_t offset = line_offset_map[row + y];
front_buf[offset + x] = invert ? (~CHARSET[(ch * CHAR_HEIGHT) + row]) & 0x7F : CHARSET[(ch * CHAR_HEIGHT) + row];
}
}
uint8_t convert_string(uint8_t *buf, uint8_t buf_len, char *str) {
uint8_t size = 0;
while(*str && size < buf_len) { // Yeah yeah. Unsafe.
char ch = *str;
if(ch >= 64 && ch <= 95) buf[size] = ch - 64;
else if (ch >= 97 && ch <= 122) buf[size] = ch - 96; // Uppercase conversion
else if (ch >= 32 && ch <= 63) buf[size] = ch; // As is
else buf[size] = 0x20; // For everything else, insert a space.
str++;
size++;
}
return size;
}

View file

@ -13,6 +13,8 @@ void initialize_display_buffer(void);
void clear_display_buffer(void);
void draw_number(uint16_t n, uint8_t len, uint8_t x, uint8_t y);
void clear_box(uint8_t w, uint8_t h, uint8_t off_x, uint8_t off_y);
void draw_char(uint8_t x, uint8_t y, uint8_t invert, uint8_t ch);
void draw_chars(uint8_t x, uint8_t y, uint8_t invert, uint8_t *buf, uint8_t len);
uint8_t convert_string(uint8_t *buf, uint8_t buf_len, char *str);
#endif /* _GRAPHICS_HEADER_ */

View file

@ -9,7 +9,10 @@
#include "mem_map.h"
#include "mem_registers.h"
#include "graphics.h"
#include "sound.h"
#include "disk2.h"
#include "input.h"
#include "charset.h"
// External initialization requirements
#pragma require __preserve_zp
@ -17,7 +20,20 @@
#define DEFAULT_DRIVE_CONTROLLER_OFFSET 0x10
#define TOT_FLOPPY_TRACKS 35
#define SECTORS_PER_TRACK 16
#define SECTOR_SIZE 256
#define TRACKS_AT_ONCE 7
#define TRACK_PARTS (TOT_FLOPPY_TRACKS / TRACKS_AT_ONCE)
static uint8_t *track_buffer = (uint8_t*)TRACK_BUFFER_START;
static uint8_t *crc_buffer = (uint8_t*)CRC_BUFFER_START;
static uint8_t str_conv_buffer[SCREEN_CHAR_WIDTH];
static void init(void);
static void draw_sector_map(void);
static void reseat_floppy_heads(void);
// Low level initialization
static void init(void) {
@ -34,27 +50,144 @@ static void init(void) {
clear_display_buffer();
}
#define MAP_TOP_OFFSET 2
static void draw_sector_map(void) {
uint8_t str_len;
str_len = convert_string(str_conv_buffer, SCREEN_CHAR_WIDTH, "00000000000000001111111111111111222");
draw_chars(1, CHAR_HEIGHT * (MAP_TOP_OFFSET + 0), 1, str_conv_buffer, str_len);
str_len = convert_string(str_conv_buffer, SCREEN_CHAR_WIDTH, "0123456789ABCDEF0123456789ABCDEF012");
draw_chars(1, CHAR_HEIGHT * (MAP_TOP_OFFSET + 1), 1, str_conv_buffer, str_len);
for(uint8_t row = 0; row < 0x10; row++) {
draw_char(0, CHAR_HEIGHT * (MAP_TOP_OFFSET + 2 + row), 1, str_conv_buffer[row]);
}
str_len = convert_string(str_conv_buffer, SCREEN_CHAR_WIDTH, "...................................");
for(uint8_t row = 0; row < 0x10; row++) {
draw_chars(1, CHAR_HEIGHT * (MAP_TOP_OFFSET + 2 + row), 0, str_conv_buffer, str_len);
}
}
static void reseat_floppy_heads(void) {
dii_power_on(DEFAULT_DRIVE_CONTROLLER_OFFSET, 0);
dii_head_reposition(DEFAULT_DRIVE_CONTROLLER_OFFSET, 96, 0);
dii_power_off(DEFAULT_DRIVE_CONTROLLER_OFFSET);
dii_power_on(DEFAULT_DRIVE_CONTROLLER_OFFSET, 1);
dii_head_reposition(DEFAULT_DRIVE_CONTROLLER_OFFSET, 96, 0);
dii_power_off(DEFAULT_DRIVE_CONTROLLER_OFFSET);
}
__task int main(void) {
uint8_t cur_trk_1, cur_trk_2 = 0;
uint8_t keep_going = 1;
uint8_t trk_pos_1 = 0, trk_pos_2 = 0;
uint16_t errors = 0;
uint8_t *temp_crc_buf;
__disable_interrupts();
init();
uint8_t str_len = convert_string(str_conv_buffer, SCREEN_CHAR_WIDTH, "THE FLOPPICATOR");
draw_chars(12, 32, 0, str_conv_buffer, str_len);
str_len = convert_string(str_conv_buffer, SCREEN_CHAR_WIDTH, "PRESS ANY KEY TO CONTINUE");
draw_chars(7, 176, 1, str_conv_buffer, str_len);
while(!read_any_key());
snd_mod_button();
clear_display_buffer();
draw_sector_map();
str_len = convert_string(str_conv_buffer, SCREEN_CHAR_WIDTH, "ERRORS: 000");
draw_chars(0, CHAR_HEIGHT * (MAP_TOP_OFFSET + 19), 0, str_conv_buffer, str_len);
reseat_floppy_heads();
temp_crc_buf = crc_buffer;
for(uint8_t part = 0; part < TRACK_PARTS; part++) {
uint8_t start_track = part * TRACKS_AT_ONCE;
dii_power_on(DEFAULT_DRIVE_CONTROLLER_OFFSET, 0);
for(uint8_t cur_trk = 0; cur_trk < TRACKS_AT_ONCE; cur_trk++) {
dii_head_reposition(DEFAULT_DRIVE_CONTROLLER_OFFSET, trk_pos_1 << 1, (start_track + cur_trk) << 1);
trk_pos_1 = (start_track + cur_trk);
for(uint8_t sec = 0; sec < SECTORS_PER_TRACK; sec++) {
uint8_t read_res = dii_read_sector(DEFAULT_DRIVE_CONTROLLER_OFFSET, trk_pos_1, sec, track_buffer + (cur_trk * SECTORS_PER_TRACK * SECTOR_SIZE) + (sec * SECTOR_SIZE), 0);
*(temp_crc_buf++) = calculate_crc8(track_buffer + (cur_trk * SECTORS_PER_TRACK * SECTOR_SIZE) + (sec * SECTOR_SIZE), SECTOR_SIZE);
draw_char((start_track + cur_trk) + 1, CHAR_HEIGHT * (MAP_TOP_OFFSET + 2 + sec), read_res ? 0 : 1, read_res ? 18 : 24);
if(!read_res) {
errors++;
draw_number(errors, 3, 8, CHAR_HEIGHT * (MAP_TOP_OFFSET + 19));
}
}
}
dii_power_off(DEFAULT_DRIVE_CONTROLLER_OFFSET);
dii_power_on(DEFAULT_DRIVE_CONTROLLER_OFFSET, 1);
for(uint8_t cur_trk = 0; cur_trk < TRACKS_AT_ONCE; cur_trk++) {
dii_head_reposition(DEFAULT_DRIVE_CONTROLLER_OFFSET, trk_pos_2 << 1, (start_track + cur_trk) << 1);
trk_pos_2 = (start_track + cur_trk);
for(uint8_t sec = 0; sec < SECTORS_PER_TRACK; sec++) {
dii_encode_gcr62_data(track_buffer + (cur_trk * SECTORS_PER_TRACK * SECTOR_SIZE) + (sec * SECTOR_SIZE), (uint8_t*)WRITE_SIXES_BUFFER_DEFAULT_ADDRESS, (uint8_t*)WRITE_TWOS_BUFFER_DEFAULT_ADDRESS);
uint8_t write_res = dii_write_sector(DEFAULT_DRIVE_CONTROLLER_OFFSET, trk_pos_2, sec);
draw_char((start_track + cur_trk) + 1, CHAR_HEIGHT * (MAP_TOP_OFFSET + 2 + sec), write_res ? 1 : 0, write_res ? 24 : 23);
if(write_res) {
errors++;
draw_number(errors, 3, 8, CHAR_HEIGHT * (MAP_TOP_OFFSET + 19));
}
}
}
dii_power_off(DEFAULT_DRIVE_CONTROLLER_OFFSET);
}
if(!errors) { // No errors up to now, check what we have written
dii_power_on(DEFAULT_DRIVE_CONTROLLER_OFFSET, 1);
// Now, time to check that we wrote things that make sense...
temp_crc_buf = crc_buffer;
for(uint8_t cur_trk = 0; cur_trk < TOT_FLOPPY_TRACKS; cur_trk++) {
dii_head_reposition(DEFAULT_DRIVE_CONTROLLER_OFFSET, trk_pos_2 << 1, cur_trk << 1);
trk_pos_2 = cur_trk;
for(uint8_t sec = 0; sec < SECTORS_PER_TRACK; sec++) {
uint8_t read_res = dii_read_sector(DEFAULT_DRIVE_CONTROLLER_OFFSET, trk_pos_2, sec, track_buffer, 0);
draw_char(cur_trk + 1, CHAR_HEIGHT * (MAP_TOP_OFFSET + 2 + sec), 0, read_res ? 102 : 24);
uint8_t crc_check = (calculate_crc8(track_buffer, SECTOR_SIZE) == *(temp_crc_buf++));
draw_char(cur_trk + 1, CHAR_HEIGHT * (MAP_TOP_OFFSET + 2 + sec), crc_check ? 0 : 1, crc_check ? 22 : 24);
if(!read_res) {
errors++;
draw_number(errors, 3, 8, CHAR_HEIGHT * (MAP_TOP_OFFSET + 19));
}
if(!crc_check) {
errors++;
draw_number(errors, 3, 8, CHAR_HEIGHT * (MAP_TOP_OFFSET + 19));
}
}
}
dii_power_off(DEFAULT_DRIVE_CONTROLLER_OFFSET);
}
__enable_interrupts();
uint8_t chars[] = {1, 2, 3, 32, 4};
if(errors) snd_sad_scale();
else snd_festive();
draw_chars(0, 0, 1, chars, 5);
draw_chars(1, 8, 0, chars, 5);
draw_chars(2, 16, 1, chars, 5);
do {
} while(keep_going);
__asm volatile(" brk\n":::);
while(1);
return 0;
}

View file

@ -7,8 +7,7 @@
#define ROMRAM_BANK 0xC100
#define SHARED_PAGE 0x9B00
#define STATE_PAGE 0x9A00
#define MODULE_PAGE 0x4000
#define TRACK_BUFFER_START 0x4000
#define CRC_BUFFER_START 0xB000
#endif /* _MEMORY_MAP_HEADER_ */

View file

@ -45,10 +45,10 @@ uint16_t lfsr_update(void) {
}
#define CRC8RDALLAS_POLY 0x31
uint8_t calculate_crc8(uint8_t* data, uint8_t len) {
uint8_t calculate_crc8(uint8_t* data, uint16_t len) {
uint8_t crc = 0;
for(uint8_t data_idx = 0; data_idx < len; data_idx++) {
for(uint16_t data_idx = 0; data_idx < len; data_idx++) {
uint8_t carry;
uint8_t d = data[data_idx];

View file

@ -29,6 +29,6 @@ uint8_t bit_reverse(uint8_t b);
uint8_t bit_count(uint8_t b);
void lfsr_init(uint16_t reg);
uint16_t lfsr_update(void);
uint8_t calculate_crc8(uint8_t* data, uint8_t len);
uint8_t calculate_crc8(uint8_t* data, uint16_t len);
#endif /* _UTILITY_HEADER_ */