I've been in the process of upgrading my backup/home media server for a few weeks now. I managed to get hold of an old case from a skip outside a closing down fax/photocopier company. It's a fairly decent case, although it was somewhat 5.25" centric in design. Amongst other things I did to modify this case, I replaced the old drive door with a new completely transparent one with some USB ports and an additional fan for cooling the new compliment of many hard disks. The server is going to be running in a cupboard without a monitor most of the time and I wanted to be able to see at a glance what the system was doing. Inspired by the computer-graphic imaginary servers that are featured in web hosting ads that have a screen on the front, I set about adding a little monochrome LCD.
I used a module I'd got off eBay several years ago, it's based around the very common KS0108/0107 driver chips so pin-compatible alternatives are still around now. I drove this with a PIC18F4520 which is overkill for this project really as all it has to do is copy text from a serial port to the display, and the display has its own internal static memory, however I made a bulk purchase of this chip a couple of years ago so it's the cheapest option for me. The PIC is connected to a MAX202 RS232 level-converter and is then plugged into the motherboard of the server which has an RS232 port on a 10 pin header.
The PIC has a 32.768kHz watch crystal attached to the timer 1 external oscillator pins, allowing it to internally generate a 1 Hz interrupt for an (approximately) real time clock. In fact the crystal runs a bit fast, I've not been able to narrow down the exact cause for this, the datasheet for the PIC describes some fairly particular ground plane requirements though as this crystal is right next to the main crystal, and I've built my project on a bit of strip-board.
The PIC receives commands from the PC in 24 byte packets, these consist of a special start byte, a row number, 21 ASCII codes and a checksum (simple bitwise XOR of all bytes in the packet except start byte). The start byte is 0xAA which is an illegal character in ASCII (as it is more than 128), whenever this is received any partially received packet is discarded. This ensures that the PC can communicate even if the PIC misses receiving one byte of a packet protecting the link from getting out of sync. The row number is 0-7 for the physical rows on screen or 8-15 for various "special" messages. The 21 bytes of data corresponds to the line length on the screen as it is a 128x64 pixel display and my character set is 8x6 pixels there are 21 columns and 8 rows. The final byte just acts as a bit of protection to stop a bit error issuing a firmware update command etc. by accident.
A character table to convert ASCII codes into 8x6 pixel bitmap font is stored in the flash memory of the PIC. The only thing the PIC can update on the display without receiving from the host PC is the time, which it updates from the internal RTC registers once a second. A simple BCD to ASCII converter displays the time on the bottom row, all the other rows are controlled entirely from the PC, this simplified formatting and handling of numerical data types.
The host code is written in python using the daemon class from this site [27-Apr-2014: the site seems to have gone away, I've hosted the python file with the daemon class as an attachment to this post]. It uses pyserial for the interface to the serial port and calls various system diagnostic tools (df, sensors) and reads some /proc files to get the data needed for the display. This is then formatted into 21 character strings (quite a challenge actually!) and then sent down the wire to the PIC along with periodic updates of the time (partly due to the frequency problem but also because the PIC has not battery backup for its RTC so needs to be updated at boot anyway). I added a fourth option to the controlling client of the daemon, "test", this invokes the main run() method without daemonizing the process so any error output is dumped to the terminal and can be read, this was handy when debugging the info gathering routines.
The schematic as a PDF is attached and in the image gallery, there's a picture of it working in there too. The python code for my part is attached, I'd advise removing the .txt and making it executable. You'll need the daemon.py file from the referenced site as well. Please note that the information gathering functions are not very robust, they have been designed to work on the specific system I'm building and nothing else.
The source code for the PIC is in a tar attached to the article, the source is all GPL so use as you like. There is a bootloader that allows the firmware in the PIC to be updated via the serial link by sending a specially crafted message packet and then sending a slightly modified intel hex format down the serial link. This is not particularly robust and has had very little testing so I'd advise against relying on this. It saved me some time messing around with PIC programmers inside the PC though. The firmware updater python script is attached as well and should accept output from any PIC assembler (I used gputils).
Update 27 Feb 2011
I just started running a local Minecraft server on this machine and was somewhat surprised to see that the RAM usage was still sitting at a few hundred MB. After much head scratching I realised that the find("MemFree") statement in the mem_info() function in the daemon was not working the way I expected. Of course it returns the location of the string "MemFree" in the line of text which is column zero so evaluates false only on the line I was looking for it to evaluate true. I've added an if greater than -1 statement to the two find() calls which sorts it all out. monitor_daemon.txt has been updated to the latest version.
|assembly.tgz||April 23, 2014, 9:06 p.m.||8.7 KB|
|mon_flash.txt||April 23, 2014, 9:06 p.m.||5.1 KB|
|schematic.pdf||April 23, 2014, 9:06 p.m.||56.0 KB|
|monitor_daemon.txt||April 23, 2014, 9:06 p.m.||3.3 KB|
|Deamon class||April 27, 2014, 10:15 p.m.||2.8 KB|