Charge Master 2016 Serial Protocol

Charge Master 2016 Serial Protocol

The Voltcraft (Conrad) Charge Master 2016 has a completely different protocol from the CM2010 and other devices.

The USB port is still a serial port which is /dev/cu.SLAB_USBtoUART on my Mac. Every second the device sends a package with 19200 baud 8N1. I’ve written a simple python script to demonstrate reading and interpreting the data. For actual use you should add some error handling.

Only one byte in the slot header is unknown (it seems the Windows software is also not using it) and the device header has a few semi-unknown ones (the version, the temperature, etc) – only the chemical setting is actually used by the Window software.

The full source code can be found on GitHub

ELV Mobile Alerts

Mobile Alerts

This document tries to describe every detail of the Mobile Alerts sensors, which are sold by ELV in Germany, but are also available at the common suspects (Amazon, etc). Be careful buying at Amazon: certain sensors mention Mobile Alerts, but seem to be designed for the US. They are not compatible with the ELV Mobile Alerts ones!

Mobile Alerts is covering mostly climate sensors, but also contains moisture and door/window sensors plus a sound detector, which acts as a gateway for smoke sensors.

The Mobile Alerts are a version of the LaCrosse Alerts Mobile system made for the European market.

Detailed Infomation

Unit Calculator in Objective C

An piece of code I wrote in 2006, which allows you to do mathematical calculations with units from Objective-C. I’ve updated the code to Objective-C with properties and generics. It is not depended on macOS and should work fine on iOS as well.

By default the result will be in SI compatible units, but all units and prefixes (like kg or ms) can be freely defined in a configuration file units.dat. You can also force a specific unit and add variables to the term. It is also trivial to add new functions, even functions which accept a list of values.

A few examples:

((123.45e-1 + sqrt(+4) -4-.69/2)*2^1/5)^2 => 16
 avg(1,2,3,4) => 2.5
 (9*m^2)^0.5 => 3 m
 60 m + 2 mm => 60.002 m
 sqrt(9 m^2) => 3 m
 20 lb requestedUnit: kg => 9.07185 kg
 60 km/h + 12 m/s requestedUnit: km/h => 103.2 km/h
 1 Torr*760 requestedUnit: atm => 1 atm
 68 F requestedUnit: C => 20 C
 0 C + 0 C requestedUnit: C => 273.15 C --- internally temperatures are converted to Kelvin

The project is an Xcode project with a simple NSLog in the app delegate for testing. It also has a bunch of unit tests to make sure the math works out in all cases.

The code can be found on GitHub.

Label Placement

Implementation of a little algorithm to draw labels/rectangles on a background while trying to avoid overlapping. This is useful for maps, drawing labels on graphs, etc. The sources are – as always – available on GitHub.

In the screenshots you can see the planned area in light grey, while the repositioned ones are in black. The size of the rectangles is arbitrary.

The implementation is specifically simple and not optimized for performance at all. The goal is to be able to understand it.

Raspbian Jessie with a Pi-Raq LCD

The Pi-Raq came with an old version of Raspbian. An upgrade to e.g. Jessie will render the display non-functioning. The manufacturer sadly never got back to me, so I fixed it myself.

Download the archive with all needed files from GitHub.

There are two main things to do:

  1. Provide a custom dt-blob.bin for the pin configuration. This has changed with later version of Raspbian and is the reason why the old file no longer works.
  2. Update a stock config.txt to switch to the LCD.

How to modify the dt-blob.dts

There is very few documenation for this, which is expected, considering that hooking up a custom LCD to a Raspberry is not a very common thing to do.

I used the stock dt-blob.dts as a new base. First I stripped it down, because the Pi-Raq ships with a “Pi 2 Model B rev 1.1” only, which means all other pin configurations are not used anyway and I can’t test it. If you try to use it with a different Raspberry Pi (which seems possible), you have to change the pins_2b2 to match your Raspberry Pi. Use the stock version as an example and transfer the changes over.

By looking at the “Pi-RAQ Hardware Schematic.pdf” you can find out all custom pin mappings:

  • Pin 0 => PCLK-Out (pixel clock)
  • Pin 1 => DE-Out (display enable)
  • Pin 4–8 => B3-B7-Out (5 bits for blue)
  • Pin 9–14 => G2-G7-Out (6 bits for blue, our eyes are more sensitive to green)
  • Pin 15–19 => R3-R7-Out (5 bits for blue)
  • Pin 20–26 are for the jog shuttle controls. They don’t need a custom config, because they are already covered by the pin@default case.
    • Pin 20 = Right button
    • Pin 21 = Left button
    • Pin 22 = Rot1
    • Pin 23 = Center button
    • Pin 24 = Rot2
    • Pin 25 = Down button
    • Pin 26 = Left button
  • Pin 27 is the output for the backlight of the LCD. It has to be an output and should have a startup_state of “active”, otherwise the display stays off after boot. It can still be turned off at any time via a script.

Normal buttons are detected on a falling edge with 100ms debounce. Rotation is doing an edge-detection (both, 10ms debounce). If Rot1 changes and the Rot1 and Rot2 bits are the same, the wheel was rotated left. If both bits have a different value, it was rotated right.

Everything beyond pin 28 is not modified.

How to modify the config.txt

