Building simh for OpenWRT

I have always had a soft spot for minicomputers... real minicomputers from the early 70's... machines that filled 19" racks with panels full of blinking lights.  

I remember my father having a PDP8 at work before micros slowly took over...

and the Data General Nova I supported in one of my first jobs.... oh the Nova 3...

what I lovely machine.  I wish I had the forthought to save it when it was decommissioned.  

 

But back to now.... from time to time I have played with simh mainly OS8 on the PDP8 but had never really done anything serious.  The lack of blicking lights didn't make it quite the same.  One day I would build a PDP8 simulator to get a better experience but that is a big job and it stayed an idea until I wondered... could I compile simh (at least the simpler machines... definitely not the VAX or PDP11) and run this on a DLink DSL-502T router? (my NZ$1 universal hardware platform at the moment).  If I could then was it possible to add some blinking lights?

 

Part One... Building simh for OpenWRT

This turned out to be surprisingly easy if you have an OpenWRT build environment.  The steps are:

1. Download the simh sources from http://simh.trailing-edge.com/sources/simhv38-1.zip

2. Create a simh subdirectory in the package directory of your OpenWRT build environment.

3. Create a Makefile in the simh directory so the OpenWRT build process will find your new simh package.

4.  Create a src directory in the simh directory.

5.  Unzip the contents of the simh sources zip file into the src directory.  If you check the src directory contents you will find a subdirectory for each emulator and some shared files.

6.  Replace the standard simh Makefile in the src directory with one compatible with the OpenWRT build process.  

The following example builds the PDP8 and Altair simulators and is based on the style of the standard simh makefiles.  You can download it from here.

 

# build selected SIMH modules executable when user executes "make"
 
SIMHFLAGS = -lrt -lm -I .
SIM = scp.c sim_console.c sim_fio.c sim_timer.c sim_sock.c \
sim_tmxr.c sim_ether.c sim_tape.c
 
PDP8D = PDP8
PDP8 = ${PDP8D}/pdp8_cpu.c ${PDP8D}/pdp8_clk.c ${PDP8D}/pdp8_df.c \
${PDP8D}/pdp8_dt.c ${PDP8D}/pdp8_lp.c ${PDP8D}/pdp8_mt.c \
${PDP8D}/pdp8_pt.c ${PDP8D}/pdp8_rf.c ${PDP8D}/pdp8_rk.c \
${PDP8D}/pdp8_rx.c ${PDP8D}/pdp8_sys.c ${PDP8D}/pdp8_tt.c \
${PDP8D}/pdp8_ttx.c ${PDP8D}/pdp8_rl.c ${PDP8D}/pdp8_tsc.c \
${PDP8D}/pdp8_td.c ${PDP8D}/pdp8_ct.c ${PDP8D}/pdp8_fpp.c
PDP8_OPT = -I ${PDP8D}
 
ALTAIRD = ALTAIR
ALTAIR = ${ALTAIRD}/altair_sio.c ${ALTAIRD}/altair_cpu.c ${ALTAIRD}/altair_dsk.c \
${ALTAIRD}/altair_sys.c
ALTAIR_OPT = -I ${ALTAIRD}
 
ALTAIRZ80D = AltairZ80
ALTAIRZ80 = ${ALTAIRZ80D}/altairz80_cpu.c ${ALTAIRZ80D}/altairz80_cpu_nommu.c \
${ALTAIRZ80D}/altairz80_dsk.c ${ALTAIRZ80D}/disasm.c \
${ALTAIRZ80D}/altairz80_sio.c ${ALTAIRZ80D}/altairz80_sys.c \
${ALTAIRZ80D}/altairz80_hdsk.c ${ALTAIRZ80D}/altairz80_net.c \
${ALTAIRZ80D}/flashwriter2.c ${ALTAIRZ80D}/i86_decode.c \
${ALTAIRZ80D}/i86_ops.c ${ALTAIRZ80D}/i86_prim_ops.c \
${ALTAIRZ80D}/i8272.c ${ALTAIRZ80D}/insnsa.c ${ALTAIRZ80D}/insnsd.c \
${ALTAIRZ80D}/mfdc.c ${ALTAIRZ80D}/n8vem.c ${ALTAIRZ80D}/vfdhd.c \
${ALTAIRZ80D}/s100_disk1a.c ${ALTAIRZ80D}/s100_disk2.c ${ALTAIRZ80D}/s100_disk3.c\
${ALTAIRZ80D}/s100_fif.c ${ALTAIRZ80D}/s100_mdriveh.c \
${ALTAIRZ80D}/s100_mdsad.c ${ALTAIRZ80D}/s100_selchan.c \
${ALTAIRZ80D}/s100_ss1.c ${ALTAIRZ80D}/s100_64fdc.c \
${ALTAIRZ80D}/s100_scp300f.c ${ALTAIRZ80D}/sim_imd.c \
${ALTAIRZ80D}/wd179x.c ${ALTAIRZ80D}/s100_hdc1001.c \
${ALTAIRZ80D}/s100_if3.c ${ALTAIRZ80D}/s100_adcs6.c
ALTAIRZ80_OPT = -I ${ALTAIRZ80D}
 
ALL = pdp8 altair altairz80
 
all : ${ALL} 
 
pdp8 : ${PDP8} ${SIM}
$(CC) $(CFLAGS) ${SIMHFLAGS} ${PDP8} ${SIM} ${PDP8_OPT} -o $@ $(LDFLAGS)
 
