hpr3812 :: PeePaw's computer does nothing
a z80 nop test
Hosted by Brian in Ohio on Tuesday, 2023-03-14 is flagged as Clean and is released under a CC-BY-SA license.
z80, forth, retrocomputer.
(Be the first).
The show is available on the Internet Archive at: https://archive.org/details/hpr3812
Listen in ogg,
spx,
or mp3 format. Play now:
Duration: 00:25:27
general.
peepaws computer does nothing
- who's peepaw, whats the goal
- to build and understand the inner workings of an 8 bit computer and maybe one day pass it on to a grand kid
- this episode -nop test
- do a nop test, that is get the z80 up and running executing the nop instruction
- using the facilities of an arduino mega board running flash forth to do that, talk about pictures
- why? flash forth is interactive, without being such a big application itself. Happily runs on an atmega328
- why the mega, oodles and oodles of io, so emulating hardware should be a snap
- use the microcontroller board to provide 5 volts, clock signal and data to get the z80 up and running
- use the logic probe to see if there is activity on the address bus
- wiring up
- hot glued solderless breadboard on to an arduino mega protoshield, white wire is the logicprobe input
- power and ground first
- clock, blue
- control lines int, nmi, wait busrq and reset
- orange wires data bus
- address lines go around the chip clockwise from the clock signal (blue wire) we'll be probing A0, next to the ground line
1.logicprobe.jpg
2.power.jpg
3.clock.jpg
4.control.signals.jpg
5.data.jpg
6.ready.to.probe.jpg
z80-pinout.jpg
2560-pinout.jpg
Click the thumbnail
to see the full-sized image
- fixing some words, refactoring some words, defining new words
- fixed the data processing word to us the input on pin e4 (digital 2) not the output on pin h6 (digital 9)
- changed freq= some value to simply pulse, not interested in the specific frequency
- split clock and logic probe init words
- added some words to control the reset line reset and run
- added a word step that allows for single clock pulses
- the test, mega board plugged into laptop, seral terminal running
- spool up the logic probe
- spool up the microcontroller board setting up a port to provide data on the z80 data bus (rudimentary rom)
- add 5 volts
- initialize and start the clock
- probe the clock line
- probe a0 line
- a little more to see what else we can discern
- single step to reset
- probe m1
- single step to reset
- add halt instruction
- probe halt line
- this is output captured from the tests run on the show. lines that
begin with a back slash are comments used as narration
ok<#,ram>
is the forth interpreter reporting it has successfully processed the proceeding word(s), including comments pulse, high and low are output from the logicprobe, all other words are defined in the source text and the end of the notes
E FlashForth 5 ATmega2560 13.06.2022
\ initialize the logic probe ok<#,ram>
logicprobe.init ok<#,ram>
\ initialize the clock ok<#,ram>
clock.init ok<#,ram>
\ initialize arduinomega ports that interact with z80 ok<#,ram>
z80.ports.init ok<#,ram>
\ add power on the board ok<#,ram>
\ probe the clock pin to see if there is activity ok<#,ram>
sample
pulse ok<#,ram>
\ success! ok<#,ram>
\ probe adrress line A0, pin 30 on the z80 ok<#,ram>
sample
pulse ok<#,ram>
\ pulse means there is activity on the bus ok<#,ram>
\ stop the clock and probe A0 again, should see either a static high or low
signal ok<#,ram>
stop.clock sample
low ok<#,ram>
\ now move logic probe to pin 27, the M1 signal ok<#,ram>
\ put the z80 in reset and give three clock steps ok<#,ram>
reset ok<#,ram>
step ok<#,ram>
step ok<#,ram>
step ok<#,ram>
\ the z80 should be reset, now put in run ok<#,ram>
run ok<#,ram>
\ now single step the clock to see the M1 ok<#,ram>
\ signal go from high to low as the z80 begins ok<#,ram>
\ fetching data fro the data bus at address 0 ok<#,ram>
step sample
high ok<#,ram>
step sample
high ok<#,ram>
step sample
low ok<#,ram>
step sample
low ok<#,ram>
step sample
high ok<#,ram>
\ success! the M1 signal is working as expected ok<#,ram>
\ now reset the z80 and see what happens when ok<#,ram>
\ we give a different instruction this time hex 76 ok<#,ram>
\ the halt instruction. We should see the halt signal go from ok<#,ram>
\ high to low ok<#,ram>
reset step step step ok<#,ram>
\ put hat instruction on data lines ok<#,ram>
$76 DATA c! ok<#,ram>
\ now run mode ok<#,ram>
run ok<#,ram>
\ step clock and sample pin 18 the halt line ok<#,ram>
step sample
high ok<#,ram>
step sample
high ok<#,ram>
step sample
high ok<#,ram>
step sample
high ok<#,ram>
step sample
high ok<#,ram>
step sample
low ok<#,ram>
step sample
low ok<#,ram>
\ 4 clock cycles and halt line goes low and stays low, success! ok<#,ram>
\ thanks for listening ok<#,ram>
- Forth source code
-logicprobe
marker -logicprobe
variable Compare
variable Count
$100 constant PINH
$101 constant DDRH
$102 constant PORTH
$a0 constant TCCR4A
$a1 constant TCCR4B
$a8 constant OCR4A
$2c constant PINE
$2d constant DDRE
$2e constant PORTE
$6a constant EICRB
$3d constant EIMSK
: ext4.irq ( -- ) Count @ 1+ Count ! ;i
: logicprobe.init ( -- )
%0 DDRE c! \ e input
%0000.0010 EICRB mset \ falling edge
['] ext4.irq #6 int! \ attach interrupt
;
: clock.init ( -- )
1249 Compare ! \ 100 hz
%0000.1000 DDRH mset \ h3 output
%0100.0000 TCCR4A c! \ toggle d6, ph3 on compare match
%0000.1011 TCCR4B c! \ set ctc mode, clk/64
Compare @ OCR4A ! \ set compare value
;
\ helper words
: start.clock ( -- ) %0100.0000 TCCR4A c! %0000.1011 TCCR4B c! ;
: stop.clock ( -- ) %0000.0000 TCCR4A c! %0000.0000 TCCR4B c! ;
: set.frequency ( n -- ) OCR4A ! ; \ set compare value
: pin.high ( -- ) %0000.1000 PORTH mset ;
: pin.low ( -- ) %0000.1000 PORTH mclr ;
: open.gate ( -- ) 0 Count ! %0001.0000 EIMSK mset ;
: close.gate ( -- ) %0001.0000 EIMSK mclr ;
: process.data ( -- )
Count @ 1-
Count !
Count @ 0 > if
\ cr ." freq=" 10 * .
cr ." pulse"
else
%0001.0000 PINE mtst if
cr ." high"
else
cr ." low"
then then
;
: wait 100 ms ;
: sample ( -- ) open.gate wait close.gate process.data ;
\ nop tester
-nop
marker -nop
$20 constant PINA
$21 constant DDR.DATA
$22 constant DATA
$23 constant PINB
$24 constant DDRB
$25 constant PORTB
$2f constant PINF
$30 constant DDRF
$31 constant PORTF
%0000.0001 constant WAIT
%0000.0010 constant BUSRQ
%0000.0100 constant RESET
%0001.0000 constant INT
%0010.0000 constant NMI
: z80.ports.init ( -- )
\ data port output
$ff DDR.DATA c!
\ control signals, output
NMI INT or DDRB mset
WAIT BUSRQ RESET or or DDRF mset
\ nop instruction on data port
$ff DATA mclr
\ control lines high
NMI INT or PORTB mset
WAIT BUSRQ RESET or or PORTF mset
;
: reset ( -- ) RESET PORTF mclr ;
: run ( -- ) RESET PORTF mset ;
: step ( -- ) pin.high 1 ms pin.low ;
\ logicprobe.init
\ clock.init
\ z80.ports.init
\ sample