zxuno-git/utils/rtc.asm

164 lines
6.6 KiB
NASM

; rtc.asm - return date for esxdos call on $2700
;
; Copyright (C) 2022 Antonio Villena/McLeod_ideafix
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, version 3.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <https://www.gnu.org/licenses/>.
;
; Compatible compilers:
; SjAsmPlus, <https://github.com/z00m128/sjasmplus>
;
;-------------------------------------------------------------------------------
output RTC.SYS
define SCL0SDA0 00b
define SCL0SDA1 01b
define SCL1SDA0 10b
define SCL1SDA1 11b
define I2CADDR_R $a3
define I2CADDR_W $a2
include zxuno.def
include esxdos.def
org $2700
ld bc, ZXUNOADDR
ld a, i2creg
out (c), a ; selecciono el registro I2C.
inc b
ld hl, Params
SendW ld a, SCL1SDA1 ;Transmito E bytes apuntados por HL al bus I2C (escritura)
out (c), a ;Envío condición de START al bus (SDA a 0 mientras mantengo SCL a 1)
dec a ;ld a,SCL1SDA0
out (c), a
ld a, I2CADDR_W ;Envío la dirección I2C de escritura del RTC
call SendByte
ld a, 2 ;y en un bucle, me pongo a enviar uno tras otro, los E bytes a los que apunta HL
call SendByte
call Send0 ;después de enviar el ultimo byte, envío la condición de STOP al bus (envío un 0, con lo que se queda SDA a 0 y SCL a 1, y a continuación pongo SDA a 1)
inc d ;ld d, SCL1SDA1
out (c), d
ld e, 7
ld a, SCL1SDA1 ;Recibo E bytes que se guardarán a partir de donde indique HL
out (c), a
dec a ;Envío la condición de START al bus I2C
out (c), a
ld a, I2CADDR_R ;Envío la dirección I2C de lectura del RTC
call SendByte
LoopSendR call nz, Send0 ;enviar un ACK es enviar un 0
call RcvByte ;y en un bucle, me pongo a recibir un byte detrás de otro. Tras cada byte, menos el último, envío ACK
ld (hl), a
inc hl
dec e
jr nz, LoopSendR
call Send1 ;aquí llego si acabo de recibir el último byte. Envío un NACK (un 1)
call Send0 ;y a continuación envío la condición de STOP al bus I2C
inc d ;ld d, SCL1SDA1
out (c), d
ld hl, Params
ld b, %01111110 ;Segundos
call BCDtobin
rrca ;Segundos / 2
ld e, a ;Guarda en E
ld b, %01111111 ;Minutos
call BCDtobin
rrca
rrca
rrca
ld d, a
and %11100000
or e
ld e, a
ld b, %00111111 ;Horas
call BCDtobin
rlca
rlca
rlca
xor d
and %11111000
xor d
ld d, a
push de
ld b, %00111111 ;Días
call BCDtobin
ld e, a
inc hl
ld b, %00011111 ;Siglo/Mes
ld c, (hl)
call BCDtobin
rrca
rrca
rrca
ld d, a
and %11100000
or e
ld e, a
dec b
call BCDtobin
bit 7, c
jr z, Milnov
add 100
Milnov sub 80
rr d
adc a, a
ld b, a
ld c, e
pop de
ret
BCDtobin ld a, (hl)
inc hl
and b
ld b, 0
Repite inc b
sub $10
jr nc, Repite
Suma10 add a, 10
djnz Suma10
add a, 6
ret
Params db 0, 0, 0, 0, 0, 0, 0 ;La hora a la que quieres poner el reloj
; S M H D W Mo Y En lectura, estos datos se machacan con la hora leída del RTC
SendByte scf ;Enviar un byte por I2C. Byte en A. BC=puerto de datos del ZXUNO ya
adc a, a ;apuntando a I2CREG. Usa y modifica: A, D, flags
Trans call c, Send1
call nc, Send0
add a, a
jr nz, Trans
Send1 ld d, SCL0SDA1
out (c), d
ld d, SCL1SDA1
out (c), d ;Transmito un bit 1 para dejar SDA en modo de alta impedancia y que el receptor puedo ponerlo a 0
ld d, SCL0SDA1
out (c), d
ret ; S flag 0 = ACK received, S flag 1 = ACK not received
RcvByte ld a, 1 ;byte a recibir en A. BC=puerto de datos del ZXUNO ya apuntando a I2CREG. Usa y modifica: A, D, flags
RcvBit call Send1 ;envío un pulso de reloj con SDA a alta impedancia
in d, (c) ;el RTC pone aquí el dato (1 o 0) y lo leo (está en bit 7 de D)
sll d ;bit 7 a carry
adc a, a ;carry a bit 0 de A, y desplazo a la izquierda
jr nc, RcvBit
ret
Send0 ld d, SCL0SDA0
out (c), d
ld d, SCL1SDA0
out (c), d
ld d, SCL0SDA0
out (c), d
ret