altair : ${ALTAIR} ${SIM}
${CC} $(CFLAGS) ${SIMHFLAGS} ${ALTAIR} ${SIM} ${ALTAIR_OPT} -o $@ ${LDFLAGS}
 
altairz80 : ${ALTAIRZ80} ${SIM}
${CC} $(CFLAGS) ${SIMHFLAGS} ${ALTAIRZ80} ${SIM} ${ALTAIRZ80_OPT} -o $@ ${LDFLAGS}
 
# remove object files and executable when user executes "make clean"
clean:
rm *.o ${ALL}
 

 

7.  Use Make MenuConfig to select the OpenWRT packages.  The simh package will appear in the Utilities group if you used the Makefile from step 3.  Select to build simh as a Module.

8.  Use Make to rebuild.  All going well this will compile simh with the results in the build_dir/mipsel/SIMH folder in my environment.  Copy the pdp8, altair, altairz80 and any other simulators you have compiled and upload them to your OpenWRT powered router.

It worked well for me.  The DSL-502T is not particularly fast and is a bit limited in available storage but it happily runs OS8 on the PDP8, 4K and 8K Basic and AltDos on the Altair.  I haven't tried CP/M yet and need to free up some space or add some additional flash memory.

In the mean time... on to the blinking lights.  The DSL-502T does not have enough free GPIO pins to provide a display of a 12 or 16 bit address or data bus.  It does support I2C via the GPIO-i2c driver so I have ordered a couple of MCP23016 I2C port extenders to try.  Each chip can drive 16 LED's.... the trick will be to get enough blinking light effect without slowing the simulator.  I am sure the bit bashed I2C bus will be too slow to update with ever address change in the simulator.  Watch this space.

 

Keeping only the last downloaded podcast....

My linux server uses podget to download podcasts. 

The downloaded podcasts are picked up using rsync by my Asus WL-520GU / OpenWRT based car audio player.

The Asus WL-520GU uses an 8GB USB stick for storage so care is needed to ensure that downloaded podcasts are cleaned up.

I went with the approach of keeping only the most recent copy of each subscribed podcast.

While podget has a facility to cleanup old podcasts this is time based and did not always seem to work for my subscriptions.  

Instead to solve the problem I created a shell script which is run on the linux server immediately after the podget process completes.

# Remove playlist files

rm *.m3u

# Remove all but the most recent podcast in each subfolder

for directory in `find . -type d \( ! -iname ".*" \)`; do
    find $directory -maxdepth 1 -type f -printf "%T@\t%p\n" | sort -k1,1n | cut -f2- | sed '$d' | tr '\n' '\0' | xargs -r0 rm -f
done

On the ASUS WL-520GU the rsync process is run with the --delete flag to ensure files that no longer exist on the server are deleted from the ASUS.

 

Who is using the water?... the bore monitor speaks

At the top of the hill on my rural property is a bore that provides stock water for my stock and three neighboring properties.

 

Bore Shed

 

So what does this have to do with thingspeak?

From time to time faults in the various farm system drain water from the header tank faster than the bore pump can pull water out of the ground.... so the pump runs continually.  Expensive on power but also potentially damaging.  Normal use is about 1 hour per day in summer, much less in winter.

 

Pump

 

(Pump)

The problem was how to know if the pump was running excessively without climbing the hill.... and even if I did check it was hard to know if the pump was running because it had just reached to refill point or had been running for three days.

A couple of years back I built a bore monitor that used an IR beam to determine of the bore pump was running and could be queried over the wireless network by a ruby application. 

The IR source and receiver are both powered by PICAXE08M microcontrollers.

 

IR Sender

(IR Beam Sender)

 

 

IR Receiver

 

(IR Beam Receiver)

The PICAXE code for the IR Beam Sender and Receiver are available here.  The Receiver uses a TTL output to indicate the bore running state. 

By querying every 5 minutes and storing the data in a MYSQL database on my server I could graph daily usage over time and see when things had gone awry.

The network connection in the original design was performed using an AVR AT90S8515 and a Packet Wacker ethernet interface.  For 2 years this worked well and then the Packet Wacker died.

Around this time i had been playing with DLink DSL-502T ADSL models and reflashing them with OpenWRT to provide Amateur Radio IGate services.  These worked really well in the APRS application so I wrote a Ruby application that monitors the IR sensor via a GPIO pin on the DSL and provides a browser based summary of the last 30 days activity.

Bore Running Summary

The status pages work well inside my network but I wasn't keen on opening a port on my router so I can check the status while I was at work or on vacation.  Unfortunately problems only happen when you go on vacation.

 

Thingspeak to the rescue....

 

Building a DLink DSL-502T Based IGate - TNC Schematic and Firmware

As mentioned elsewhere the TNC we use in the Igates is based on the ATMega8 based TNC design from Henry Carl Ott (N2RVQ).

For those interested in constructing their own here is the schematic

Mega8TNC Schematic

and version 1.9 AVR TNC firmware.

The firmware is a slightly modified version of N2RVQ's version 1.8 firmware which we call version 1.9.  

The difference is a startup delay to prevent the TNC transmitting via the serial port and preventing the DSL-502T from booting.

When programming an ATMega8 with the firmware ensure you set the fuses to 0xDA (High) and 0xBF (Low).   Incorrect fuse settings will prevent the chip from starting correctly.

 


Page 16 of 25

Powered by Easytagcloud v2.1

Contact Andrew Quinn

jaquinn@ihug.co.nz http://twitter.com/jaquinn