Graphical touchscreen terminal

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.

Idea

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.

Software

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).

Bitmap Transmission

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.

First application. Weather is taken from openweathermap.org

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).

Transmission of updated regions

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).

That short line on the bottom of display is a bug - the screen was not updated properely.

Server side software

Now, server is running mentioned PHP script that handles two "screens". One displays current time, date, weather and upcoming appointments. The other is activated by clicking on current weather panel and shows forecast for today and tomorrow.

Appointments are stored in MySQL database and managed using web interface.

Hardware

Power supply

PocketViewer is originally powered by two AAA-size batteries. I wanted it to be running nonstop, so it needs to be powered otherwise. I tried to use small 3V stabiliser (LP2950 CZ3.0), but the device refused to power up. Sometimes it powered up, entering setup (screen calibration, ...), then it powered down. Adding small capacitor didn't help - the device was generating current spikes that made voltage fall too much, so device kept resetting. Later I've found that 100uF capacitor was enough. I made a free form circuit small enough to fit in original battery compartment. Cutting small hole to pass the wires through was needed.
Detail of 3V stabiliser in battery compartment.

Wiring

Device is connected by ethernet cables in our house. I made two DB-9 to RJ45 cables, pin 1(RJ45) is used for power supply, pins 1 and 9 on DB-9 side are not connected. Other pins are connected 2 to 2, 3 to 3, etc.

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)

  • PV rotated to landscape and mounted on nokia phone holder.
  • Weather forecast screen.

Source code

Warning! It was done very quickly and code is poor :(
You can view souce code on your own risk here.