Day 9: The search for a working Assembler

My patience is running thin, but thanks to some folks on the RC2014 for pointing me in a few possible directions.

First of all.  Xmodem. Somehow my terminal settings got changed, and I couldn’t get files transferred.  You need RTS/CTS on, DTR/DSR on, and XON/XOFF off.  It’s still a miserable way to move files, but better than nothing.  There’s a way to do it with the CF card, but it’s… a lot of steps, and maybe needs a linux machine?

Second of all, there are like 3 or 4 different packages called “Z80ASM”.  Fortunately someone posted the manual for one, and I was able to find it. It’s Z80ASM by SLR Systems, which I found here.

I tried to run the wrong version of Z80ASM (which may very well have been intended for another platform), and I got the message BAD LOAD.  This means that you attempted to load a binary that’s larger than the Transient Program Area.  Shouldn’t have been surprised, as the binary was like 80k (Eeeuge in the realm of 8 bit micros).

Z80ASM is installed, and is at least throwing a copywright message (1983 – 1986) and an error, so I’m going to assume it’s ‘working’.  Now to understand what it wants.  There’s a host of options, presumably a fraction of which I should learn.  The most important thing to remember with this and a lot of other programs I’ve come across in the CP/M world is that it expects the file to have a specific suffix, and you need to tell it what drive(s) to use.  In order to compile the file TEST.Z80, you type ‘Z80ASM TEST.C’, telling it that the file named TEST.Z80 is on drive C (even if that’s your current drive).  This is a hold over from when everything was on floppies which were 180k – 360k in size.  There may have been a good chance that you wouldn’t have room for the compiler, the source, and the object file on the same disk.

Speaking of object files, this compiler spits out COM files directly, so you don’t need to run the LOAD command on HEX files.  Yay.

I took the worlds simplest example from the CP/M assembly book, and translated the few opcodes for Z80.

BDOS EQU 5 WCONF EQU 2 ORG 100H LD C,WCONF LD E,'$' CALL BDOS JP 0 END
Code language: JavaScript (javascript)

Sweet baby jebus, I finally have a working Z80 compiler.

(also, how useless is the code box in WordPress if it doesn’t accept TAB?!?)

Posted in Blinking Lights | Leave a comment

Day 8: Z80 Assembly in CP/M

I need to find a Z80 assembler that runs in CP/M (if such a thing exists), and I need to figure out how to get it onto my RC2014 that’s now running ROMWBW.

B:XM.COM is Xmodem, a popular tool for copying files via the serial port.  REMEMBER B: DRIVE IS READ ONLY! You have to write to another drive, like C: (ask me how many times I tried to XM to B: drive… ).

Xmodem is slllloooow, and for whatever reason, my serial terminal program doesn’t always initiate the transfer correctly (or it’s on the RC2014 side, who knows… )

As far as compiler implementations, there seems to be a few:

ZMAC – there’s a lot going on there, lots of files & libraries across multiple user directories.. gonna hold off on that one for now.

ZSM – This looks short, sweet & to the point.  Lets start there.  ZEN is also listed on that same site, maybe worth a look.  There’s a more recent version on the gitub page.

Z80ASM – found here

There’s a whole thread about it here

Other things I need to look into to make this machine a little more user friendly:

  • How can I add more drives?  ROMWBW works a lot different than the vanilla implementation.
  • How can I customize ZDE, or give it a start up macro file to fix a few things:
    • Don’t want to see CR’s as ‘>’ = ^OD
    • Set right margin to 80 = ^OR80
    • Set tab additional tab at columns 26 & 31 = ^OI26 & ^OI31
    • Cycle quiet (helps unstick the header on my physical terminal) ^OQ ^OQ
  • do I need a different debugger if I’m using Z80 mnemonics?

I’m getting nowhere with ZSM. No matter what I type I get “BAD LOAD”.  There seems to be a newer version here, but I’m fucking done with this nonsense for today.

Posted in Blinking Lights | Leave a comment

Day 7: Z80 Assembly, CP/M & Failing at stuff

This’ll be a short post, and in fact, I’m writing it the following day.  Yesterday I beat my head against the wall failing  & flailing.  I got some things blinking, so.. yay, but kept getting all sorts of compiler errors, even when some things sort of worked.

