diff --git a/roms/f256k/README.md b/roms/f256k/README.md new file mode 100644 index 0000000..d0523cf --- /dev/null +++ b/roms/f256k/README.md @@ -0,0 +1,12 @@ +# ROM Files for the F256K + +This directory contains BIN files for programming the F256K flash memory with the Foenix Toolbox. + +## How to Install + +Currently, the toolbox must be installed by bulk programming the flash memory. +Using the FoenixMgr Python script, this can be done with the following command (substitute the device path or name for your F256K's USB debug port): + +``` +python FoenixMgr.zip --port {debug device name} --flash-bulk toolbox.csv +``` diff --git a/roms/f256k/toolbox-00.bin b/roms/f256k/toolbox-00.bin new file mode 100644 index 0000000..cec34f6 Binary files /dev/null and b/roms/f256k/toolbox-00.bin differ diff --git a/roms/f256k/toolbox-01.bin b/roms/f256k/toolbox-01.bin new file mode 100644 index 0000000..80831b4 Binary files /dev/null and b/roms/f256k/toolbox-01.bin differ diff --git a/roms/f256k/toolbox-02.bin b/roms/f256k/toolbox-02.bin new file mode 100644 index 0000000..d619f45 Binary files /dev/null and b/roms/f256k/toolbox-02.bin differ diff --git a/roms/f256k/toolbox-03.bin b/roms/f256k/toolbox-03.bin new file mode 100644 index 0000000..4204f45 Binary files /dev/null and b/roms/f256k/toolbox-03.bin differ diff --git a/roms/f256k/toolbox-04.bin b/roms/f256k/toolbox-04.bin new file mode 100644 index 0000000..20db7a2 Binary files /dev/null and b/roms/f256k/toolbox-04.bin differ diff --git a/roms/f256k/toolbox-05.bin b/roms/f256k/toolbox-05.bin new file mode 100644 index 0000000..67f3874 Binary files /dev/null and b/roms/f256k/toolbox-05.bin differ diff --git a/roms/f256k/toolbox-06.bin b/roms/f256k/toolbox-06.bin new file mode 100644 index 0000000..2e27cde Binary files /dev/null and b/roms/f256k/toolbox-06.bin differ diff --git a/roms/f256k/toolbox-07.bin b/roms/f256k/toolbox-07.bin new file mode 100644 index 0000000..cd2c586 Binary files /dev/null and b/roms/f256k/toolbox-07.bin differ diff --git a/roms/f256k/toolbox-08.bin b/roms/f256k/toolbox-08.bin new file mode 100644 index 0000000..4c048e3 Binary files /dev/null and b/roms/f256k/toolbox-08.bin differ diff --git a/roms/f256k/toolbox-09.bin b/roms/f256k/toolbox-09.bin new file mode 100644 index 0000000..0196a6e Binary files /dev/null and b/roms/f256k/toolbox-09.bin differ diff --git a/roms/f256k/toolbox-0A.bin b/roms/f256k/toolbox-0A.bin new file mode 100644 index 0000000..4b80763 Binary files /dev/null and b/roms/f256k/toolbox-0A.bin differ diff --git a/roms/f256k/toolbox-0B.bin b/roms/f256k/toolbox-0B.bin new file mode 100644 index 0000000..41a87eb Binary files /dev/null and b/roms/f256k/toolbox-0B.bin differ diff --git a/roms/f256k/toolbox-0C.bin b/roms/f256k/toolbox-0C.bin new file mode 100644 index 0000000..187bf71 Binary files /dev/null and b/roms/f256k/toolbox-0C.bin differ diff --git a/roms/f256k/toolbox-0D.bin b/roms/f256k/toolbox-0D.bin new file mode 100644 index 0000000..edbf3a0 Binary files /dev/null and b/roms/f256k/toolbox-0D.bin differ diff --git a/roms/f256k/toolbox-0E.bin b/roms/f256k/toolbox-0E.bin new file mode 100644 index 0000000..cd73497 Binary files /dev/null and b/roms/f256k/toolbox-0E.bin differ diff --git a/roms/f256k/toolbox-0F.bin b/roms/f256k/toolbox-0F.bin new file mode 100644 index 0000000..9a6c02a Binary files /dev/null and b/roms/f256k/toolbox-0F.bin differ diff --git a/roms/f256k/toolbox-3F.bin b/roms/f256k/toolbox-3F.bin new file mode 100644 index 0000000..0f8d0c6 Binary files /dev/null and b/roms/f256k/toolbox-3F.bin differ diff --git a/roms/f256k/toolbox.bin b/roms/f256k/toolbox.bin new file mode 100644 index 0000000..37e4c53 Binary files /dev/null and b/roms/f256k/toolbox.bin differ diff --git a/roms/f256k/toolbox.csv b/roms/f256k/toolbox.csv new file mode 100644 index 0000000..e299297 --- /dev/null +++ b/roms/f256k/toolbox.csv @@ -0,0 +1,17 @@ +"00","toolbox-00.bin" +"01","toolbox-01.bin" +"02","toolbox-02.bin" +"03","toolbox-03.bin" +"04","toolbox-04.bin" +"05","toolbox-05.bin" +"06","toolbox-06.bin" +"07","toolbox-07.bin" +"08","toolbox-08.bin" +"09","toolbox-09.bin" +"0A","toolbox-0A.bin" +"0B","toolbox-0B.bin" +"0C","toolbox-0C.bin" +"0D","toolbox-0D.bin" +"0E","toolbox-0E.bin" +"0F","toolbox-0F.bin" +"3F","toolbox-3F.bin" diff --git a/src/C256/addresses.csv b/src/C256/addresses.csv new file mode 100644 index 0000000..87c7b0e --- /dev/null +++ b/src/C256/addresses.csv @@ -0,0 +1,55 @@ +"sys_proc_exit","FFE000" +"sys_chan_read_b","FFE004" +"sys_chan_read","FFE008" +"sys_chan_readline","FFE00C" +"sys_chan_write_b","FFE010" +"sys_chan_write","FFE014" +"sys_chan_status","FFE018" +"sys_chan_flush","FFE01C" +"sys_chan_seek","FFE020" +"sys_chan_ioctrl","FFE024" +"sys_chan_open","FFE028" +"sys_chan_close","FFE02C" +"sys_chan_swap","FFE030" +"sys_chan_device","FFE034" +"sys_bdev_register","FFE038" +"sys_bdev_read","FFE03C" +"sys_bdev_write","FFE040" +"sys_bdev_status","FFE044" +"sys_bdev_flush","FFE048" +"sys_bdev_ioctrl","FFE04C" +"sys_fsys_open","FFE050" +"sys_fsys_close","FFE054" +"sys_fsys_opendir","FFE058" +"sys_fsys_closedir","FFE05C" +"sys_fsys_readdir","FFE060" +"sys_fsys_findfirst","FFE064" +"sys_fsys_findnext","FFE068" +"sys_fsys_mkdir","FFE06C" +"sys_fsys_delete","FFE070" +"sys_fsys_rename","FFE074" +"sys_fsys_set_cwd","FFE078" +"sys_fsys_get_cwd","FFE07C" +"sys_fsys_load","FFE080" +"sys_fsys_register_loader","FFE084" +"sys_fsys_stat","FFE088" +"sys_mem_get_ramtop","FFE08C" +"sys_mem_reserve","FFE090" +"sys_err_message","FFE094" +"sys_proc_run","FFE098" +"sys_txt_get_capabilities","FFE09C" +"sys_txt_set_mode","FFE0A0" +"sys_txt_setsizes","FFE0A4" +"sys_txt_set_xy","FFE0A8" +"sys_txt_get_xy","FFE0AC" +"sys_txt_get_region","FFE0B0" +"sys_txt_set_region","FFE0B4" +"sys_txt_set_color","FFE0B8" +"sys_txt_get_color","FFE0BC" +"sys_txt_set_cursor_visible","FFE0C0" +"sys_txt_set_font","FFE0C4" +"sys_txt_get_sizes","FFE0C8" +"sys_txt_set_border","FFE0CC" +"sys_txt_set_border_color","FFE0D0" +"sys_txt_put","FFE0D4" +"sys_txt_print","FFE0D8" diff --git a/src/C256/extras.s b/src/C256/extras.s index 86d8a07..ff559a3 100644 --- a/src/C256/extras.s +++ b/src/C256/extras.s @@ -9,7 +9,7 @@ #endif .section stack - .section code + .section farcode ; ; Reset the stack to the initial value. diff --git a/src/C256/f256-cstartup.s b/src/C256/f256-cstartup.s new file mode 100644 index 0000000..d73021d --- /dev/null +++ b/src/C256/f256-cstartup.s @@ -0,0 +1,149 @@ +;;; Startup variant, change attribute value if you make your own + .rtmodel cstartup,"f256" + + .rtmodel version, "1" + .rtmodel core, "*" + + .section stack + .section cstack + .section heap + .section data_init_table + + .extern main, exit + .extern _Dp, _Vfp + .extern _DirectPageStart + +#ifndef __CALYPSI_DATA_MODEL_SMALL__ + .extern _NearBaseAddress +#endif + +#include "macros.h" + +;;; *************************************************************************** +;;; +;;; The reset vector. This uses the entry point label __program_root_section +;;; which by default is what the linker will pull in first. +;;; +;;; *************************************************************************** + + .section reset + .pubweak __program_root_section +__program_root_section: + .word __program_start + +;;; *************************************************************************** +;;; +;;; __program_start - actual start point of the program +;;; +;;; Set up CPU stack, initialize sections and call main(). +;;; You can override this with your own routine, or tailor it as needed. +;;; The easiest way to make custom initialization is to provide your own +;;; __low_level_init which gets called after stacks have been initialized. +;;; +;;; *************************************************************************** + +#ifdef __CALYPSI_CODE_MODEL_COMPACT__ + .section code +#else + .section code, noreorder +#endif + .pubweak __program_start +__program_start: + clc + xce ; native 16-bit mode + rep #0x38 ; 16-bit registers, no decimal mode + ldx ##.sectionEnd stack + txs ; set stack + lda ##_DirectPageStart + tcd ; set direct page +#ifdef __CALYPSI_DATA_MODEL_SMALL__ + lda ##0 +#else + lda ##.word2 _NearBaseAddress +#endif + stz dp:.tiny(_Vfp+2) + xba ; A upper half = data bank + pha + plb ; pop 8 dummy + plb ; set data bank + +#ifdef __CALYPSI_CODE_MODEL_COMPACT__ + jmp long:_Trampoline_program_start + .section compactcode, noreorder +_Trampoline_program_start: +#define CODE compactcode +#elif __CALYPSI_CODE_MODEL_LARGE__ + jmp long:_Trampoline_program_start + .section farcode, noreorder +_Trampoline_program_start: +#define CODE farcode +#else +#define CODE code +#endif + call __low_level_init + +;;; **** Initialize data sections if needed. + .section CODE, noroot, noreorder + .pubweak __data_initialization_needed + .extern __initialize_sections +__data_initialization_needed: + lda ##.word2 (.sectionEnd data_init_table) + sta dp:.tiny(_Dp+6) + lda ##.word0 (.sectionEnd data_init_table) + sta dp:.tiny(_Dp+4) + lda ##.word2 (.sectionStart data_init_table) + sta dp:.tiny(_Dp+2) + lda ##.word0 (.sectionStart data_init_table) + sta dp:.tiny(_Dp+0) + call __initialize_sections + +;;; **** Initialize streams if needed. + .section CODE, noroot, noreorder + .pubweak __call_initialize_global_streams + .extern __initialize_global_streams +__call_initialize_global_streams: + call __initialize_global_streams + +;;; **** Initialize heap if needed. + .section CODE, noroot, noreorder + .pubweak __call_heap_initialize + .extern __heap_initialize, __default_heap +__call_heap_initialize: +#ifdef __CALYPSI_DATA_MODEL_SMALL__ + lda ##.sectionSize heap + sta dp:.tiny(_Dp+2) + lda ##.sectionStart heap + sta dp:.tiny(_Dp+0) + lda ##__default_heap +#else + lda ##.word2 (.sectionStart heap) + sta dp:.tiny(_Dp+6) + lda ##.word0 (.sectionStart heap) + sta dp:.tiny(_Dp+4) + lda ##.word2 __default_heap + sta dp:.tiny(_Dp+2) + lda ##.word0 __default_heap + sta dp:.tiny(_Dp+0) + ldx ##.word2 (.sectionSize heap) + lda ##.word0 (.sectionSize heap) +#endif + call __heap_initialize + + .section CODE, root, noreorder + lda ##0 ; argc = 0 + call main + jump exit + +;;; *************************************************************************** +;;; +;;; __low_level_init - custom low level initialization +;;; +;;; This default routine just returns doing nothing. You can provide your own +;;; routine, either in C or assembly for doing custom low leve initialization. +;;; +;;; *************************************************************************** + + .section libcode + .pubweak __low_level_init +__low_level_init: + return diff --git a/src/C256/f256-flash.scm b/src/C256/f256-flash.scm new file mode 100644 index 0000000..1406771 --- /dev/null +++ b/src/C256/f256-flash.scm @@ -0,0 +1,57 @@ +(define memories + '( + (memory flash + (address (#xf80000 . #xfdffff)) + (type ROM) + (fill #xff) + (section + (jumptable #xf80000) + data_init_table + data + ifar)) + + (memory flash-shadow + (address (#xffff00 . #xffffff)) + (type ROM) + (fill 0) + (section + (LoCodeStorage #xffff00) + (VectorStorage #xffffe0))) + + (memory LoCode + (address (#x00ff00 . #x00ffdf)) + (type ROM) + (scatter-to LoCodeStorage) + (section code cdata)) + + (memory Vector + (address (#x00ffe0 . #x00ffff)) + (type ROM) + (scatter-to VectorStorage) + (section (reset #xfffc))) + + (memory hiram + (address (#x070000 . #x07ffff)) + (type RAM) + (section heap)) + + (memory loram + (address (#x00d000 . #x00dfff)) + (type RAM) + (placement-group nobits (section zdata znear)) + (placement-group bits (section data near))) + + (memory stackram + (address (#x00c000 . #x00cfff)) + (type RAM) + (section stack)) + + (memory DirectPage + (address (#x00bf00 . #x00bfff)) + (section (registers ztiny))) + + (block stack (size #x1000)) + (block heap (size #x1000)) + (base-address _DirectPageStart DirectPage 0) + (base-address _NearBaseAddress hiram 0) +)) diff --git a/src/C256/ld_lc_f256.scm b/src/C256/f256-ld_lc.scm similarity index 81% rename from src/C256/ld_lc_f256.scm rename to src/C256/f256-ld_lc.scm index eba4002..77940a1 100644 --- a/src/C256/ld_lc_f256.scm +++ b/src/C256/f256-ld_lc.scm @@ -1,10 +1,15 @@ (define memories '((memory flash (address (#x040000 . #x07ffff)) - (type rom)) + (type rom) + ) (memory DirectPage (address (#x00c000 . #x00c0ff)) (section (registers ztiny))) (memory LoRAM (address (#x00c100 . #x00efff)) (section stack data zdata data heap)) + (memory RAM-jumptable + (address (#x00f000 . #x00feff)) + (section jumptable)) + (memory NearRAM1 (address (#x010000 . #x017fff)) (section znear near)) (memory NearRAM2 (address (#x018000 . #x01ffff)) @@ -13,8 +18,8 @@ (section far huge)) (memory FarRAM2 (address (#x030000 . #x03ffff)) (section zfar zhuge )) - (memory LoCODE (address (#x00f000 . #x00ffdf)) - (section code cdata (jumptable #x00f000))) + (memory LoCODE (address (#x00ff00 . #x00ffdf)) + (section code cdata)) (memory Vector (address (#x00ffe0 . #x00ffff)) (section (reset #xfffc))) (block stack (size #x1000)) diff --git a/src/C256/flash-f256.scm b/src/C256/flash-f256-old.scm similarity index 72% rename from src/C256/flash-f256.scm rename to src/C256/flash-f256-old.scm index a825401..7691eb2 100644 --- a/src/C256/flash-f256.scm +++ b/src/C256/flash-f256-old.scm @@ -1,5 +1,12 @@ (define memories - '((memory flash (address (#xf80000 . #xffffff)) + '( + (memory HiCode1 (address (#xfc0000 . #xfcffff)) + (section cfar switch data_init_table idata ifar farcode)) + (memory HiCode2 (address (#xfd0000 . #xfdffff)) + (section cfar switch data_init_table idata ifar farcode)) + (memory HiCode3 (address (#xfe0000 . #xfeffff)) + (section cfar switch data_init_table idata ifar farcode)) + (memory flash (address (#xff0000 . #xffffff)) (fill 0) (section (LoCodeStorage #xffe000) @@ -22,12 +29,6 @@ (memory Vector (address (#x00ffe0 . #x00ffff)) (scatter-to VectorStorage) (section (reset #xfffc))) - (memory HiCode1 (address (#xf80000 . #xf8ffff)) - (section cfar switch data_init_table ifar farcode)) - (memory HiCode2 (address (#xf90000 . #xf9ffff)) - (section cfar switch data_init_table ifar farcode)) - (memory HiCode3 (address (#xfa0000 . #xfaffff)) - (section cfar switch data_init_table ifar farcode)) (block stack (size #x1000)) (block heap (size #x1000)) (base-address _DirectPageStart DirectPage 0) diff --git a/src/C256/genaddresses.py b/src/C256/genaddresses.py new file mode 100644 index 0000000..6c8d1f7 --- /dev/null +++ b/src/C256/genaddresses.py @@ -0,0 +1,19 @@ +address = 0xffe000 + +# Read in the list of system calls ("sys_") +with open("addresses.csv", "w") as addresses: + with open("syscalls.txt", "r") as call_names: + for line in call_names: + # Remove comments + index = line.find("#") + if index == 0: + line = "" + elif index > 0: + line = line[index - 1:] + + line = line.strip() + + # Process only actual names + if len(line) > 0: + addresses.write("\"sys_{0}\",\"{1:06X}\"\n".format(line, address)) + address = address + 4 diff --git a/src/C256/iecll.s b/src/C256/iecll.s index 6d46218..41ce3ca 100644 --- a/src/C256/iecll.s +++ b/src/C256/iecll.s @@ -2,8 +2,8 @@ ;;; Low-level support code for the IEC port ;;; ;;; NOTE: routines will be split into private routines and public routines. -;;; Private routines will assume near JSRs, 8-bit accumulator and index registers, and interrupts disabled. -;;; Public routines will assume far JSRs and 16-bit accumulator and index registers. +;;; Private routines will assume near jsls, 8-bit accumulator and index registers, and interrupts disabled. +;;; Public routines will assume far jsls and 16-bit accumulator and index registers. ;;; Public routines will also assume Calypsi calling conventions. ;;; @@ -21,14 +21,14 @@ #include "F256/iec_f256.h" - .section data,data + .section ztiny,bss -eoi_pending: .byte 0 -rx_eoi: .byte 0 -delayed: .byte 0 -queue: .byte 0 +eoi_pending: .space 1 +rx_eoi: .space 1 +delayed: .space 1 +queue: .space 1 - .section code + .section farcode ;; ;; Macros @@ -40,7 +40,7 @@ assert_bit: .macro pin and #(\pin ^ 0xff) sta IEC_OUTPUT_PORT pla - rts + rtl .endm release_bit: .macro pin @@ -49,7 +49,7 @@ release_bit: .macro pin ora #(\pin) sta IEC_OUTPUT_PORT pla - rts + rtl .endm read_bit: .macro pin @@ -60,7 +60,7 @@ loop$ lda IEC_INPUT_PORT and #(\pin) cmp #1 pla - rts + rtl .endm emit: .macro char @@ -106,38 +106,38 @@ sleep_20us: phx _loop$ dex bne _loop$ plx - rts + rtl sleep_100us: phx ldx #5 -_loop$ jsr sleep_20us +_loop$ jsl sleep_20us dex bne _loop$ plx - rts + rtl -sleep_300us: jsr sleep_100us - jsr sleep_100us - jsr sleep_100us - rts +sleep_300us: jsl sleep_100us + jsl sleep_100us + jsl sleep_100us + rtl -sleep_1ms: jsr sleep_300us - jsr sleep_300us - jsr sleep_300us - jmp sleep_100us +sleep_1ms: jsl sleep_300us + jsl sleep_300us + jsl sleep_300us + jmp long: sleep_100us ;; ;; Code to handle the IEC port ;; -init: jsr sleep_1ms - jsr release_ATN - jsr release_DATA - jsr release_SREQ - jsr assert_CLOCK ; IDLE state - jsr sleep_1ms - jsr sleep_1ms - jsr sleep_1ms +init: jsl sleep_1ms + jsl release_ATN + jsl release_DATA + jsl release_SREQ + jsl assert_CLOCK ; IDLE state + jsl sleep_1ms + jsl sleep_1ms + jsl sleep_1ms ; Bail if ATN and SRQ fail to float back up. ; We'll have a more thorough test when we send @@ -145,18 +145,18 @@ init: jsr sleep_1ms nop nop nop - jsr read_SREQ + jsl read_SREQ bcc err$ - jsr read_ATN + jsl read_ATN bcc err$ - jsr sleep_1ms + jsl sleep_1ms clc - rts + rtl err$ sec - rts + rtl ; ; Send a command byte and release the DATA and CLOCK lines afterwards @@ -164,25 +164,25 @@ err$ sec ; A = the command byte to send ; atn_release_data - jsr release_DATA - jsr release_CLOCK ; TODO: makes /no/ sense; maybe we can remove... - jsr atn_common ; NOTE: does NOT release ATN! Does NOT release IRQs! - rts + jsl release_DATA + jsl release_CLOCK ; TODO: makes /no/ sense; maybe we can remove... + jsl atn_common ; NOTE: does NOT release ATN! Does NOT release IRQs! + rtl ; ; Send a command byte and release the ATN, DATA, and CLOCK lines ; ; A = the command byte to send ; -atn_release jsr atn_common +atn_release jsl atn_common - jsr release_ATN - jsr sleep_20us - jsr sleep_20us - jsr sleep_20us - jsr release_CLOCK - jsr release_DATA - rts + jsl release_ATN + jsl sleep_20us + jsl sleep_20us + jsl sleep_20us + jsl release_CLOCK + jsl release_DATA + rtl ; ; Send a command byte with ATN asserted @@ -193,41 +193,41 @@ atn_common ; Assert ATN; if we aren't already in sending mode, ; get there: - jsr assert_ATN - jsr assert_CLOCK - jsr release_DATA + jsl assert_ATN + jsl assert_CLOCK + jsl release_DATA ; Now give the devices ~1ms to start listening. - jsr sleep_1ms + jsl sleep_1ms ; If no one is listening, there's nothing on ; the bus, so signal an error. - jsr read_DATA + jsl read_DATA bcs err$ ; ATN bytes are technically never EOI bytes stz eoi_pending - jmp send + jmp long: send err$ ; Always release the ATN line on error; TODO: add post delay - jmp release_ATN + jmp long: release_ATN ; ; Send a byte over the IEC bus but mark it as the last byte ; ; A = the byte to send ; -send_eoi jsr set_eoi - jmp send +send_eoi jsl set_eoi + jmp long: send ; ; Set that the EOI byte is the next to be sent ; set_eoi stz eoi_pending dec eoi_pending - rts + rtl ; ; Sends the queued byte with an EOI @@ -237,9 +237,9 @@ flush bit delayed pha lda queue stz delayed - jsr send_eoi + jsl send_eoi pla -done$: rts +done$: rtl ; ; Send a byte over the IEC bus @@ -251,26 +251,26 @@ send ; the host is asserting CLOCK and the devices are asserting DATA. ; There must be at least 100us between bytes. - jsr sleep_300us + jsl sleep_300us ; ; Clever cheating (PJW: removed since we disable interrupts for all this code) ; ; Act as an ersatz listener to keep the other listeners busy ; ; until we are ready to receive. This is NOT part of the ; ; IEC protocol -- we are doing this in lieu of an interrupt. - ; jsr assert_DATA + ; jsl assert_DATA ; Release CLOCK to signal that we are ready to send ; We can do this without disabling interrupts because ; we are also asserting DATA. - jsr release_CLOCK + jsl release_CLOCK ; Now we wait for all of the listeners to acknowledge. wait$ - jsr sleep_20us + jsl sleep_20us ; Check to see if all listeners have acknowledged - jsr read_DATA + jsl read_DATA bcs ready$ ; Other listeners are still busy; go back to sleep. @@ -288,7 +288,7 @@ eoi$ ; already had the opportunity to delay before starting the ; ack, so hopefully it will stay in nominal 250us range. -TYE$ jsr read_DATA +TYE$ jsl read_DATA bcs TYE$ ; Now we're basically back to the point where we are waiting @@ -299,13 +299,13 @@ TYE$ jsr read_DATA ; The drive should hold DATA for at least 60us. Give it ; 20us, and then repeat our ersatz listener trick. - jsr sleep_20us - ; jsr assert_DATA (PJW: removed trick) + jsl sleep_20us + ; jsl assert_DATA (PJW: removed trick) bra wait$ send$ ; Give the listeners time to notice that the've all ack'd - jsr sleep_20us ; NOT on the C64 + jsl sleep_20us ; NOT on the C64 ; Now start pushing out the bits. Note that the timing ; is not critical, but each clock state must last at @@ -317,32 +317,32 @@ loop$ ; TODO: opt test for a frame error ; Clock out the next bit - jsr assert_CLOCK - jsr sleep_20us + jsl assert_CLOCK + jsl sleep_20us lsr a bcs one$ -zero$ jsr assert_DATA +zero$ jsl assert_DATA bra clock$ -one$ jsr release_DATA +one$ jsl release_DATA bra clock$ clock$ ; Toggle the clock - jsr sleep_20us ; TODO: Maybe extend this. + jsl sleep_20us ; TODO: Maybe extend this. - jsr sleep_20us ; 1541 needs this. - jsr release_CLOCK + jsl sleep_20us ; 1541 needs this. + jsl release_CLOCK - jsr sleep_20us + jsl sleep_20us dex bne loop$ plx ; Finish the last bit and wait for the listeners to ack. - jsr release_DATA - jsr assert_CLOCK + jsl release_DATA + jsl assert_CLOCK ; Now wait for listener ack. Of course, if there are ; multiple listeners, we can only know that one ack'd. @@ -352,10 +352,10 @@ clock$ ; TODO: ATN release timing appears to be semi-critical; we may need ; to completely change the code below. -ack$ jsr read_DATA +ack$ jsl read_DATA bcs ack$ clc - rts + rtl ; ; Wait for a byte of data to be read from the IEC port @@ -366,16 +366,16 @@ recv_data stz rx_eoi ; Wait for the sender to have a byte -wait1$ jsr read_CLOCK +wait1$ jsl read_CLOCK bcc wait1$ ; TODO: start and check a timer ; Signal we are ready to receive -ready$ jsr release_DATA +ready$ jsl release_DATA ; Wait for all other listeners to signal -wait2$ jsr read_DATA +wait2$ jsl read_DATA bcc wait2$ ; Wait for the first bit or an EOI condition @@ -383,7 +383,7 @@ wait2$ jsr read_DATA lda #0 ; counter wait3$ inc a beq eoi$ - jsr read_CLOCK + jsl read_CLOCK bcc recv$ adc #7 ; microseconds per loop bcc wait3$ @@ -392,10 +392,10 @@ eoi$ lda rx_eoi bmi error$ ; Ack the EOI - jsr assert_DATA - jsr sleep_20us - jsr sleep_20us - jsr sleep_20us + jsl assert_DATA + jsl sleep_20us + jsl sleep_20us + jsl sleep_20us ; Set the EOI flag. dec rx_eoi ; TODO: error on second round @@ -404,42 +404,42 @@ eoi$ lda rx_eoi bra ready$ error$ sec - rts + rtl recv$ ; Clock in the bits phx ldx #8 -wait_fall$ jsr read_CLOCK +wait_fall$ jsl read_CLOCK bcs wait_fall$ -wait_rise$ jsr read_CLOCK +wait_rise$ jsl read_CLOCK bcc wait_rise$ - jsr read_DATA + jsl read_DATA ror a dex bne wait_fall$ plx ; Ack - jsr sleep_20us - jsr assert_DATA + jsl sleep_20us + jsl assert_DATA ; Drives /usually/ work with a lot less, but ; I see failures on the SD2IEC on a status check ; after file-not-found when debugging is turned off. - jsr sleep_20us ; Seems to be missing the ack. - jsr sleep_20us ; Seems to be missing the ack. - jsr sleep_20us ; Seems to be missing the ack. - jsr sleep_20us ; Seems to be missing the ack. + jsl sleep_20us ; Seems to be missing the ack. + jsl sleep_20us ; Seems to be missing the ack. + jsl sleep_20us ; Seems to be missing the ack. + jsl sleep_20us ; Seems to be missing the ack. ; Return EOI in NV clc bit rx_eoi ora #0 - rts + rtl ;; ;; Public Functions @@ -458,7 +458,7 @@ iecll_ioinit php stz delayed - jsr init + jsl init bcs err$ plp @@ -481,8 +481,8 @@ iecll_talk php sep #0x30 ora #0x40 - jsr flush - jsr atn_release_data ; NOTE: does NOT drop ATN! + jsl flush + jsl atn_release_data ; NOTE: does NOT drop ATN! plp rtl @@ -498,12 +498,12 @@ iecll_talk_sa php sei sep #0x30 - jsr atn_common + jsl atn_common - jsr assert_DATA - jsr release_ATN - jsr release_CLOCK -1$ jsr read_CLOCK + jsl assert_DATA + jsl release_ATN + jsl release_CLOCK +1$ jsl read_CLOCK bcs 1$ ; TODO: should time out. plp @@ -521,8 +521,8 @@ iecll_listen php sep #0x30 ora #0x20 - jsr flush - jsr atn_release_data ; NOTE: does NOT drop ATN! + jsl flush + jsl atn_release_data ; NOTE: does NOT drop ATN! plp rtl @@ -538,8 +538,8 @@ iecll_listen_sa php sei sep #0x30 - jsr atn_common - jsr release_ATN + jsl atn_common + jsl release_ATN ; TODO: WARNING! No delay here! ; TODO: IMHO, should wait at least 100us to avoid accidental turn-around! @@ -569,8 +569,8 @@ iecll_untalk php ; TODO: track the state and cause calls to IECOUT to fail. ; pre-sets CLOCK IMMEDIATELY before the ATN ... again, TODO: makes no sense - jsr assert_CLOCK - jsr atn_release + jsl assert_CLOCK + jsl atn_release plp rtl @@ -587,8 +587,8 @@ iecll_unlisten php ; Detangled from C64 sources; TODO: compare with Stef's lda #0x3f - jsr flush - jsr atn_release + jsl flush + jsl atn_release plp rtl @@ -607,7 +607,7 @@ iecll_in php sei ; Disable interrupts sep #0x30 ; Switch to 8-bit registers - jsr recv_data + jsl recv_data ; NOTE: we'll just read from the eoi variable in a separate function ; We might need to return it here folded in with the data somwhow @@ -662,7 +662,7 @@ iecll_out php ; Send the old byte pha lda queue - jsr send + jsl send pla stz delayed @@ -680,9 +680,9 @@ iecll_reset: php sei sep #0x30 - jsr assert_RST - jsr sleep_1ms - jsr release_RST + jsl assert_RST + jsl sleep_1ms + jsl release_RST plp rtl \ No newline at end of file diff --git a/src/C256/interrupts.s b/src/C256/interrupts.s new file mode 100644 index 0000000..a5bfe0a --- /dev/null +++ b/src/C256/interrupts.s @@ -0,0 +1,144 @@ +;;; +;;; Assembly stubs for the interrupt handlers on the F256 +;;; +;;; NOTE: this is necessary since the F256 has only 256 bytes of flash mapped +;;; into bank 0, so we can have only the smallest amount of code there +;;; that we can get away with. +;;; + + .extern int_handle_nmi + .extern int_handle_irq + .extern _Dp, _Vfp + .extern _DirectPageStart + .extern _NearBaseAddress + + .section `$$interruptVector_0x00ffee`,text + .word hw_handle_irq + + .section `$$interruptVector_0x00ffea`,text + .word hw_handle_nmi + + .section code,root +hw_handle_irq: rep #48 + pha + phx + phy + pei dp:.tiny _Dp + pei dp:.tiny (_Dp+2) + pei dp:.tiny (_Dp+4) + pei dp:.tiny (_Dp+6) + pei dp:.tiny (_Dp+8) + pei dp:.tiny (_Dp+10) + pei dp:.tiny (_Dp+12) + pei dp:.tiny (_Dp+14) + pei dp:.tiny (_Dp+8) + pei dp:.tiny (_Dp+10) + + ; Save the caller's databank and direct page + ; TODO: this might change to being done only in the toolbox IRQ handler + phd + phb + + ; Set the toolbox's direct page + lda ##_DirectPageStart + tcd + + ; Set the toolbox's databank + lda ##.word2 _NearBaseAddress + stz dp:.tiny(_Vfp+2) + xba ; A upper half = data bank + pha + plb ; pop 8 dummy + plb ; set data bank + + ; Call the interrupt handlers + jsl int_handle_irq + + plb + pld + ply + sty dp:.tiny (_Dp+10) + ply + sty dp:.tiny (_Dp+8) + ply + sty dp:.tiny (_Dp+14) + ply + sty dp:.tiny (_Dp+12) + ply + sty dp:.tiny (_Dp+10) + ply + sty dp:.tiny (_Dp+8) + ply + sty dp:.tiny (_Dp+6) + ply + sty dp:.tiny (_Dp+4) + ply + sty dp:.tiny (_Dp+2) + ply + sty dp:.tiny _Dp + ply + plx + pla + rti + +hw_handle_nmi: rep #48 + pha + phx + phy + pei dp:.tiny _Dp + pei dp:.tiny (_Dp+2) + pei dp:.tiny (_Dp+4) + pei dp:.tiny (_Dp+6) + pei dp:.tiny (_Dp+8) + pei dp:.tiny (_Dp+10) + pei dp:.tiny (_Dp+12) + pei dp:.tiny (_Dp+14) + pei dp:.tiny (_Dp+8) + pei dp:.tiny (_Dp+10) + + ; Save the caller's databank and direct page + ; TODO: this might change to being done only in the toolbox IRQ handler + phd + phb + + ; Set the toolbox's direct page + lda ##_DirectPageStart + tcd + + ; Set the toolbox's databank + lda ##.word2 _NearBaseAddress + stz dp:.tiny(_Vfp+2) + xba ; A upper half = data bank + pha + plb ; pop 8 dummy + plb ; set data bank + + ; Call the interrupt handlers + jsl int_handle_nmi + + plb + pld + ply + sty dp:.tiny (_Dp+10) + ply + sty dp:.tiny (_Dp+8) + ply + sty dp:.tiny (_Dp+14) + ply + sty dp:.tiny (_Dp+12) + ply + sty dp:.tiny (_Dp+10) + ply + sty dp:.tiny (_Dp+8) + ply + sty dp:.tiny (_Dp+6) + ply + sty dp:.tiny (_Dp+4) + ply + sty dp:.tiny (_Dp+2) + ply + sty dp:.tiny _Dp + ply + plx + pla + rti diff --git a/src/C256/macros.h b/src/C256/macros.h new file mode 100644 index 0000000..5f1cd4f --- /dev/null +++ b/src/C256/macros.h @@ -0,0 +1,86 @@ +#ifndef __MACROS_H +#define __MACROS_H + +#ifdef __CALYPSI_ASSEMBLER__ + +#ifdef __CALYPSI_CODE_MODEL_SMALL__ + +#define libcode code + +call .macro dest + jsr \dest + .endm + +return .macro + rts + .endm + +jump .macro dest + jmp \dest + .endm + +#elif defined(__CALYPSI_CODE_MODEL_COMPACT__) + +#define libcode compactcode + +call .macro dest + jsr .kbank \dest + .endm + +return .macro + rts + .endm + +jump .macro dest + jmp .kbank \dest + .endm + +#else + +#define libcode farcode + +call .macro dest + jsl \dest + .endm + +return .macro + rtl + .endm + +jump .macro dest + jmp long:\dest + .endm + +#endif // __CALYPSI_CODE_MODEL_SMALL__ + +// ---------------------------------------------------------------------- +// +// Define code and data model used. This is to add a bit of safety in +// case the way a file is assembled is combined with the wrong run-time. +// +// ---------------------------------------------------------------------- + +#if defined(__CALYPSI_DATA_MODEL_SMALL__) + .rtmodel dataModel,"small" +#elif defined (__CALYPSI_DATA_MODEL_MEDIUM__) + .rtmodel dataModel,"medium" +#elif defined(__CALYPSI_DATA_MODEL_LARGE__) + .rtmodel dataModel,"large" +#elif defined(__CALYPSI_DATA_MODEL_HUGE__) + .rtmodel dataModel,"huge" +#else +#pragma GCC error "unexpected data model" +#endif + +#if defined(__CALYPSI_CODE_MODEL_SMALL__) + .rtmodel codeModel,"small" +#elif defined(__CALYPSI_CODE_MODEL_COMPACT__) + .rtmodel codeModel,"compact" +#elif defined(__CALYPSI_CODE_MODEL_LARGE__) + .rtmodel codeModel,"large" +#else +#pragma GCC error "unexpected code model" +#endif + +#endif // __CALYPSI_ASSEMBLER__ +#endif // __MACROS_H diff --git a/src/Makefile b/src/Makefile index c1c3ff7..bf20ec6 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,8 +1,8 @@ # VPATH=.:../../module/Calypsi-remote-debug/src DEBUGGER=../module/Calypsi-remote-debug/src -UNIT := F256 -MEMORY := RAM +UNIT := F256K +MEMORY := ROM # Define OS-dependent variables @@ -44,20 +44,20 @@ else ifeq ($(UNIT),F256) CFLAGS_FOR_UNIT=-DMODEL=2 -DCPU=255 --code-model large --data-model large ifeq ($(MEMORY),ROM) - LDFLAGS_FOR_UNIT=C256/flash-f256.scm clib-lc-ld.a --rtattr printf=medium + LDFLAGS_FOR_UNIT=C256/f256-flash.scm clib-lc-ld.a --rtattr printf=medium else - LDFLAGS_FOR_UNIT=C256/ld_lc_f256.scm clib-lc-ld.a --rtattr printf=medium + LDFLAGS_FOR_UNIT=C256/f256-ld_lc.scm clib-lc-ld.a --rtattr printf=medium endif else ifeq ($(UNIT),F256K) CPU=w65816 C_SRCS_DEBUGGER=$(DEBUGGER)/agent.c $(DEBUGGER)/c256-uart.c $(DEBUGGER)/low_level_WDC65816.s - SRCS_FOR_UNIT=C256/jumptable.s C256/io_stubs.c C256/extras.s C256/iecll.s - CFLAGS_FOR_UNIT=-DMODEL=2 -DCPU=255 --code-model large --data-model large + SRCS_FOR_UNIT=C256/jumptable.s C256/io_stubs.c C256/extras.s C256/iecll.s C256/interrupts.s C256/f256-cstartup.s + CFLAGS_FOR_UNIT=-DMODEL=17 -DCPU=255 --code-model large --data-model large ifeq ($(MEMORY),ROM) - LDFLAGS_FOR_UNIT=C256/flash-f256.scm clib-lc-ld.a --rtattr printf=medium + LDFLAGS_FOR_UNIT=C256/f256-flash.scm clib-lc-ld.a --rtattr printf=medium --cstartup=f256 else - LDFLAGS_FOR_UNIT=C256/ld_lc_f256.scm clib-lc-ld.a --rtattr printf=medium + LDFLAGS_FOR_UNIT=C256/f256-ld_lc.scm clib-lc-ld.a --rtattr printf=medium --cstartup=f256 endif endif @@ -69,8 +69,8 @@ ifeq ($(CPU),w65816) endif INCLUDES=-I. -I./include -CFLAGS=$(INCLUDES) $(CFLAGS_FOR_UNIT) # -l -D_CALYPSI_MCP_DEBUGGER -ASFLAGS=$(INCLUDES) +CFLAGS=$(INCLUDES) $(CFLAGS_FOR_UNIT) -l # -l -D_CALYPSI_MCP_DEBUGGER +ASFLAGS=$(INCLUDES) --data-model large --code-model large ifeq ($(MEMORY),ROM) LDFLAGS=--rom-code $(LDFLAGS_FOR_UNIT) --list-file toolbox.map @@ -89,7 +89,7 @@ toolbox.s37: $(OBJS) $(LIBS) $(LD) $(LDFLAGS) --output-format s37 -o $@ $^ toolbox.raw: $(OBJS) $(LIBS) - $(LD) $(LDFLAGS) --output-format raw -o $@ $^ + $(LD) $(LDFLAGS) --raw-multiple-memories --output-format raw -o $@ $^ dev/devices.a: $(MAKE) --directory=dev diff --git a/src/dev/interrupts_f256.c b/src/dev/interrupts_f256.c index 4c1ff87..c14e219 100644 --- a/src/dev/interrupts_f256.c +++ b/src/dev/interrupts_f256.c @@ -469,8 +469,10 @@ SYSTEMCALL void int_clear(unsigned short n) { * * NOTE: this routine might not be fast enough in C and have to be replaced by hand written * assembly code... but we will try it this way first. + * + * __attribute__((interrupt(0xffee))) */ -__attribute__((interrupt(0xffee))) void int_handle_irq() { +void int_handle_irq() { uint8_t mask_bits = 0; // Process any pending interrupts in group 0 @@ -525,6 +527,8 @@ __attribute__((interrupt(0xffee))) void int_handle_irq() { /** * @brief Handle incomming NMI signal + * + * __attribute__((interrupt(0xffea))) */ -__attribute__((interrupt(0xffea))) void int_handle_nmi() { +void int_handle_nmi() { } \ No newline at end of file diff --git a/src/toolbox.c b/src/toolbox.c index f91a8b2..fb48339 100644 --- a/src/toolbox.c +++ b/src/toolbox.c @@ -79,13 +79,6 @@ void initialize() { long target_jiffies; int i; short res; - - *vky_brdr_ctrl = 0x01; - *vky_brdr_col_red = 0x80; - *vky_brdr_col_green = 0x00; - *vky_brdr_col_blue = 0x00; - *vky_brdr_size_x = 0x08; - *vky_brdr_size_y = 0x08; /* Setup logging early */ log_init(); @@ -186,8 +179,8 @@ void initialize() { INFO("Timers initialized"); /* Initialize the real time clock */ - rtc_init(); - INFO("Real time clock initialized"); + // rtc_init(); + // INFO("Real time clock initialized"); /* Enable all interrupts */ int_enable_all(); @@ -487,24 +480,28 @@ int main(int argc, char * argv[]) { test_sysinfo(); - printf("Initializing IEC\n"); - result = iec_init(); - if (result != 0) { - printf("Error initializing IEC.\n"); - } + printf("Foenix Toolbox v%d.%04d.%04d\n", VER_MAJOR, VER_MINOR, VER_BUILD); + test_kbd(); + + // printf("Initializing IEC\n"); + // result = iec_init(); + // if (result != 0) { + // printf("Error initializing IEC.\n"); + // } // printf("Attempting to get status for IEC drive #8: "); // short n = iec_status(8, message, 256); // printf("\"%s\"\n", message); - printf("Attempting to write to the printer.\n"); - iec_print(4, "\e1THIS IS PRINTED FROM AN F256K OVER THE IEC PORT!\r"); - printf("Done.\n"); + // printf("Attempting to write to the printer.\n"); + // iec_print(4, "\e1THIS IS PRINTED FROM AN F256K OVER THE IEC PORT!\r"); // Attempt to start up the user code // log(LOG_INFO, "Looking for user startup code:"); // boot_launch(); + printf("Done.\n"); + #ifdef _CALYPSI_MCP_DEBUGGER extern int CalypsiDebugger(void); CalypsiDebugger(); // This will not return diff --git a/src/toolbox.csv b/src/toolbox.csv new file mode 100644 index 0000000..e299297 --- /dev/null +++ b/src/toolbox.csv @@ -0,0 +1,17 @@ +"00","toolbox-00.bin" +"01","toolbox-01.bin" +"02","toolbox-02.bin" +"03","toolbox-03.bin" +"04","toolbox-04.bin" +"05","toolbox-05.bin" +"06","toolbox-06.bin" +"07","toolbox-07.bin" +"08","toolbox-08.bin" +"09","toolbox-09.bin" +"0A","toolbox-0A.bin" +"0B","toolbox-0B.bin" +"0C","toolbox-0C.bin" +"0D","toolbox-0D.bin" +"0E","toolbox-0E.bin" +"0F","toolbox-0F.bin" +"3F","toolbox-3F.bin" diff --git a/src/version.h b/src/version.h index beac75c..6f591dc 100644 --- a/src/version.h +++ b/src/version.h @@ -7,6 +7,6 @@ #define VER_MAJOR 1 #define VER_MINOR 0 -#define VER_BUILD 0 +#define VER_BUILD 2 #endif diff --git a/tests/make_test.bat b/tests/make_test.bat new file mode 100644 index 0000000..0ee46a0 --- /dev/null +++ b/tests/make_test.bat @@ -0,0 +1,2 @@ +@echo off +64tass -x -f -b --list test_boot.lst -o test_boot.bin test_boot.s \ No newline at end of file diff --git a/tests/test.csv b/tests/test.csv new file mode 100644 index 0000000..4f5ebcb --- /dev/null +++ b/tests/test.csv @@ -0,0 +1 @@ +"3F","test_boot.bin" diff --git a/tests/test_boot.s b/tests/test_boot.s new file mode 100644 index 0000000..2e20700 --- /dev/null +++ b/tests/test_boot.s @@ -0,0 +1,65 @@ +;;; +;;; Test booting the F256k2e... +;;; + + .cpu "65816" + +vky_border_ctrl = $f01004 +vky_border_blue = $f01005 +vky_border_green = $f01006 +vky_border_red = $f01007 +vky_border_size_x = $f01008 +vky_border_size_y = $f01009 + +led_pwr_blue = $f016a7 +led_pwr_green = $f016a8 +led_pwr_red = $f016a9 + +* = $ff00 + +start: clc + xce + + sep #$30 + .as + .xs + + lda #$01 + sta @l vky_border_ctrl + + lda #$ff + sta @l vky_border_red + sta @l led_pwr_red + + lda #0 + sta @l vky_border_blue + sta @l led_pwr_blue + sta @l vky_border_green + sta @l led_pwr_green + + lda #16 + sta @l vky_border_size_x + sta @l vky_border_size_y + +loop: nop + bra loop + +not_impl: rti + +* = $ffe4 + +hcop: .word <>not_impl +hbrk: .word <>not_impl +habort: .word <>not_impl +hnmi: .word <>not_impl + .word 0 +hirq: .word <>not_impl + +* = $fff4 + +ehcop: .word <>not_impl + .word 0 +ehabort: .word <>not_impl +ehnmi: .word <>not_impl +hreset: .word <>start +ehirq: .word <>not_impl diff --git a/utils/srec2bin.py b/utils/srec2bin.py new file mode 100644 index 0000000..7ecdd6a --- /dev/null +++ b/utils/srec2bin.py @@ -0,0 +1,66 @@ +# +# Convert Motorola SREC to binary ROM files (both a 512KB main file and 8KB sector files for non-empty sectors) +# +# usage: python srec2bin.py +# + +import re + +def srec_add_data(rom, address, data): + """Add a line of data from an SREC file (hex digits) to the binary image at the given address""" + data_bytes = bytearray.fromhex(data) + for i in range(len(data_bytes)): + rom[address + i] = data_bytes[i] + +def srec_process(rom, line): + """Process a line of a Motorola SREC file""" + + m = re.match(r'^S(\d)([0-9a-fA-F]{2})([0-9a-fA-F]+)$', line) + if m: + type = int(m.group(1), 10) + size = int(m.group(2), 16) + addr_data_chk = m.group(3) + + if type == 3: + m2 = re.match(r'^([0-9a-fA-F]{8})([0-9a-fA-F]+)([0-9a-fA-F]{2})$', addr_data_chk) + if m2: + address = int(m2.group(1),16) + data = m2.group(2) + chksum = m2.group(3) + if address >= rom_base: + srec_add_data(rom, address - rom_base, data) + +def bank_has_data(rom, bank): + """Check to see if a bank is empty (all 0xFF)""" + start = bank * 8192 + end = start + 8192 + + for i in range(start, end): + if rom[i] != 0xff: + # Return True if we find a non-blank entry + return True + + return False + +rom_size = 512 * 1024 +rom_base = 0xf80000 + +input_file = "toolbox.s37" +output_file = "toolbox.bin" + +rom_image = bytearray(rom_size) +for i in range(rom_size): + rom_image[i] = 0xff + +with open(input_file, "r") as input: + for line in input: + srec_process(rom_image, line) + +with open("toolbox.bin", "wb") as output: + output.write(rom_image) + +for bank in range(0, 64): + if bank_has_data(rom_image, bank): + output_name = "toolbox-{:02X}.bin".format(bank) + with open(output_name, "wb") as output: + output.write(rom_image[bank * 8192:bank * 8192 + 8192]) \ No newline at end of file