The config.txt has to be modified to switch from HDMI to the LCD. Besides basic changes, like turning overscan off (the LCD doesn’t have a overscan area) and set the framebuffer size to 1024×100 pixel, it is also necessary to enable dpi support (via enable_dpi_lcd), switch the default over and reconfigure the timing and output format for the dpi. Check the comments for a bit more details. The timings and the output format are specific to the LCD panel, which is connected.

Installation Step-by-Step

  1. Install Raspbian on an SD Card
  2. Use ApplePi-Baker to install Raspbian Jessie Lite (the normal version is not needed for this tiny display)
  3. Boot Raspberry with this card. You need to have a HDMI display connected and a USB keyboard
  4. sudo raspi-config => fix the keyboard layout, set a password, changed the hostname, reboot
  5. Remove the card and copy the content of this folder into /home/pi
  6. Put the card back into the Raspberry and boot the Pi-Raq again.
  7. It is typically faster to SSH into the Pi-Raq to configure it, but not necessary.
  8. Now finish the installation:

sudo nano /boot/config.txt

Uncomment/Modify the following lines, which should already be in the config.txt



and add this to the bottom of the file:

#Generated on Thu Feb 19 13:20:39 2015 by Segler-HP
#config file for None
#Output Format -> DPI_OUTPUT_FORMAT_16BIT_565_CFG1
#Invert Pixel Clock ->RGB Data changes on falling edge and is stable at rising edge
#Hsync Disable ->False
#Vsync Disable ->False
#Output Enable ->False
#Hsync Polarity ->Inverted
#Vsync Polarity ->Inverted
#Output Enable Polarity ->default for HDMI mode
#Output Enable Phase ->DPI_PHASE_NEGEDGE
hdmi_timings=1024 0 50 100 50  100 0 2 10 2 0 0 0  60 0 25000000 7
dpi_output_format=4194306 #6488594

The pin configuration of the device tree can be compiled from source:

sudo dtc -I dts -O dtb -o /boot/dt-blob.bin dt-blob.dts

As an alternative to you copy the dt-blob.bin

sudo cp dt-blob.bin /boot/dt-blob.bin

The Raspberry icons occupy a large amount of the vertical space during boot. They can be disabled by adding an option to the cmdline.txt:

sudo nano /boot/cmdline.txt

Add logo.nologo to the parameters. It should look like this after it:

dwc_otg.lpm_enable=0 logo.nologo console=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait

We should also upgrade and update our installation:

sudo apt-get upgrade && sudo apt-get update

Now we can reboot:

sudo reboot

The HDMI should now be off (and can it be disconnected) and the LCD is used

Launching the demos

To get the demos to work, we need to install a few more python specific pieces:

For AlarmTest we need pygame:

sudo apt-get install python-pygame

This demo can be launched by cd AlarmTest and then python

We need pip to install more Python packages

sudo apt-get install build-essential python-dev python-pip

This is only used for rotTest:

sudo pip install psutil

This demo can be launched by cd rotTest and then python The demo can be quit via Control-C, but the display stays blank. I haven’t fixed this. sudo reboot solves it…

The full dt-blob.dts for EarthLCD Pi-Raq