I entered a simple routine out of a book, ‘CP/M Assembly Language Programming’ by Ken Barbier.  The routine simply takes a character typed in and echos it back to the console, using CP/M’s built-in routines. To use these routines, you place the function’s number on the C register, using MVI, and then call BDOS at location 0005h.  Then I tried adding an OUT command to place those same characters on the LEDs at Port 0.  It actually worked, but I got errors. And then I realized:  The compiler is expecting 8080 assembly only, and I was typing in Z80 assembly. The out command in particular, is quite different.

In 8080 Assembler, OUT ##h takes whatever is on Register A, and puts it on the specified port. That’s it. Whereas Out in Z80 has a lot more options (which I will explore soon).

This page has a comprehensive list of all of the instructions for the Z80 & 8080, and shows how their mnemonics and methods differ.

I’d rather learn Z80 assembly, so lets see if we can’t find a Z80 assembler for CP/M.

 

Posted in Blinking Lights | Leave a comment

Day 6: RC2014

Changing domains for a bit, and getting back into my Z80 based RC2014 computer to learn how to manipulate the the timer.  The timer is a separate chip, a Z80 CTC, and the board is designed by Dr. Scott Baker.  I’m also going to steal some inspiration from Leonardo Miliani, who’s recently done some similar work on the CTC.  This video is also a good reference.

The CTC has 4 channels, each of which can operate as a counter or a timer.  It’s run off an external clock, has a built in prescaler of /16 or /256, and can be set to send interrupts.  Channels can be cascaded when longer times are needed.

Each of the 4 channels takes one or two control words (bytes), and in the case of sending a time constant, we have to send those 2 words consecutively.  This basic program sends the 1st control word which sets up the parameters of the channel, and the second word sends the time constant.  In the Timer mode, which is the mode we’re interested in, the time constant is the divisor.  The period of the Timer output is the Clock * the Prescaler * the Time Constant.

20 REM 30 REM COUNTER ATTEMPT USING SMBAKER BOARD AT 0x40 40 REM VARIABLES 50 REM 60 REM AD0 IS THE ADDRESS OF THE BOARD 70 AD0 = &H40 80 REM 90 REM CT00 IS THE CONTROL WORD 100 CT00 = 0 + 0 + 0 + 16 + 0 + 4 + 0 + 1 110 REM 120 REM CT01 IS THE TIME CONSTANT 130 GOSUB 1000 140 REM 150 REM OUTPUT CONTORL WORD, FOLLOWED BY TIME CONSTANT 160 OUT &H40,CT00 170 OUT &H40,CT01 180 GOTO 130 190 REM 200 REM 1000 REM SUB: GET INPUT 1010 KIN = INP(&H81) 1030 IF KIN = 32 THEN PRINT "ENTER TIME CONSTANT":INPUT CT01 1040 OUT 0,CT01 1050 RETURN
Code language: PHP (php)

The program will prompt for the time constant when the spacebar is pressed, and show the selected time constant in binary on the LEDs at port0.

Note that the pulses are super short, and of a fixed width. If you’re trying to do something slower with them, they may need to get stretched into something useful. At lower repetition rates, they aren’t really visible on a scope as a train of pulses.

Posted in Blinking Lights | Leave a comment

Day 5: Dual Range, Adjustable Multivibrator w/ Eurorack Out

OK, I swear, I’m done subjecting y’all to this dumb little circuit.  I’ve added a switchable range, which gets me down to ~ .1Hz, and another pair of transistors fro a clean output pulse of about 8v, suitable for Eurorack triggering. Oh, and it’s running at 12V now.  Not sure if I’m going to bother making this, or just move on.

This was a really terrible example of how to design something; I just kept bolting on stuff instead of having a clear plan at the beginning.  That being said, I’m not sure how much differently I would have designed this if I was trying to do the same thing starting from scratch.  I probably would have thought more carefully about certain values, rather than the trial & error experimentation I did.  Whatever, it kept me off the streets and out of trouble.

I did the schematic in Diptrace. The free version is useful enough for small stuff, the next tier up is reasonably priced, and it’s not a subscription like Eagle (f’ing Autodesk). It also works most like a modern piece of software should, in that you can intuit basic operation. I tried KiCad a while back, but it just seemed so willfully obtuse. The one bummer about Diptrace is in order to make it cross platform, they bundle it in Wine. I’m grateful they went through the trouble, but I can’t for the life of me figure out how to print a PDF from it’s print dialog box, so I just did a screen-shot.

Posted in Blinking Lights | Leave a comment

Day 4: variable speed multivibrator

