In parts 1 and 2, I discussed the important parts of what is going on the PC side with lua. While not 110% detailed I hope it gave you an idea on how the data is processed so the Apple II computer could quickly digest it. Now its time to see what happens at the other end of the serial cable. I am using basic, but its not 100% off the rom Applesoft basic, that would be even slower, so I am using a compiler and a fast graphics driver. Both are from “The Beagle Compiler” which was produced by the ever awesome Beagle Bro’s software company, and though still under copyright, the publishers have given permission for use of their software (within reason I don’t think you will get very far selling it).
Beagle Compiler does not crunch down to machine code like others, so it has a bit of overhead, but I choose it because it has some interesting add-ons like fast hplot (quick drawing), input anything (by default basic will only accept alphanumeric input), and memory drivers for 128K or more machines, all I thought I might need. The final version does not need extra input because all data being sent to the computer is alphanumeric, but I did use fast hplot, which doubles the speed that the computer can draw individual pixels, and one of the memory managers.
On the disk there are 2 COM programs, which are compiled basic scripts, one is STARTUP the other is CLIENT. STARTUP is the first program prodos run when you start a disk and it just does some basic startup tasks.
REM LOAD THE FAST GRAPHICS ROUTINE 11 PRINT CHR$(4)"BLOAD FAST.HPLOT" REM YAP 12 HOME:VTAB 3 13 PRINT " Please type in IN#n (where n = the ssc" 14 PRINT " slot number, then hold control hit A, " 15 PRINT " and type in 7B (600 baud) at the SSC" 16 PRINT " or ? prompt." :PRINT "" 17 PRINT " (you may or may not need to press" 18 PRINT " return depending on model)":PRINT "" 19 PRINT " Then type the following to run ":PRINT "" 20 PRINT " -CLIENT"
As you can see it loads the FAST.HPLOT program, its a binary program so I BLOAD it (binary load), in order to do that we have to PRINT a (ctrl +D) to tell the interpreter that this is a dos command, then the command we want.
Line 12 clears the Apples current text screen and puts the prompt at the top of the screen, VTAB 3 just bumps the cursor down 3 lines.
Then we have some instructions, this could / should be able to be done automatically, and I remember doing it as a kid with my apple IIe, but no matter what I tried on my current //c I could not get the darn serial port set up via script. I figured if I did ever get it to work, it would be so funky that no other Apple’s would automatically set the serial port, so you have to do it manually.
Next, and more importantly is the CLIENT program
REM STARTUP 0-6 REM ENTER HIGH RES PAGE ONE AND TURN OFF THE 4 LINE TEXT DISPLAY REM PAGE 2, NORMALLY FULL SCREEN, IS OCCUPIED AND I DONT FEEL REM LIKE MESSING WITH MOVING STUFF AROUND IN MEMORY 0 HGR:POKE -16302,0 REM LOAD SPLASH SCREEN BINARY INTO HIGH RES PAGE 1 MEMORY 2 PRINT CHR$(4)"BLOAD SPLASH.HGR,A$2000" REM DELAY 4 FOR I = 0 TO 30000 6 NEXT REM MAKE A PALETTE 10-12 10 DIM CL(5): CL(1) = 0:CL(2) = 5 12 CL(3) = 2:CL(4) = 1:CL(5) = 6 REM CLEAR HIGH RES GRAPHICS PAGE 1 100-105 100 HGR:POKE -16302,0:HCOLOR = 7 102 FOR Y = 0 TO 138 STEP 2 104 HPLOT 0,Y TO 140,Y 105 NEXT REM TEMP AND ALERT TEXT GRAPHICS INPUT DECODING 110-125 110 FOR Y = 0 TO 137 112 TB = 140:INPUT TS$ 114 FOR X = 1 TO LEN(TS$) REM CHARACTER --> ASCII VALUE 116 TC$ = MID$(TS$,X,1):TA = ASC(TC$) REM IF NEW CODE BLOCK 118 IF TC$ = "b" THEN TB = TB + 35 REM DRAW PIXEL 120 IF (TA < 65) AND (TA >= 49) THEN HPLOT((TA - 48) + TB), Y 122 IF (TA >= 65) AND (TA <= 90) THEN HPLOT((TA - 55) + TB),Y 124 NEXT X:NEXT Y REM BOTTOM TEXT GRAPHICS INPUT DECODING 130-144 130 FOR Y = 139 TO 191 132 BB = 0:INPUT BS$ 134 FOR X = 1 TO LEN(BS$) REM CHARACTER --> ASCII VALUE 136 BC$ = MID$(BS$,X,1):BA = ASC(BC$) REM IF NEW CODE BLOCK 138 IF BC$ = "b" THEN BB = BB + 35 REM DRAW PIXEL 140 IF (BA < 65) AND (BA >= 49) THEN HPLOT((BA - 48) + BB), Y 142 IF (BA >= 65) AND (BA <= 90) THEN HPLOT((BA - 55) + BB),Y 144 NEXT X:NEXT Y REM RADAR GRAPHICS INPUT DECODING 150-166 150 FOR C = 1 TO 5:HCOLOR = CL(C) 152 FOR Y = 0 TO 138 STEP 2 154 RB = 0:INPUT RS$ 156 FOR X = 1 TO LEN(RS$) REM CHARACTER --> ASCII VALUE 158 RC$ = MID$(RS$,X,1):RA = ASC(RC$) REM IF NEW CODE BLOCK 160 IF RC$ = "b" THEN RB = RB + 35 REM DRAW PIXEL 162 IF (RA < 65) AND (RA >= 49) THEN HPLOT((RA - 48) + RB), Y 164 IF (RA >= 65) AND (RA <= 90) THEN HPLOT((RA - 55) + RB),Y 166 NEXT X:NEXT Y:NEXT C REM WAIT FOR UPDATE LOOP 200 INPUT UD$ 210 IF UD$ = "update" THEN GOTO 100 220 GOTO 200
Which has much more meat to it. Starting at the top I have (HGR:POKE -16302,0). The HGR command clears and sends the apple into High GRapichs mode 1. Mode 1 goes to memory page 1 (there are 2 total for 80 column text or High res graphics) and sets the display to 280×160 with 4 lines of text at the bottom. As already stated I dont want the four lines of text so I POKE location -16302,0 to turn that off.
Maybe someone out there is saying to themselves right now “why didnt he use HGR2?” HGR2 (mode 2) defaults to the second page and is full screen by default, but I didn’t want to use it because there is no dedicated video memory on the Apple II, and something was already using that memory space, so it seemed simpler to just use screen 1 and poke it to be full screen, rather than moving every darn thing around in memory just to free up HGR2.
Next I load the lovely splash screen with Hack A Day’s and Weather Underground’s logos. This image was made in the gimp, converted by an older junkier image converter script I made and dumped into an emulator running at 10X speed. Once the image is drawn on the emulator I BSAVEd it to disk, now in the client script I am just copying that data back into video memory producing the image. There is no time reference for basic so there is just an empty loop to delay the splash screen for a few seconds.
Oddly enough for a machine that has a grand total of 6 unique colors in high resolution graphics, I need to make a palette. The colors on an Apple II are not lined up with the way I want them, and I am not sending it in exact color order either. DIM is dimensioning an array, and the values that follow are the apple color values we want to use and in the order we want them, nice and neat for a loop.
The rest of the script just repeats itself depending on which image is next, first is the tempature and storm advisory graphic(s), its 2 files on the pc side but since they are the same width and going in the same block of the screen I lumped them together as a single image right before it goes to the serial port. Variables are similar to every other Microsoft based 8 bit basic in only the first two characters of a variable is its name, so while you could name everything in nice descriptive words, your going to run into clashes quick.
I loop though each line of the graphic, waiting for input from the serial port each time. each character in the line gets read with the MID function (its like substring) and I also grab each character’s ASCII value using the ASC function. If the character is a “b” then add 35 to the current block counter (TB, BB, or RB for temp, bottom, or radar block).
If the character’s ASCII value is less than 65 but at least 49 then its a number 1-9 so we can just take it at face value, plot the point and move on. If the character’s ASCII value is between 65 and 90 that means its an upper case letter (and here is a chart btw). I take the ascii value and subtract 55 from it, 65 – 55 = 10, A is the 10th character in my graphics key and ASCII value 65 and so on. Now I can plot the point.
Radar is exactly the same thing but its wrapped up in a 5 count loop to change the color after one color of the image has been drawn. Its Y counter also advances 2 steps, since we only have the even lines if I did not “STEP 2” the image would be squashed, now it just has the odd lines replaced with black.
Final thoughts: I had a lot of fun writing kludgey bad code, and it does function though very slowly. I wish I knew more about Apple II programming, but all the years I have spent on the thing, its just now coming up as a hobby. Maybe one day soon Ill be laughing at this while coding furiously in C to make an awesome video game or demo, but its kind of low on my list. The Apple II is one of my favorite little computers and it will continue to remain on my desk for quite a while, if you have the means and like retro computers, the Apple II is plentiful and surprising.
Pitfalls and problems:
It took for-freakin-ever for me to settle on a graphics format, even worse I wrote and tested 5 of them. RLE, binary, high ascii, XPM decoding on the apple and finally base 36.
I probably spent 3 evenings trying to get the stupid serial port working via BASIC script, as you can see that never worked out.
Wasted 2 nights poking all sorts of mad stuff into the Apple trying to kick over its color killer circuit, just to find out it was my tv tuner application not switching from NTSC to RS170 when changing from graphics to text (with the color burst signal enabled during text mode you cant read ANYTHING)
My computer died! Yea at the start I disabled my bench pc cause my wifes machine popped its power supply, well my machine also got a little bit of it cause I was just sitting there writing (probably graphics code) and the computer shuts off. Long story short, at like 11pm on a work night I am switching out a motherboard, and my 2.8ghz dual core can go from room temperature to over 100C in less than 10 seconds!
I think the last big fiasco was for the video, other than the durn cat bumping the camera a couple times, I had spend a couple hours getting everything onto my “craptop” and set up in the living room. After doing some test shots, fiddling with lighting its now like 10PM on a work night and I am ready to go … except I did not have the graphic for the splash screen on the Apple II disk. Lucky for me I could not find my USB drive (both were at work) and that afternoon I had just sold my WIFI card to a co worker as I had an internal one on the way. So yea I burned a 8k file onto a cd rom, hurried to patch the basic script, get it sent over and working correctly, and ended up cleaning the living room at like 2AM.
Oh well it was fun.
Read the rest of this entry »
rofl @t&p
omg. take the hint. no ones interested in this crap.
p.s fix your post, it’s cluttering up the home page
I find it quite interesting
yes. I’m interested in this crap too.
p.s fix your attitude its cluttering up the comments
Nifty. I usually just click Firefox, since a giant radar map of my area is on my iGoogle home page.
@Stevie: Smile and the world smiles with you. Fart and you stand alone. PS: Your breath smells.
Seriously, This is the very essence of why people read this blog. This is a very clever kuldge combining all sorts of odds and ends to make something “modern” using very unlikely forms of scripting and, of all things, Basic.
Granted, there are ways to pull this off a lot more efficiently (and in fact I could since the code of Apple Game Server, previously featured here years ago, is designed for pumping compressed graphic displays over a 115.2 kbaud serial link as well as other things) but I think it’s important to commend Kevin on his work and dedication to show us we can also pull off this stuff if we have as much commitment as he does.
Ok, let me put it another way. Take his post and remove the Apple // and replace it with some other embedded device. Same level of effort, same accomplishment. The Apple // is, for all practical purposes, a very relevant way of experimenting with embedded logic design and code. The fact you have a serial port and some +5 TTL pins that can be toggled on/off with software make it relevant even today, if not more convenient than using, say, a MSP430 launchpad for prototyping logic circuits. It lends itself to hacking because it was designed by a hacker for hackers.
@Kevin: If you’re using the Apple //c, the rom firmware routines (if left active) can actually buffer the serial port for you. This could be useful in achieving a higher baud rate in some cases. But beware though it can also get in the way if you want to use a polling loop in assembler to read the serial port. If you ever feel like borrowing some routines, I’ll happily send ’em your way.
Would it have really been that hard to include links to Parts 1 and 2 somewhere in the post? Not all of us follow this site every day.
A+ article, would read again. :-)
To be honest I’d rather see more of this than anything about Arduino, but that’s just me.
Some Guy:
Part i: http://hackaday.com/2011/04/18/apple-ii-weather-display-part-1/
Part ii: http://hackaday.com/2011/04/19/apple-ii-weather-display-part-2/
Dear Kevin,
You rock.
Sincerely,
wunderground.com
p.s.- Send me an email with your address and we’ll send you some awesome stuff.
I would love to do something like this but sadly I do not have an apple ii. I just love how retro it looks perhaps is there a way to make something similar with slightly newer systems?