Skip to content

Commit

Permalink
4.7.0 add fn_clock interface and atari/apple2 cc65 implementations
Browse files Browse the repository at this point in the history
  • Loading branch information
markjfisher committed Sep 20, 2024
1 parent 0cbbc3c commit df98441
Show file tree
Hide file tree
Showing 15 changed files with 421 additions and 28 deletions.
4 changes: 4 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## [Unreleased]

## [4.7.0] - 2024-09-20

- [clock] a simple clock library to interface with FujiNet clock device with atari/apple2 (cc65) implementations

## [4.6.2] - 2024-09-15

- [apple2 bus] refactor all sp_get_xxx functions, moving common code into sp_find_device
Expand Down
22 changes: 11 additions & 11 deletions apple2/src/bus/cc65/sp_find_device.s
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

.export device_type_id
.export device_count
.export device_id_idx
.export _device_id_idx
.export tmp_orig_type

.import _sp_cmdlist
Expand All @@ -15,12 +15,11 @@
.import pusha
.import negax
.import return0
.import return1

.include "sp.inc"
.include "zp.inc"

; bool sp_find_device();
; uint8_t sp_find_device();
; device_type_id contains the type id to search for
; where type_id is the internal fujinet device type_id:
; $10 = fujinet
Expand Down Expand Up @@ -69,7 +68,7 @@ have_count:
sta device_count

lda #$01
sta device_id_idx
sta _device_id_idx
device_loop:
jsr pusha ; the current Device ID
lda #$03
Expand All @@ -84,12 +83,12 @@ device_loop:

; found it, so return the current index
ldx #$00
lda device_id_idx
lda _device_id_idx
rts

not_found_yet:
inc device_id_idx
lda device_id_idx
inc _device_id_idx
lda _device_id_idx
cmp device_count
bcc device_loop
beq device_loop
Expand Down Expand Up @@ -123,9 +122,11 @@ id_loc1 = *-2

beq not_found

; found it from searching, so return success after setting the id
; found it from searching, so return the id after setting it
jsr set_id
jmp return1
ldx #$00
cmp #$00 ; set status registers for the return based on A's id value
rts

not_found:
tax ; set x to 0
Expand All @@ -136,9 +137,8 @@ id_loc2 = *-2

rts


.bss
device_type_id: .res 1
device_count: .res 1
device_id_idx: .res 1
_device_id_idx: .res 1
tmp_orig_type: .res 1
14 changes: 5 additions & 9 deletions apple2/src/bus/cc65/sp_find_fuji.s
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,10 @@
.import _sp_payload
.import _sp_status

.import device_id_idx
.import _device_id_idx
.import device_count

.import pusha
.import return0
.import return1

.macpack cpu

; uint8_t sp_get_fuji_id()
_sp_get_fuji_id:
Expand All @@ -35,7 +31,7 @@ not_found_by_id:
; assumes device_count is set from previous search by ID
try_fallback:
lda #$01
sta device_id_idx
sta _device_id_idx

device_loop:
jsr pusha ; the current Device ID
Expand Down Expand Up @@ -63,12 +59,12 @@ device_loop:

; found it, so return the current index
ldx #$00
lda device_id_idx
lda _device_id_idx
bne :+

not_found_yet:
inc device_id_idx
lda device_id_idx
inc _device_id_idx
lda _device_id_idx
cmp device_count
bcc device_loop
beq device_loop
Expand Down
3 changes: 0 additions & 3 deletions apple2/src/bus/cc65/sp_read.s
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@

.import _sp_cmdlist
.import sp_dispatch
.import _sp_nw_unit
.import _sp_payload

.import popa
.import sp_rw_common

.include "sp.inc"
Expand Down
70 changes: 70 additions & 0 deletions apple2/src/fn_clock/cc65/clock_get_time.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
.export _clock_get_time

.import _sp_count
.import _sp_get_clock_id
.import _sp_payload
.import _sp_status

.import incsp2
.import popax
.import pusha
.import return0
.import return1

.include "macros.inc"
.include "zp.inc"

; uint8_t clock_get_time(uint8_t* time_data, TimeFormat format);

_clock_get_time:
sta time_format ; format, save it where we need it! saves a BSS byte

; get the device id of the clock, this is stored in _sp_clock_id, but also returned so we can check if it failed (0 is error)
jsr _sp_get_clock_id
bne got_id

; no clock found, return 1 as an error (FN_ERR_IO_ERROR)
; but first adjust the stack to remove the data pointer
error:
jsr incsp2
jmp return1

got_id:
; call sp_status(uint8_t dest, uint8_t statcode)
sta tmp1 ; save the clock device id