When in doubt, add another transistor. I’ve got it working from ~ 1Hz to 11Hz.. Not too bad, though I’d like even more range on a single control.

Posted in Blinking Lights | Leave a comment

Day 3: variable speed multivibrator

The thought occurred to me late last night that I could replace the resistors that governed the rate of charge for the capacitors with transistors so that I could vary the rate.

Turns out I was right!

One question remains is how to vary the rate over a wider range and use a potentiometer instead? The LDR goes from about 30k all the way up to 1M, which is a pretty wide swing, and isn’t giving me all that much range in rate. You can of course get 1M pots, but they’re not as common, while I’ve got drawers full of 5k – 100k pots. If I can figure that out, maybe I’ll actually build this up proper as a Eurorack module. I’m probably going to have to use math, but not on a Friday night…

Posted in Blinking Lights | Leave a comment

Day 2: More on the Multivibrator

I wanted to look at this circuit in more detail to understand what’s going on.

I’m probing the collector of Q2 on the yellow trace, and the base of Q2 on the green trace.

Note that the time off and time on are different – I changed the value of the resistor on the base of Q1 to 10k, down from 22k. This means one side blinks faster than the other, and it just makes it a bit easier to tell one half from the other when looking at the trace below.

This mostly me just winging it, but:

When the yellow trace is low, Q2 is conducting, placing the cathode of the LED D2 at ground. (sorry, I didn’t label the parts, but you can imagine Q2 & D2 are on the right). When the yellow trace is high, Q2 is cut off, and D2 is off, without a path to ground.
When the green trace is at it’s highest ~.7v above 0, there’s current flowing through the 22k resistor, through the base of Q2, holding it high. But then how does the trace go negative, when we don’t have a negative supply? That’s when C1 is discharging through Q1 when it’s conducting. That negative swing also shuts off Q2, allowing C2 to start charging. C2 charges quicker, and gets higher (hence it looking more like a square wave) because it’s charging though a lower value resistor, and it’s being allowed to charge for longer, because the other side is slower.

I don’t think I understand absolutely everything about this circuit, but I think I’ve mostly explained this correct. I’m sure I could read something that would explain it better, but I wanted to work through this on my own.

Posted in Blinking Lights | Leave a comment

Day 1: The Astable Multivibrator

How do you blink a light with only discrete components? The Astable Multivibrator, which is a type of relaxation oscillator. ‘Astable’, meaning it’s keeps flipping between two states, and never rests in one (we’ll see this later when exploring the venerable 555).

We’ll draw this up in a moment, but first lets pick a flashing rate, and see how close we can get.
And again, I’m exploring and winging it in real-time, so I’m going to be wrong, but: The time constant is simply R*C, which gets us to 63% of the total charge of the capacitor in the RC circuit. Will this circuit flip at that point? I don’t know! But lets use it as a starting point.
Lets try for a period of 1 second. I’m going to guess that we need a pretty large value of C, and I’m going to pick a standard value, say 47uF. So now we have to calculate the R, given T & C:
R = T/C == 1/47e-6 (sorry, that’s horribly formatted scientific notation) = 21,276, or ~22k, which is super convenient, since that’s a standard value as well (huge coincidence, or exactly how the grandfathers of electronics intended?)

Fun fact: The Astable Multvibrator is the only schematic that it’s OK to use diagonal lines for!

When wired up, it has a nice symmetry, which is super important in the field of electronics.

And you’re not gonna believe this, but it worked on the first time. I’m calling that pretty damn close to 1 second period too… so yeah, Day one’s in the bag 🤘.

Video’s on the second pic.

Posted in Blinking Lights | Leave a comment

Day 0: LDR

We’re officially starting the 50 days tomorrow, but I started layout out parts and ended up jumping in.  This is obviously not how you’d make a light blink on it’s own, but I just stated messing around with a few parts that I happened to have in front of me.

The few microamps that flows through the LDR & base circuit allows a few milliamps to flow through the collector circuit.  The downside of this rudimentary approach is that the current through the base never goes all the way to zero, and some newer, more efficient LEDs won’t actually go dark.

Ways we might be able to resolve this – And I’m just riffing

  • Use a FET instead of a transistor.  If we drive the voltage down below the drop of the LED, it will cut off.
  • use a second transistor to amplify the current swing into the base of the first one.

I’m not going to solve this tonight (or possibly ever).  The point of these exercises is just to keep doing something every day for like 30 – 60 minutes.

Posted in Blinking Lights | Leave a comment