Long time ago, I have got an Casio PocketViewer personal organiser. It is an device with 160x160 px monochrome touchscreen. It was laying in my drawer for a long time. Now I took it out to make something useful with it.
The idea was to make Casio PV show some useful information, possibly updated from the internet. As the device has only serial interface available, simplest way to do it was to prepare the information to display on a server and push it to the PV through serial port.
First, I downloaded Casio SDK and made simple application to receive an bitmap image from serial interface and display it on screen. Development for CasioPV is not wery user(programmer)-friendly. Coding is done in C, but C99 is not supported. Simulator/debugger is hard to use (i.e. you must go through first-boot setup - screen calibration, clock setup - on every simulator restart).
First approach was to listen for incoming bytes, do bitwise operations and put the image on screen
dot-by-dot. It worked, but was (as expected) veeery slow. Next, the application was rewritten to
buffer received data and use LibPutGraph()
to replace the screen all at once.
Bitmap is represented by two words ( = 2x2 bytes) representing the size (width and height) of
bitmap and followed by (WIDTH*HEIGHT/8) bytes, where each bit represents one pixel (1 = black, 0 =white).
It is transmitted to the device by sending D
(as Display) followed by the bitmap.
There were some problems with lost bytes (serial interface buffer overflow), but it was solved by enabling HW flow control. (Using SW flow control was a bad idea - bitmap inevitably contained XON and XOFF characters, messing up all the things).
Then I made an PHP script to render simple screen with current weather - temperature, clouds icon,
description of weather, wind speed and cloud coverage.
Next step was to enable user interaction. PV application was modified to send back coordinates
of user touch. This was not so easy. PV standard library has only LibTchWait()
function,
that (as you might guess by "wait") is blocking. Fortunately, i've found nice website
explaining event polling on Casio PV.
It is done by some obscure, undocumented system interrupt, but it works great.
On each touch, the device sends T
(as Tocuch) character, followed by coordinates (two bytes).
After debugging touch interaction, i've made little PHP "framework" that handles touch events from terminal and sends back screen bitmap to display. I've discovered, that sending whole screen is too slow to give resonable user experience. I've edited the code to send only parts of screen that were updated. This is done by simple algorithm: original and new bitmaps are traversed to find changed regions, if regions are close enough, their are merged together, to compensate for overhead (for every region update, update command, starting offset and region size must be transmitted). Maximum chunk size was limited to 1000 bytes, so even if whole screen is changed (i.e. inverted), it is updated by parts, so user can see that something is actually happening. If all screen was updated at once, there would be 1-2 second delay.
Partial updates are transmitted by command C
(as Change), followed by offset (2 bytes) and
lengh (2 bytes).
Appointments are stored in MySQL database and managed using web interface.
The device is connected by original sync cable to this DB-9=>RJ45 cable, that runs to the wall socket, from there cable runs to the basement where small rack is situaded. There RJ45=>DB-9 cable is connected to RS232/USB adpter and connected to MikroTik router. The router is connected by VPN to my server, where PHP script generates screen bitmaps and sends them by TCP to MikroTik, that outputs them to the serial port. Power is taken from the RS232/USB adapter (5V from USB)