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: 2023/04/19 16:59 por 127.0.0.1