; convert the time format to the appropriate device specific code.
; SIMPLE_BINARY (0) -> 'T'
; PRODOS_BINARY (1) -> 'P'
; APETIME_TZ_BINARY (2) -> 'A'
; APETIME_BINARY (3) -> 'B'
; TZ_ISO_STRING (4) -> 'S'
; UTC_ISO_STRING (5) -> 'Z'

ldx #$00
time_format = *-1
; ensure the value is valid
cpx #$06
bcs error
pusha tmp1
lda code_table, x

jsr _sp_status
bne error

; results are in sp_payload, the clock data returned is small (4 to 26 bytes)
; _sp_count holds the number of bytes to copy from sp_payload, will always contain at least 1 byte (null terminator)
popax ptr1 ; read the time_data location into ptr1
ldy #$00
: lda _sp_payload, y
sta (ptr1), y
iny
cpy _sp_count
bne :-

jmp return0

.data
code_table:
.byte 'T', 'P', 'A', 'B', 'S', 'Z'

45 changes: 45 additions & 0 deletions apple2/src/fn_clock/cc65/clock_get_tz.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
.export _clock_get_tz

.import _sp_count
.import _sp_get_clock_id
.import _sp_payload
.import _sp_status

.import pusha
.import return0
.import return1

.include "macros.inc"
.include "zp.inc"

; uint8_t clock_get_tz(uint8_t* tz);

_clock_get_tz:
axinto tmp_tz_loc
jsr _sp_get_clock_id
bne got_id

error:
jmp return1

got_id:
; sp_status(clock_id, 'G')
jsr pusha
lda #'G'
jsr _sp_status
bne error

; copy sp_count bytes from payload into buffer, there's always at least 1 byte (null terminator)
mwa tmp_tz_loc, ptr1
ldy #$00
: lda _sp_payload, y
sta (ptr1), y
iny
cpy _sp_count
bne :-

jmp return0


.bss
tmp_tz_loc: .res 2
55 changes: 55 additions & 0 deletions apple2/src/fn_clock/cc65/clock_set_tz.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
.export _clock_set_tz

.import _fn_error
.import _memcpy
.import _sp_control
.import _sp_get_clock_id
.import _sp_payload
.import _strlen

.import incsp2
.import pusha
.import pushax
.import return1

.include "macros.inc"
.include "zp.inc"

; uint8_t clock_set_tz(char *tz);
_clock_set_tz:
axinto tmp_tz_ptr ; save the tz

; get the device id of the clock, this is stored in _sp_clock_id, but also returned so we can check if it failed (0 is error)
jsr _sp_get_clock_id
bne got_id

; no clock found, return 1 as an error (FN_ERR_IO_ERROR)
jmp return1

got_id:
jsr pusha ; store the destination device for call to sp_control

; copy timezone string into sp_payload, including the null terminator
pushax #(_sp_payload + 2)
pushax tmp_tz_ptr
jsr _strlen

clc
adc #$01
bcc :+
inx

: sta _sp_payload + 0
stx _sp_payload + 1
jsr _memcpy

; destination was stored on s/w stack already
lda #'T' ; set 'T'imezone
jsr _sp_control

; convert to fujinet error
jmp _fn_error


.bss
tmp_tz_ptr: .res 2
54 changes: 54 additions & 0 deletions atari/src/fn_clock/clock_get_time.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
.export _clock_get_time

.import _bus
.import _fuji_success

.import popax
.import return0

.include "device.inc"
.include "fujinet-clock.inc"
.include "macros.inc"
.include "zp.inc"

; uint8_t clock_get_time(uint8_t* time_data, TimeFormat format);
_clock_get_time:
tay
cpy #$06 ; was the format value in range?
bcc ok

; return an error status
jmp return0

ok:
lda t_clock_get_time_cmd, y
sta IO_DCB::dcomnd
lda t_clock_get_time_len, y
sta IO_DCB::dbytlo
popax IO_DCB::dbuflo

; the SIO clock device follows the APETIME device ID:
; #define SIO_DEVICEID_APETIME 0x45
mva #SIO_CLOCK_DEVICE_ID, IO_DCB::ddevic
mva #$40, IO_DCB::dstats
ldx #$00
stx IO_DCB::dunuse
stx IO_DCB::daux1
stx IO_DCB::daux2
stx IO_DCB::dbythi
inx ; x = 1
stx IO_DCB::dunit
inx ; x = 2 - as this is a FN non network call, we can keep this low
stx IO_DCB::dtimlo
jsr _bus
jmp _fuji_success

.rodata

; tables for the commands that have to be sent for the different types of time command
; see fuji_clock.h
t_clock_get_time_cmd:
.byte 'T', 'P', SIO_APETIMECMD_GETTZTIME, SIO_APETIMECMD_GETTIME, 'S', 'Z'

t_clock_get_time_len:
.byte 7, 4, 6, 6, 25, 25
Loading

0 comments on commit df98441

Please sign in to comment.