/ {
   videocore {
      clock_routing {
        vco@PLLD { freq = <2000000000>; };
        chan@DPER { div = <8>; }; // APER will be 500MHz
      }; // clock routing

      pins_2b2 { // Pi 2 Model B rev 1.1
         pin_config {
            pin@default {
               polarity = "active_high";
               termination = "pull_down";
               startup_state = "inactive";
               function = "input";
            }; // pin

            pin@p0  { function = "dpi";    termination = "no_pulling"; drive_strength_mA = < 8 >; };    // PCLK-OUT
            pin@p1  { function = "dpi";    termination = "no_pulling"; drive_strength_mA = < 8 >; };    // DE-OUT

            pin@p2  { function = "i2c1";   termination = "pull_up";    }; // I2C 1 SDA
            pin@p3  { function = "i2c1";   termination = "pull_up";    }; // I2C 1 SCL

            pin@p4  { function = "dpi";    termination = "no_pulling"; };   // B3-Out
            pin@p5  { function = "dpi";    termination = "no_pulling"; };   // B4-Out
            pin@p6  { function = "dpi";    termination = "no_pulling"; };   // B5-Out
            pin@p7  { function = "dpi";    termination = "no_pulling"; };   // B6-Out
            pin@p8  { function = "dpi";    termination = "no_pulling"; };   // B7-Out

            pin@p9  { function = "dpi";    termination = "no_pulling"; };   // G2-Out
            pin@p10 { function = "dpi";    termination = "no_pulling"; };   // G3-Out
            pin@p11 { function = "dpi";    termination = "no_pulling"; };   // G4-Out
            pin@p12 { function = "dpi";    termination = "no_pulling"; };   // G5-Out
            pin@p13 { function = "dpi";    termination = "no_pulling"; };   // G6-Out
            pin@p14 { function = "dpi";    termination = "no_pulling"; };   // G7-Out

            pin@p15 { function = "dpi";    termination = "no_pulling"; };   // R3-Out
            pin@p16 { function = "dpi";    termination = "no_pulling"; };   // R4-Out
            pin@p17 { function = "dpi";    termination = "no_pulling"; };   // R5-Out
            pin@p18 { function = "dpi";    termination = "no_pulling"; };   // R6-Out
            pin@p19 { function = "dpi";    termination = "no_pulling"; };   // R7-Out

            // Pin 20..26 are the Jog Shuttle controls, they are all inputs, which is covered by the pin@default case
            // p20 = Right button
            // p21 = Left button
            // p22 = Rot1           (Rot1 ^ Rot2) != 0 => Right, (Rot1 ^ Rot2) == 0 => Left if an edge was detected
            // p23 = Center button
            // p24 = Rot2
            // p25 = Down button
            // p26 = Left button

            pin@p27 { function = "output"; termination = "pull_up"; startup_state = "active"; };    // LCD Backlight enable, active at boot

            // From here on it is identical to Jessie's defaults:

            // The firmware changes I2C pin functions on the fly, returning them to inputs when done. But pins 28&29 are
            // not used on a 1.1 Pi2, so the I2C0 function ends up multiply mapped (bad). therefore don't statically map.
            // pin@p28 { function = "i2c0";   termination = "pull_up";    }; // I2C 0 SDA
            // pin@p29 { function = "i2c0";   termination = "pull_up";    }; // I2C 0 SCL
            pin@p31 { function = "output"; termination = "pull_down"; }; // LAN_RUN
            pin@p32 { function = "output"; termination = "pull_down"; }; // Camera LED
            pin@p35 { function = "input";  termination = "no_pulling"; polarity = "active_low"; }; // Power low
            pin@p38 { function = "output"; termination = "no_pulling";    }; // USB current limit (0=600mA, 1=1200mA)
            pin@p40 { function = "pwm";    termination = "no_pulling"; drive_strength_mA = < 16 >; }; // Right audio
            pin@p41 { function = "output"; termination = "no_pulling";    }; // Camera shutdown
            // Communicate with the SMPS by "bit-bashing" the I2C protocol on GPIOs 42 and 43
            pin@p42 { function = "output"; termination = "pull_up";    }; // SMPS_SCL
            pin@p43 { function = "input";  termination = "no_pulling";    }; // SMPS_SDA
            pin@p44 { function = "gp_clk"; termination = "pull_down"; }; // ETH_CLK - Ethernet 25MHz output
            pin@p45 { function = "pwm";    termination = "no_pulling"; drive_strength_mA = < 16 >; }; // Left audio

            pin@p46 { function = "input";  termination = "no_pulling"; polarity = "active_low"; }; // HDMI hotplug detect (goes to pin 6 of IC1)
            pin@p47 { function = "output"; termination = "pull_down"; }; // activity LED
            pin@p48 { function = "sdcard"; termination = "pull_up";    drive_strength_mA = < 8 >; }; // SD CLK
            pin@p49 { function = "sdcard"; termination = "pull_up";    drive_strength_mA = < 8 >; }; // SD CMD
            pin@p50 { function = "sdcard"; termination = "pull_up";    drive_strength_mA = < 8 >; }; // SD D0
            pin@p51 { function = "sdcard"; termination = "pull_up";    drive_strength_mA = < 8 >; }; // SD D1
            pin@p52 { function = "sdcard"; termination = "pull_up";    drive_strength_mA = < 8 >; }; // SD D2
            pin@p53 { function = "sdcard"; termination = "pull_up";    drive_strength_mA = < 8 >; }; // SD D3
         }; // pin_config

         pin_defines {
            pin_define@HDMI_CONTROL_ATTACHED { type = "internal"; number = <46>; };

            pin_define@NUM_CAMERAS { type = "internal"; number = <1>; };
            pin_define@CAMERA_0_I2C_PORT { type = "internal"; number = <0>; };
            pin_define@CAMERA_0_SDA_PIN { type = "internal"; number = <28>; };
            pin_define@CAMERA_0_SCL_PIN { type = "internal"; number = <29>; };
            pin_define@CAMERA_0_SHUTDOWN { type = "internal"; number = <41>; };
            pin_define@CAMERA_0_UNICAM_PORT { type = "internal"; number = <1>; };
            pin_define@CAMERA_0_LED { type = "internal"; number = <32>; };

            pin_define@FLASH_0_ENABLE { type = "absent"; };
            pin_define@FLASH_0_INDICATOR { type = "absent"; };
            pin_define@FLASH_1_ENABLE { type = "absent"; };
            pin_define@FLASH_1_INDICATOR { type = "absent"; };

            pin_define@POWER_LOW { type = "internal"; number = <35>; };
            pin_define@LEDS_DISK_ACTIVITY { type = "internal"; number = <47>; };
            pin_define@LAN_RUN { type = "internal"; number = <31>; };
            pin_define@SMPS_SDA { type = "internal"; number = <43>; };
            pin_define@SMPS_SCL { type = "internal"; number = <42>; };
            pin_define@ETH_CLK { type = "internal"; number = <44>; };
            pin_define@USB_LIMIT_1A2 { type = "internal"; number = <38>; };
            pin_define@SIO_1V8_SEL { type = "absent"; };
            pin_define@PWML { type = "internal"; number = <45>; };
            pin_define@PWMR { type = "internal"; number = <40>; };
            pin_define@SAFE_MODE { type = "internal"; number = <3>; };
            pin_define@SD_CARD_DETECT { type = "absent"; };
            pin_define@ID_SDA { type = "internal"; number = <0>; };
            pin_define@ID_SCL { type = "internal"; number = <1>; };
            pin_define@DISPLAY_I2C_PORT { type = "internal"; number = <0>; };
            pin_define@DISPLAY_SDA { type = "internal"; number = <28>; };
            pin_define@DISPLAY_SCL { type = "internal"; number = <29>; };
         }; // pin_defines
      }; // pins


The full config.txt

# For more options and information see
# Some settings may impact device functionality. See link above for details

# uncomment if you get no picture on HDMI for a default "safe" mode

# uncomment this if your display has a black border of unused pixels visible
# and your display can output without overscan

# uncomment the following to adjust overscan. Use positive numbers if console
# goes off screen, and negative if there is too much border

# uncomment to force a console size. By default it will be display's size minus
# overscan.

# uncomment if hdmi display is not detected and composite is being output

# uncomment to force a specific HDMI mode (this will force VGA)

# uncomment to force a HDMI mode rather than DVI. This can make audio work in
# DMT (computer monitor) modes

# uncomment to increase signal to HDMI, if you have interference, blanking, or
# no display

# uncomment for composite PAL

#uncomment to overclock the arm. 700 MHz is the default.

# Uncomment some or all of these to enable the optional hardware interfaces

# Uncomment this to enable the lirc-rpi module

# Additional overlays and parameters are documented /boot/overlays/README

#Generated on Thu Feb 19 13:20:39 2015 by Segler-HP
#config file for None
#Output Format -> DPI_OUTPUT_FORMAT_16BIT_565_CFG1
#Invert Pixel Clock ->RGB Data changes on falling edge and is stable at rising edge
#Hsync Disable ->False
#Vsync Disable ->False
#Output Enable ->False
#Hsync Polarity ->Inverted
#Vsync Polarity ->Inverted
#Output Enable Polarity ->default for HDMI mode
#Output Enable Phase ->DPI_PHASE_NEGEDGE
hdmi_timings=1024 0 50 100 50  100 0 2 10 2 0 0 0  60 0 25000000 7
dpi_output_format=4194306 #6488594

Mobile Alerts Sensors

ELV is selling affordable weather sensors, which can be monitored via an iOS application. To allow that all data is transmitted via a gateway to a server, which the application can access. Sadly the protocol is not documented. I don’t think anybody has documented the way the URL has been constructed, especially the MD5 hash over the first part of it.

This sample code integrates sensors into fhem and I wrote it for Mac OS X, but it should work on Linux, too.

All information (and more) is available on GitHub as well.

To integrate the sensors into fhem, add the sensors to the iOS application and check if they show up. You need to note all sensor IDs. The ID is 6 bytes long and represented as a hexadecimal number. This same code supports sensors of type 2 (temperature only) and type 3 (temperature and humidity), which can be recognized via the first two characters of the ID.

You have to adjust the following things in the code:

  • sensors = … Here you have to add all sensors IDs as strings
  • downloadPath This needs to be adjusted to point to the log folder of fhem.
  • vendorid You might want to change the UUID to a new one (just run uuidgen from the terminal)

Python Code

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import os
import json
import pprint
import datetime
import hashlib
import time

downloadPath = os.path.expanduser('~/fhem-5.7/log')
pp = pprint.PrettyPrinter()

sensors =  set(['021122334455',...,'031122334455'])

def parseJSON(jj):
    if not jj['success']:
        print '#%d %s' % (jj['errorcode'],jj['errormessage'])
    for device in jj['result']['devices']:
        deviceTypeId = device['devicetypeid']
        deviceName = device['name']
        print '%s %s [%d] #%d %s' % (device['deviceid'], deviceName, device['lowbattery'],len(device['measurements']),datetime.datetime.fromtimestamp(device['lastseen']).strftime('%Y-%m-%d %H:%M:%S'))
        year = -1
        month = -1
        logPath = ''
        for measurement in device['measurements']:
            idx = measurement['idx']
            transmitTime = datetime.datetime.fromtimestamp(measurement['c'])
            measurementTime = datetime.datetime.fromtimestamp(measurement['ts'])
            tx = measurement['tx']
            mm = measurement
            del mm['idx']
            del mm['c']
            del mm['ts']
            del mm['tx']

            if year != measurementTime.year or month != measurementTime.month:
                if len(logPath):
                    f = open(logPath, "w")
                    for d in sorted(data):
                        f.write('%s %s\n' % (d,data[d]))
                year = measurementTime.year
                month = measurementTime.month
                logPath = downloadPath + '/S_SENSOR_%s-%d-%02d.log' % (deviceName.upper().replace(' ','_'),year,month)
                data = {}
                    for line in open(logPath).readlines():
                        vals = line[:-1].split(' ')
                        data[' '.join(vals[:-1])] = vals[-1]
            dataKey = measurementTime.strftime('%Y-%m-%d_%H:%M:%S') + ' SENSOR_' + deviceName.upper().replace(' ','_') + ' '
            if deviceTypeId == 2:
                data[dataKey + 'TEMP:'] = '%.1f' % (measurement['t1'])
            elif deviceTypeId == 3:
                data[dataKey + 'TEMP:'] = '%.1f' % (measurement['t1'])
                data[dataKey + 'FEUCHTIGKEIT:'] = '%.1f' % (measurement['h'])
        if len(logPath):
            f = open(logPath, "w")
            for d in sorted(data):
                f.write('%s %s\n' % (d,data[d]))

import urllib
import urllib2

devicetoken = 'empty'               # defaults to "empty"
vendorid = '1FB220C4-CC15-4195-97CF-8BE4FD3DAE72'   # iOS vendor UUID (returned by iOS, any UUID will do). Launch uuidgen from the terminal to generate a fresh one.
phoneid = 'Unknown'                 # Phone ID - probably generated by the server based on the vendorid (this string can be "Unknown" and it still works)
version = '1.21'                    # Info.plist CFBundleShortVersionString
build = '248'                       # Info.plist CFBundleVersion
executable = 'Mobile Alerts'        # Info.plist CFBundleExecutable
bundle = 'de.synertronixx.remotemonitor'    # [[NSBundle mainBundle] bundleIdentifier]
lang = 'en'                         # preferred language

request = "devicetoken=%s&vendorid=%s&phoneid=%s&version=%s&build=%s&executable=%s&bundle=%s&lang=%s" % (devicetoken,vendorid,phoneid,version,build,executable,bundle,lang)
request += '&timezoneoffset=%d' % 60        # local offset to UTC time
request += '&timeampm=%s' % ('true')        # 12h vs 24h clock
request += '&usecelsius=%s' % ('true')      # Celcius vs Fahrenheit
request += '&usemm=%s' % ('true')           # mm va in
request += '&speedunit=%d' % 0              # wind speed (0: m/s, 1: km/h, 2: mph, 3: kn)
request += '&timestamp=%s' % datetime.datetime.utcnow().strftime("%s")  # current UTC timestamp

requestMD5 = request + 'asdfaldfjadflxgeteeiorut0ß8vfdft34503580'  # SALT for the MD5
requestMD5 = requestMD5.replace('-','')
requestMD5 = requestMD5.replace(',','')
requestMD5 = requestMD5.replace('.','')
requestMD5 = requestMD5.lower()

m = hashlib.md5()
hexdig = m.hexdigest()

request += '&requesttoken=%s' % hexdig

request += '&deviceids=%s' % ','.join(sensors)
#request += '&measurementfroms=%s' % ('0,' * len(sensors))
#request += '&measurementcounts=%s' % ('50,' * len(sensors))

http_header = {
                "User-Agent" : "remotemonitor/248 CFNetwork/758.2.8 Darwin/15.0.0",
                "Accept-Language" : "en-us",
                "Content-Type": "application/x-www-form-urlencoded; charset=utf-8",
                "Host" : "",

# create an urllib2 opener()
opener = urllib2.build_opener()

# create your HTTP request
req = urllib2.Request('', request, http_header)

# submit your request
while True:
    res =
    print '-' * 40
    time.sleep(10*60)   # wait for 10 minutes

Atari ST Book: Internal Registers

By looking at the ROM code, available software and the hardware layout I can now document most specialty registers in the ST Book from Atari. I hope it is useful to you. Also available at GitHub.

The main ROM for the ST Book starts at $e0000 and ends at $e3ffff (256kb large). At $e40000 starts the ROM-Disk (also 256kb large), which is automatically activated as drive P.

YM Port A

Bit Description
0 Side Select (S0SEL)
1 Disk 0 Select (D0SEL)
2 Disk 1 Select (D1SEL)
3 MAX241 Pin 20 (TI3) – RS232 RTS (/MFPRTS)
4 MAX241 Pin 6 (TI2) – RS232 DTR (/MFPDTR)
5 Centronics Strobe (STROBE)
7 FDD Dense Selection (FDD_DENSE_SEL)

Autovector Interrupt Level 7 /POWER FAIL (NMI)

MFP Input Pins

Bit Description
7 Power Alarms (Power Alarms) (POWER_ALARMS-) = (/SRCLOW /RTC_ALARM /POWERON)
6 MAX241 Pin 22 (RD4) – RS232 CD (/MFPRI)
2 MAX241 Pin 26 (RD3) – RS232 CTS (/MFPCTS)
1 MAX241 Pin 5 (RD2) – RS232 DCD (/MFPCD)
0 Centronics Busy (BUSY)

$D0000 – Unknown $D0004 – Unknown


Bit Description
0 0: enable combo -> shadow controller video transfer, 1: disable combo -> shadow controller video transfer


Bit Description
0 0: Shadow Chip OFF
1 0: /SHIFTER_OFF output (Unused in STBook)
2 0: POWER_OFF (Turns off main VCC when high)
3 0: /22ON output (turns off LCD Bias when HIGH)
4 0: REFRESH_MACHINE output (turns on refresh controller)
5 0: RS–232_OFF output (turns off +/- 10 generator)
6 0: (Unused in STBook)
7 0: MTR_POWER_ON (turns on IDE drive motor supply)

$FF9200 (Configuration/Signal register)

Bit Description
0 0: Power Button pressed /(POWER_SWITCH)
1 0: Top is closed /(TOP_CLOSED)
2 0: RTC Alarm triggered /(RTC_ALARM)
3 0: “Common Source” voltage level below 7.2V /(SOURCE_DEAD) – triggers an NMI
4 0: “Common Source” voltage level below 8.8V /(SOURCE_LOW)
5 0: External Modem (Pin 10 on J204) /(MODEM_WAKE)
6 Reserved (always 1)
7 0: Triggered from the Expansion Port /(EXPANSION_WAKE)
8 Reserved
9 Reserved
10 Reserved
11 Reserved
12 Reserved
13 SELF TEST (?)

$FF9210 8-bit Common Power Voltage Level in 100mV steps

$FF9214 8-bit Reference Voltage Level in 100mV steps

Atari ST Protection: Speedball

SpeedBall protection is almost identical in the code to Garfield. Track 79 has to be shorter than normal (e.g. 5979 bytes, about 5% shorter than normal)

02BDA8  48E77F7E            L0434:MOVEM.L   A1-A6/D1-D7,-(A7)
02BDAC  23C80002C1D0              MOVE.L    A0,$0002C1D0         L0465
02BDB2  13FC00000002C1D4          MOVE.B    #0,$0002C1D4         L0466
02BDBA  263C00000001              MOVE.L    #1,D3
02BDC0  23C30002C1D6        L0435:MOVE.L    D3,$0002C1D6         L0467
02BDC6  4EB90002BE38              JSR       EnterSuper
02BDCC  4EB90002C19E              JSR       InitProtBuffer
02BDD2  50F90000043E              ST        $43E.L
02BDD8  4EB90002BE90              JSR       YMPortDeselect
02BDDE  4EB90002BECE              JSR       FDCForceInterrupt
02BDE4  4EB90002BEF2              JSR       FDCSeekTrack79
02BDEA  4EB90002BF48              JSR       FDCReadTrack
02BDF0  4EB90002BF48              JSR       FDCReadTrack
02BDF6  4EB90002BECE              JSR       FDCForceInterrupt
02BDFC  4EB90002C050              JSR       YMDeselectFloppy
02BE02  51F90000043E              SF        $43E.L
02BE08  4EB90002C06A              JSR       ExitSuper
02BE0E  4EB90002C14E              JSR       CheckProtBuffer
02BE14  10390002C1BE              MOVE.B    $0002C1BE,D0         L045C
02BE1A  B03C0000                  CMP.B     #0,D0
02BE1E  67000012                  BEQ       18(PC)               L0436
02BE22  26390002C1D6              MOVE.L    $0002C1D6,D3         L0467
02BE28  51CBFF96                  DBF       D3,-106(PC)          L0435
02BE2C  4EF900025290              JMP       $25290
02BE32  4CDF7EFE            L0436:MOVEM.L   (A7)+,A1-A6/D1-D7
02BE36  4E75                      RTS

02BE38  2F3C00000001              MOVE.L    #1,-(A7)
02BE3E  3F3C0020                  MOVE.W    #$20,-(A7)
02BE42  4E41                      TRAP      #1
02BE44  DFFC00000006              ADDA.L    #6,A7
02BE4A  4A40                      TST.W     D0
02BE4C  6600002C                  BNE       44(PC)               L0438
02BE50  42A7                      CLR.L     -(A7)
02BE52  3F3C0020                  MOVE.W    #$20,-(A7)
02BE56  4E41                      TRAP      #1
02BE58  DFFC00000006              ADDA.L    #6,A7
02BE5E  23C00002C1C0              MOVE.L    D0,$0002C1C0         L045D
02BE64  12390002C1D4              MOVE.B    $0002C1D4,D1         L0466
02BE6A  4A01                      TST.B     D1
02BE6C  66000020                  BNE       32(PC)               L0439
02BE70  13FC00020002C1D4          MOVE.B    #2,$0002C1D4         L0466
02BE78  4E75                      RTS
02BE7A  12390002C1D4        L0438:MOVE.B    $0002C1D4,D1         L0466
02BE80  4A01                      TST.B     D1
02BE82  6600000A                  BNE       10(PC)               L0439
02BE86  13FC00010002C1D4          MOVE.B    #1,$0002C1D4         L0466
02BE8E  4E75                L0439:RTS

02BE90  4EB90002BE38              JSR       EnterSuper
02BE96  303C0000                  MOVE.W    #0,D0
02BE9A  5200                      ADDQ.B    #1,D0
02BE9C  E308                      LSL.B     #1,D0
02BE9E  00400000                  ORI.W     #0,D0
02BEA2  0A000007                  EORI.B    #7,D0
02BEA6  02000007                  ANDI.B    #7,D0
02BEAA  40E7                L043B:MOVE      SR,-(A7)
02BEAC  007C0700                  ORI.W     #$700,SR
02BEB0  13FC000E00FF8800          MOVE.B    #$E,$FF8800.L
02BEB8  123900FF8800              MOVE.B    $FF8800.L,D1
02BEBE  020100F8                  ANDI.B    #$F8,D1
02BEC2  8200                      OR.B      D0,D1
02BEC4  13C100FF8802              MOVE.B    D1,$FF8802.L
02BECA  46DF                      MOVE      (A7)+,SR
02BECC  4E75                      RTS

02BECE  4EB90002BE38              JSR       EnterSuper
02BED4  33FC008000FF8606          MOVE.W    #$80,$FF8606.L
02BEDC  3C3C00D0                  MOVE.W    #$D0,D6
02BEE0  4EB90002C0B2              JSR       FDCWriteReg
02BEE6  3E3C0028                  MOVE.W    #$28,D7
02BEEA  4EB90002C0AC              JSR       DelayD7
02BEF0  4E75                      RTS

02BEF2  4EB90002BE38              JSR       EnterSuper
02BEF8  4EB90002C0F0              JSR       $0002C0F0            L044E
02BEFE  33FC008600FF8606          MOVE.W    #$86,$FF8606.L
02BF06  3C3C004F                  MOVE.W    #$4F,D6
02BF0A  4EB90002C0B2              JSR       FDCWriteReg
02BF10  33FC008000FF8606          MOVE.W    #$80,$FF8606.L
02BF18  3C3C001B                  MOVE.W    #$1B,D6
02BF1C  4EB90002C0B2              JSR       FDCWriteReg
02BF22  2E3C00060000              MOVE.L    #$60000,D7
02BF28  5387                L043E:SUBQ.L    #1,D7
02BF2A  67000010                  BEQ       16(PC)               L043F
02BF2E  0839000500FFFA01          BTST      #5,$FFFA01.L
02BF36  6600FFF0                  BNE       -16(PC)              L043E
02BF3A  4E75                      RTS
02BF3C  3F3CFFF9            L043F:MOVE.W    #$FFF9,-(A7)
02BF40  4EB90002C14C              JSR       $0002C14C            L0452
02BF46  4E75                      RTS

02BF48  4EB90002BE38              JSR       EnterSuper
02BF4E  42B90002C1C8              CLR.L     $0002C1C8            L045F
02BF54  40F90002C1B8              MOVE      SR,$0002C1B8         L0459
02BF5A  46FC2700                  MOVE      #$2700,SR
02BF5E  33FC009000FF8606          MOVE.W    #$90,$FF8606.L
02BF66  33FC019000FF8606          MOVE.W    #$190,$FF8606.L
02BF6E  33FC009000FF8606          MOVE.W    #$90,$FF8606.L
02BF76  3C3C0016                  MOVE.W    #$16,D6
02BF7A  343C0200                  MOVE.W    #$200,D2
02BF7E  C4C6                      MULU      D6,D2
02BF80  33C20002C1BA              MOVE.W    D2,$0002C1BA         L045A
02BF86  26390002C1D0              MOVE.L    $0002C1D0,D3         L0465
02BF8C  D483                      ADD.L     D3,D2
02BF8E  23C20002C1C4              MOVE.L    D2,$0002C1C4         L045E
02BF94  4EB90002C0B2              JSR       FDCWriteReg
02BF9A  20390002C1D0              MOVE.L    $0002C1D0,D0         L0465
02BFA0  13C000FF860D              MOVE.B    D0,$FF860D.L
02BFA6  E088                      LSR.L     #8,D0
02BFA8  13C000FF860B              MOVE.B    D0,$FF860B.L
02BFAE  E088                      LSR.L     #8,D0
02BFB0  13C000FF8609              MOVE.B    D0,$FF8609.L
02BFB6  33FC008000FF8606          MOVE.W    #$80,$FF8606.L
02BFBE  3C3C00E8                  MOVE.W    #$E8,D6
02BFC2  4EB90002C0B2              JSR       FDCWriteReg
02BFC8  2E3C00050000              MOVE.L    #$50000,D7
02BFCE  2A790002C1C4              MOVEA.L   $0002C1C4,A5         L045E
02BFD4  303C0200                  MOVE.W    #$200,D0
02BFD8  51C8FFFE            L0441:DBF       D0,-2(PC)            L0441
02BFDC  0839000500FFFA01    L0442:BTST      #5,$FFFA01.L
02BFE4  67000030                  BEQ       48(PC)               L0443
02BFE8  5387                      SUBQ.L    #1,D7
02BFEA  67000060                  BEQ       96(PC)               L0446
02BFEE  13F900FF86090002C1C9      MOVE.B    $FF8609.L,$0002C1C9  L0460
02BFF8  13F900FF860B0002C1CA      MOVE.B    $FF860B.L,$0002C1CA  L0461
02C002  13F900FF860D0002C1CB      MOVE.B    $FF860D.L,$0002C1CB  L0462
02C00C  BBF90002C1C8              CMPA.L    $0002C1C8,A5         L045F
02C012  6E00FFC8                  BGT       -56(PC)              L0442
02C016  33FC009000FF8606    L0443:MOVE.W    #$90,$FF8606.L
02C01E  3A3900FF8606              MOVE.W    $FF8606.L,D5
02C024  33C50002C1BC              MOVE.W    D5,$0002C1BC         L045B
02C02A  08050000                  BTST      #0,D5
02C02E  67000018                  BEQ       24(PC)               L0445
02C032  33FC008000FF8606          MOVE.W    #$80,$FF8606.L
02C03A  4EB90002C12E              JSR       $0002C12E            FDCReadRegB
02C040  46F90002C1B8        L0444:MOVE      $0002C1B8,SR         L0459
02C046  4E75                      RTS
02C048  6000FFF6            L0445:BRA       -10(PC)              L0444
02C04C  6000FFF2            L0446:BRA       -14(PC)              L0444

02C050  4EB90002BE38              JSR       EnterSuper
02C056  33FC008000FF8606          MOVE.W    #$80,$FF8606.L
02C05E  103C0007                  MOVE.B    #7,D0
02C062  4EB90002BEAA              JSR       $0002BEAA            L043B
02C068  4E75                      RTS

02C06A  10390002C1D4              MOVE.B    $0002C1D4,D0         L0466
02C070  5300                      SUBQ.B    #1,D0
02C072  4A00                      TST.B     D0
02C074  6700002C                  BEQ       44(PC)               L0449
02C078  2F3C00000001              MOVE.L    #1,-(A7)
02C07E  3F3C0020                  MOVE.W    #$20,-(A7)
02C082  4E41                      TRAP      #1
02C084  DFFC00000006              ADDA.L    #6,A7
02C08A  4A40                      TST.W     D0
02C08C  67000014                  BEQ       20(PC)               L0449
02C090  2F390002C1C0              MOVE.L    $0002C1C0,-(A7)      L045D
02C096  3F3C0020                  MOVE.W    #$20,-(A7)
02C09A  4E41                      TRAP      #1
02C09C  DFFC00000006              ADDA.L    #6,A7
02C0A2  33FC4E7100029B08    L0449:MOVE.W    #$4E71,$29B08       ;(#"Nq")
02C0AA  4E75                      RTS

02C0AC  51CFFFFE                  DBF       D7,-2(PC)            DelayD7
02C0B0  4E75                      RTS

02C0B2  4EB90002BE38              JSR       EnterSuper
02C0B8  4EB90002C0DE              JSR       fdcDelay
02C0BE  33C600FF8604              MOVE.W    D6,$FF8604.L
02C0C4  4EB90002C0DE              JSR       fdcDelay
02C0CA  4E75                      RTS

02C0CC  4EB90002BE38              JSR       EnterSuper
02C0D2  363900FF8604              MOVE.W    $FF8604.L,D3
02C0D8  4EB90002C0DE              JSR       fdcDelay

02C0DE  40E7                      MOVE      SR,-(A7)
02C0E0  3F07                      MOVE.W    D7,-(A7)
02C0E2  3E3C0028                  MOVE.W    #$28,D7             ;(#"(")
02C0E6  51CFFFFE            L044D:DBF       D7,-2(PC)            L044D
02C0EA  3E1F                      MOVE.W    (A7)+,D7
02C0EC  46DF                      MOVE      (A7)+,SR
02C0EE  4E75                      RTS

02C0F0  3C390002C1CC        L044E:MOVE.W    $0002C1CC,D6         L0463
02C0F6  02460003                  ANDI.W    #3,D6
02C0FA  2E3C00050000              MOVE.L    #$50000,D7
02C100  33FC008000FF8606          MOVE.W    #$80,$FF8606.L
02C108  4EB90002C0B2              JSR       FDCWriteReg
02C10E  5387                L044F:SUBQ.L    #1,D7
02C110  67000010                  BEQ       16(PC)               L0450
02C114  0839000500FFFA01          BTST      #5,$FFFA01.L
02C11C  6600FFF0                  BNE       -16(PC)              L044F
02C120  4E75                      RTS
02C122  3F3CFFF9            L0450:MOVE.W    #$FFF9,-(A7)
02C126  4EB90002C14C              JSR       $0002C14C            L0452
02C12C  4E75                      RTS

02C12E  4EB90002BE38              JSR       EnterSuper
02C134  4EB90002C0DE              JSR       fdcDelay
02C13A  33F900FF86040002C1CE      MOVE.W    $FF8604.L,$0002C1CE  L0464
02C144  4EB90002C0DE              JSR       fdcDelay
02C14A  4E75                      RTS

02C14C  4E75                L0452:RTS

02C14E  33FC4E750002BDA8          MOVE.W    #$4E75,$0002BDA8    ;(#"Nu") L0434
02C156  22390002C1D0              MOVE.L    $0002C1D0,D1         L0465
02C15C  068100002EE0              ADDI.L    #6000*2,D1
02C162  2041                      MOVEA.L   D1,A0
02C164  263C00000DAC              MOVE.L    #3500,D3
02C16A  243C00000000              MOVE.L    #0,D2
02C170  3A20                      MOVE.W    -(A0),D5
02C172  3020                L0454:MOVE.W    -(A0),D0
02C174  BA40                      CMP.W     D0,D5
02C176  660A                      BNE.S     10(PC)               L0455
02C178  5482                      ADDQ.L    #2,D2
02C17A  51CBFFF6                  DBF       D3,-10(PC)           L0454
02C17E  60000014                  BRA       20(PC)               L0456
02C182  04820000170C        L0455:SUBI.L    #5900,D2
02C188  6B0A                      BMI.S     10(PC)               L0456
02C18A  13FC00000002C1BE          MOVE.B    #0,$0002C1BE         L045C
02C192  4E75                      RTS
02C194  13FC00010002C1BE    L0456:MOVE.B    #1,$0002C1BE         L045C
02C19C  4E75                      RTS

02C19E  243C0000176F              MOVE.L    #5999,D2
02C1A4  20790002C1D0              MOVEA.L   $0002C1D0,A0         L0465
02C1AA  2639000004BA              MOVE.L    $4BA.L,D3
02C1B0  30C3                L0458:MOVE.W    D3,(A0)+
02C1B2  51CAFFFC                  DBF       D2,-4(PC)            L0458
02C1B6  4E75                      RTS

02C1B8  2304                L0459:DC.W      $2304
02C1BA  2C00                L045A:DC.W      $2C00
02C1BC  0000                L045B:DC.W      $0000
02C1BE  0000                L045C:DC.W      $0000
02C1C0  00000000            L045D:DC.L      $00000000
02C1C4  00017EFA            L045E:DC.L      $00017EFA
02C1C8  00                  L045F:DC.B      $00
02C1C9  00                  L0460:DC.B      $00
02C1CA  00                  L0461:DC.B      $00
02C1CB  00                  L0462:DC.B      $00
02C1CC  0003                L0463:DC.W      $0003
02C1CE  0000                L0464:DC.W      $0000
02C1D0  000152FA            L0465:DC.L      $000152FA
02C1D4  0100                L0466:DC.B      $01,$00
02C1D6  00000001            L0467:DC.L      $00000001