Herramientas de usuario

Herramientas del sitio


sistema_de_reloj

Reloj del zak80

La idea es hacer un sistema versátil, que provea un reloj estable a una frecuencia de funcionamiento (4MHz), asi como herramientas para desarrollo; un reloj automático a 1Hz, y un reloj manual por interruptor.

Para ello se utilizará un microcontrolador AVR, serie attiny (attiny24 versión final, attiny2313 para desarrollo) que se encargará de leer unos interruptores de configuración al inicio, y seleccionar el modo de funcionamiento adecuado. Además este microcontrolador controlará la señal de reset del z80, manteniendolo en reset durante unos milisegundos al inicio, y reseteandolo cuando el mismo sea reseteado.

Para ello, se ha diseñado el siguiente código ensamblador, para garantizar timings adecuados:

reloj.asm
; z80 clock generator
; David Pello 2011
; generates a standard clock (half clk in), a ~1Hz clock
; and a manual clock (using a switch)
 
; attiny2313 version, PB3 reset output, PB2 clock output
; PB0 and PB1 mode select. PB4 external clock input
;
 
.include "tn2313def.inc"
.cseg
.org 0
    ; interrupt vectors
    rjmp    reset               ; reset interrupt
    reti                        ; INT0 interrupt
    reti                        ; PCINT0 interrupt
    reti                        ; Timer 0 overflow interrupt
    reti                        ; EE_RDY interrupt
    reti                        ; ANA_COMP interrupt
    reti                        ; TIM0_COMPA interrupt
    reti                        ; TIM0_COMPB interrupt
    reti                        ; WDT interrupt
    reti                        ; ADC interrupt
 
reset:
    cli                         ; clear interrupts
    ldi     r16, 0b10000000     ; clock preescaler enable sequence
    out     CLKPR, r16
    ldi     r16, 0b00000001     ; clock preescaler = 2 (16/2) = 8MHz
    out     CLKPR, r16
 
    ldi     r16, 0b00001100     ; PORTB, PB2 output (clock), PB3 output(reset), PB0 & PB1 inputs (clocksel), PB4 input (clock switch)
    out     DDRB, r16
    cbi     PORTB, 3            ; PB3 = 0, z80 on reset.
 
    ; read clocksel
    in      r17, PINB
    andi    r17, 0b00000011     ; we have selection in r17
 
    ; wait 10ms to come out from reset
    rcall   delay_10ms        
 
    ; check clocksel
    cpi     r17, 0x00           ; 00, 4 MHz mode
    breq    clk_4mhz
 
    cpi     r17, 0x01           ; 01, 1 Hz mode
    breq    clk_1hz
 
    cpi     r17, 0x02           ; 10, Manual mode
    breq    clk_manual
 
halt:                           ; 11, halt mode, no clock
    sleep
    rjmp    halt
 
; 4MHz selected
clk_4mhz:
    ldi      r16, 0b01000011    ; Timer0, toggle OC0A on compare match, OC0B disconected, waveform generator Fast PWM mode
    out      TCCR0A, r16        ; set
    ldi      r16, 0b00001001    ; FOC0A and FOC0B unset, waveform Fast PWM, preescaler = 1 
    out      TCCR0B, r16        ; start oscillate
    ldi      r16, 0x01          ; OCR0A = 1, toggle OC0A each 2 timer interrupts, freq = clk/4 = 4Mhz
    out      OCR0A, r16         ; set
    sbi      PORTB, 3           ; come out from reset
    sei                         ; interrups activated
 
loop_auto:
    sleep                       ; do nothing, interrupts take care
    rjmp    loop_auto
 
 
; 1Hz selected
clk_1hz:
    sbi     PORTB, 3            ; come out from reset
loop_1hz:
    sbi     PORTB, 2            ; clock high
    rcall   delay_500ms
    cbi     PORTB, 2            ; clock low
    rcall   delay_500ms         
    rjmp    loop_1hz
 
 
; manual mode selected
clk_manual:
    sbi     PORTB, 3            ; come out from reset
loop_manual:
    in      r18, PINB           ; read button
    andi    r18, 0b00010000
 
    cpi     r18, 0b00010000
    breq    clk_manual_in
 
    ; no press, continue
    rjmp    loop_manual
 
clk_manual_in:
    ; we got a pulse, send clock
    sbi     PORTB, 2            ; high
    rcall   delay_10ms         ; wait
    cbi     PORTB, 2            ; low
    ; wait...
    rcall   delay_500ms
    rjmp    loop_manual
 
 
 
; delay 10ms @ 8MHz
delay_10ms:                    
    ; delaying 79998 cycles:
     ldi  r20, $86
d10msl0:
     ldi  r21, $C6
d10msl1:
     dec  r21
     brne d10msl1
     dec  r20
     brne d10msl0
; ----------------------------- 
; delaying 2 cycles:
    nop
    nop 
    ret
 
 
; delay 0.5s @ 8MHz
delay_500ms:
; delaying 3999996 cycles:
    ldi  r20, $24
d500msl0:  
    ldi  r21, $BC
d500msl1:  
    ldi  r22, $C4
d500msl2:
    dec  r22
    brne d500msl2
    dec  r21
    brne d500msl1
    dec  r20
    brne d500msl0
; ----------------------------- 
; delaying 3 cycles:
    ldi  r20, $01
d500msl3:
    dec  r20
    brne d500msl3
; ----------------------------- 
; delaying 1 cycle:
    nop
    ret

Salida a 4MHz:

sistema_de_reloj.txt · Última modificación: 08/02/2017 21:21 (editor externo)