Solas Technical Details
This is the Solas Technical Manual, containing advanced details on the inner workings of the hardware and software. This should help to access Solas features from your own software or to develop compatible hardware add-ons.
This page is a work in progress, may be incomplete and may contain mistakes. If something isn't working as you expect, please contact me and I'll do my best to help out. More detail is being added here semi-regularly; please check back every so often for updates.
Communicating with Solas
Solas connects to the Amiga using the A1200 standard clockport. This is normally at a fixed address on the A1200 ($D8C001), but Solas is also compatible with additional clockports found at different addresses, e.g. clockport splitters, Zorro cards with clockports and so on. Communication is by means of reading and writing bytes of data from and to specific addresses corresponding to registers on Solas. These registers are located at various offsets from the base address of the clockport used by Solas; the offsets and functions are detailed below. Thus, to access a particular register, the base address must first be determined.
Once the base address is known, the Solas registers can easily be accessed. The common communication processes typically start with either a command code (to give an instruction to Solas), or a query code (to request information from Solas). Any relevant data is then read from or written to the appropriate register.
Solas has two modes: communications mode (where communication with the host Amiga has priority) and running mode (the default mode, where LED strip refreshing has priority). Refreshing the LED strips is very timing-critical, and requires the full attention of the controller on Solas. Therefore, internal interrupts are disabled while the refresh process is happening, and communication with Solas can be quite slow. Starting a command or query process disables the LED refreshes and puts the Solas board in communications priority mode, so communications can happen much more quickly. It will remain in communications mode until the expected number of bytes have been read or written, after which time it reverts to LED priority mode. For this reason, try to complete a command or query process promptly to try and avoid any pause in the LED activity.
There is no handshaking taking place during Solas communications. As a result, care must be taken to provide a minimum amount of time between bytes. See the Commands and Queries section below for details.
Obtaining the Solas Base Address
The Solas base address is the address of the clockport to which it is attached. Typically, this will be determined when the Solas is first set up and won't change unless the hardware configuration changes. The SolasControl software verifies the presence of a Solas board and sets an Env variable called "solas" containing the address (in hex format stored as ASCII). So, the simplest method of finding a Solas board is to read the address from the solas Env variable. If this variable doesn't exist, SolasControl has not verified the presence of a Solas board, so other programs should not try.
Locking the Solas Board
From the software-side, it's important to ensure that only one piece of software is accessing the software at one time. The Solas software uses an Amiga semaphore named "solas" to regulate access to the board, and will obtain that semaphore before any communication is attempted and release it afterwards. Any software looking to access Solas should use this semaphore and must not access the board unless the semaphore has been obtained. Since some software can regularly access the board, try not to hold the semaphore any longer than is required.
Note that SolasControl itself is an exception, and will hold the semaphore for as long as it is running. This has the effect of making any other software looking to access Solas wait until SolasControl is closed.
Solas currently uses the following registers, located at the given offsets from the base address:
||Send data bytes here to give information to Solas
||Send a command byte here to start a command process
||Send a query byte here to start a query process
||Read the results of the most recent query
||Sets the LED strip ID (0 or 1) to be considered for subsequent commands and queries
||Sets the fan speed (0-100). Note that this register function may be deprecated for final release.
||Sets the fan mode. Note that this register function may be deprecated for final release.
||Write $AA to this address once the ID string is confirmed to activate full communication to/from Solas. Not currently implemented.
||Contains the Solas ID string "RGBCtrl"
Verifying a Solas Board
This process is optional, and usually only carried out by SolasControl. But it can be used to verify that the board is actually located at a given address. The ID register (Solas base + $FF) contains a character from the string "RGBCtrl", and cycles through the characters with each byte read from that register. Since software can't guarantee it's the first time to read from the register, to verify the connection, it's important to read at least 14 characters from this register, checking that resultant string for the substring "RGBCtrl". For example, the string obtained may look like "trlRGBCtrlRGBC".
Reading from the ID register does not put the Solas board in communications mode, so it's important to include a small delay between reads as detailed for sending commands below. Additionally, some accelerators with very tight chipset timing (e.g. ACA1221, TF1260) can read null from the ID register when Solas isn't in communications mode, so any null bytes read during this verification process should be ignored (up to a point - e.g. 10 null bytes in a row suggests that a Solas board isn't actually present).
Commands and Queries
Almost all communication with Solas happens as either a command (sending information to Solas, e.g. telling it to do something or changing a setting) or a query (sending a request for information to Solas and reading the result.
There is no handshaking taking place during Solas communications. As a result, care must be taken to provide a minimum amount of time between bytes transferred. A slightly longer delay is required when Solas is not in communications mode because the LED refresh process might be underway, and the request will not be read by Solas until the refresh is completed. This means that the slightly longer delay is required between sending a command byte and the first data byte (if expected). Current Solas software uses a delay of 10ms after a command byte and when not in communications mode, and 5ms when in communications mode. Without these delays, bytes written may replace previous bytes before Solas has had a chance to read them, and queries might return the same byte twice.
Sending commands to Solas involves sending a single-byte command ID to the Command register (offset $04). If the command requires additional data to be provided, Solas will enter communications mode as soon as it detects the sent command byte, and will wait for all the expected data bytes to be written to the data register (offset $00). Once all data bytes are received, Solas reverts to normal run mode. Sending a byte to the Command register while data bytes are being sent will abort the current command and start a new command process based on the new ID.
A small delay is required between sending the command byte and sending the first data byte.
The command byte values will soon be available as a header file for inclusion with C or Blitz Basic code. Currently available command bytes are as follows:
- NONE (00)
- Does nothing, but cancels the current command and returns Solas to run mode.
- SETLETDS (01)
- Stream RGB values to set every LED in the current strip (as set in the Current Strip register). Expects 3 data bytes for every LED with red, green and blue values (0-255). Note the number of LEDs is based on the current configuration as set in SolasControl, regardless of whether that many LEDs are attached or not.
- SETALLLEDS (02)
- Sets all LEDs in the current strip to the same RGB values. Expects 3 data bytes with the desired red, green and blue values (0-255).
- SETSINGLELED (03)
- Sets a single LED in the current strip to the given RGB values. Expects 4 data bytes, the first byte defines the LED to set (0-199), followed by the red, green and blue values (0-255).
- FILLLEDS (04)
- Sets a range of LEDs in the current strip to the given RGB values. Expects 5 data bytes: the start LED (0-199), the number of LEDs (1-199) and the red, green and blue values (0-255). Note: this command is not currently implemented.
- EVENT (05)
- Defines the parameters and style of an event for the current LED strip. Expects 11 bytes: the event code (defined here(add link)), the style (defined here(add link)), the speed, the size, the red, green and blue values for the primary colour, the red, green and blue values for the secondary colour, and the direction (0=forwards, 1=reverse).
- STRIP (06)
- Defines the properties of the current LED strip. Expects 2 bytes: the first sets whether the strip is enabled (1) or not (0). The second defines the number of LEDs in the strip (0-200).
- FAN (07)
- Defines the main fan control parameters. Expects 5 bytes: fan speed (0-100), fan sensor (0-3 or 99, 0=manual, 1-3=sensor 1-3, 99=highest sensor reading), minimum speed (0-100), stay on property (1=true, 0=false), and fan setpoint (0-255). Note that, as with the temperature readings, this value is twice the reading, so for a setpoint of 42 degrees C, send the value 84.
- ALLOFF (08)
- Sets all LEDs in the current strip to off (RGB 0, 0, 0). Note: this command is not currently implemented.
- PREVIEW (09)
- Puts Solas in Preview mode, which forces the Preview event for the current strip to be displayed, overriding all other events. No data bytes expected.
- ENDPREVIEW (10)
- Returns Solas to normal running mode, previously defined events will be displayed. No data bytes expected.
- SAVETOFLASH (11)
- Saves the currently active settings to flash memory on the Solas, which will be used as the default settings from that point on. No data bytes expected.
- LOADFROMFLASH (12)
- Loads the settings saved to flash memory on the Solas, replacing the current settings. No data bytes expected.
- PIDCONFIG (13)
- Defines the PID values used for the fan controller. Expects 6 bytes, with 2 bytes representing the P, I and D values. The first byte is the integer part of the value, the second byte is the decimal part * 100. So to send a value of 2.45, the first byte should be 2, the second byte should be 45.
- TEMPCONFIG (14)
- Defines the settings for the temperature sensors, including the calibration values and the names for each sensor. Expects a variable number of bytes, but at least 12. The first 9 bytes comprise of the offset (1 byte) and multiplier (2 bytes) values for each of the three sensors in turn. The offset is an integer value, the first byte of the multiplier is a signed integer and the second byte of the multiplier is the fractional part * 100, as with the PID values above. Once all three sensor values have been sent, the sensor names for each sensor are expected. These consist of up to 10 ASCII characters, and must be terminated by a null character. Once the null character is received, the next sensor name is expected. If a name is not required, simply send a null character. The third null character received terminates the command.
- AUDIOCONFIG (15)
- Defines the settings for the audio input used by some LED styles, specifically the offset, range and threshold settings. Expects 6 bytes, with each 16-bit value transmitted as two bytes in big endian format, i.e. most significant byte followed by least significant byte.
- PATTERN (16)
- Defines an arbitrary pattern of RGB values to be used by some LED styles. Expects a variable number of bytes, up to 302. The first byte is the LED strip to which the pattern should be assigned (0 or 1), the second is the number of points to define in the pattern (1-100), and after that, each point in the pattern is sent as 3 bytes for the red, green and blue values (0-255) of that point. The command ends when the number of RGB values specified has been received.
- I2CWRITE (20)
- Starts the process of sending a packet to an I2C device. The first data byte is the I2C address of the destination device. The second byte is the length in bytes of in the message, and after that, the given number of bytes are collected in a buffer before sending to the I2C bus.
- I2CREAD (21)
- Starts the process of reading a data from an I2C device. Expects 2 data bytes, the first data byte is the I2C address of the device to read, and the second byte is the length in bytes to read from the source device. Once this command has been received, Solas will read the requested bytes into a buffer, and they can be read using the I2C read query.
- BOARDCONFIG (22)
- Defines general settings for the Solas board. Expects 2 data bytes: reset with host (0 or 1), and event hold (0-255).
- LCDCONFIG (23)
- Defines settings for an LCD module. Expects 16 data bytes: Enabled (0 or 1), LCD module type (currently Midas=0, Hitachi=1), I2C address of the LCD module (0-255), width of display (8-20), height of display (1-4), show temperatures 1, 2, 3 and fan speed (0=false, 1=true), default page time (10-255), sensor name length (0=short, 1=long), backlight enabled (0=false, 1=true), I2C address of the backlight RGB controller, and the red, green and blue values to use for the backlight.
- LCDMODE (30)
- Sets the mode for LCD use. Expects 1 data byte. The modes for LCD use are Paged and Direct. Paged mode cycles through complete messages, including automated pages displaying temperature information. Direct mode gives full control to the host Amiga. Note: this command is not currently implemented.
- LCDMESSAGE (31)
- Defines a complete message to display on the LCD module, either as a complete page or as one line of a page. Expects a variable number of data bytes. First byte is the page number for this message. If that page number is already in use, it will be overwritten by the new page. Second byte is the page time to be used for that page. Byte 3 contains some control flags (bit 0 = page enabled, bit 1 = show only once, bit 2 = show immediately). Byte 4 specifies the line number of the message (numbers 1-4 specify the line of the page to insert the text, a line number of 0 specifies that the text is the entire page and will fill the page starting at the top line). Byte 5 is the length of the message, and following this, the length number of ASCII bytes are expected. This string will then be stored in the specified LCD message page for display.
- LCDCLEAR (32)
- Clears the LCD module display. Only applicable in Direct mode. No data bytes expected. Note: this command is not currently implemented.
- LCDHOME (33)
- Sets the cursor location of the LCD module to the top left position (0, 0). Only applicable in Direct mode. No data bytes expected. Note: this command is not currently implemented.
- LCDLOCATE (34)
- Moves the cursor location of the LCD module to the given position. Expects 2 data bytes, X coordinate (0-19) followed by Y coordinate (0-3). Only applicable in Direct mode. Note: this command is not currently implemented.
- LCDPRINT (35)
- Displays characters given at the current cursor location on the LCD module. Only applicable in Direct mode. Note: this command is not currently implemented.
- BOARDRESET (99)
- Tells Solas to do a full reset and start as if just powered up. No data bytes expected.
- UPDATEFLASHLOADER (198)
- Starts the update process for the flash loader firmware. Don't use this - just do it via the SolasControl update function!
- UPDATEFIRMWARE (199)
- Starts the update process for the main firmware. Don't use this - just do it via the SolasControl update function!
Requesting information from Solas involves sending a single-byte query ID to the Query register (offset $08), followed by reading the resulting byte(s) from the same register. The same delay is needed between sending the query byte and reading the result, however that delay may need to be increased for some queries to allow for the result to be processed. In such cases, the description of the query will give further details.
Some queries require additional information, which needs to be sent to the relevant register first. Again, where this is the case, details will be given in the description.
- Q_VERSION (01)
- Returns 2 bytes representing the current firmware version, followed by the current firmware revision.
- Q_MAXLEDCOUNT (02)
- Returns 1 byte indicating the maximum number of LEDs supported in a strip. Note that this indicates board capability, not current LED strip configuration, which is read separately. Currently this value is 200.
- Q_MAXLEDSTRIPS (03)
- Returns 1 byte indicating the maximum number of LED strips supported. Again, this indicates board capability, not current LED strip configuration, which is read separately. Currently this value is 2.
- Q_MAXTEMPSENSORS (04)
- Returns 1 byte indicating the maximum number of temperature sensors supported. Again, this indicates board capability, not current LED strip configuration, which is read separately. Currently this value is 3.
- Q_TEMPSENSOR (10)
- Returns 1 byte indicating the current reading of a temperature sensor. The temperature sensor to be read is determined by the contents of the Data register (offset $00), which must be written before sending the query byte. The reading corresponds to double the temperature in degrees C, therefore this result must be divided by two to give the actual reading, e.g. a raw value of 63 indicates a temperature of 31.5 degrees C.
- Q_FANSPEED (11)
- Returns 1 byte indicating the current fan speed setting in percent (0-100). Note that there is no feedback from the fan, so this only indicates intended speed, not actual speed.
- Q_STRIPSETTINGS (20)
- Returns 2 bytes representing the enabled status of the current strip (0 or 1), followed by the configured number of LEDs in that strip (0-200).
- Q_FANSETTINGS (21)
- Returns 6 bytes representing the current fan settings. The first byte is the fan mode (0=manual, 1=automatic), the second is the fan speed setting (0-100), the third is the sensor setting (when in automatic mode) (0=manual, 1-3=controlled by sensors 1-3, 99=highest sensor reading), the fourth is the minimum fan speed setting (0-100), the fifth is the keep fan on setting (0=false, 1=true), and the sixth is the fan setpoint temperature. As for the sensor settings, the setpoint represents the temperature in degrees C * 2, so if the result is 83, then the setpoint is 41.5 degrees C.
- Q_EVENTSETTINGS (22)
- Returns 10 bytes representing the properties of the event style specified. The event code is determined by the contents of the Data register, which must be written before sending the query byte. The bytes received are as follows: Style code, style speed, style size, primary colour red, green and blue values, secondary colour red, green and blue, and direction (0=forwards, 1=reverse).
- Q_PIDCONFIG (23)
- Returns 6 bytes representing the P, I and D values used for the fan controller. These values are transmitted as two bytes for each value: first the integer part, then the fractional part. Note that the format of the fractional part isn't a floating point value - it's the fractional part * 100. So the value 1.25 is transmitted as 1 (1st byte) 25 (2nd byte).
- Q_TEMPCONFIG (24)
- Returns 9 bytes representing the configuration of the temperature sensors, 3 bytes for sensors 0, 1 and 2 in turn. The first byte for each sensor is the offset value, the other two bytes are the multiplier value in the same format as the PID values above.
- Q_AUDIOCONFIG (25)
- Returns 6 bytes representing the configuration of the audio input used for some LED effects. These bytes consist of two bytes each for the offset, range and threshold values in turn. The values are 16-bit words sent in big-endian format, i.e. the most significant byte followed by the least significant byte.
- Q_BOARDCONFIG (26)
- Returns 2 bytes for general board configuration options. The first byte is Reset with host (1=enabled, 0=disabled). The second byte is the HDD/CC0 activity hold delay value.
- Q_LCDCONFIG (27)
- Returns 16 bytes representing the LCD module configuration as follows: Enabled (0=false, 1=true), LCD module type (currently Midas=0, Hitachi=1), I2C address of the LCD module (0-255), width of display (8-20), height of display (1-4), show temperatures 1, 2, 3 and fan speed (0=false, 1=true), default page time (10-255), sensor name length (0=short, 1=long), backlight enabled (0=false, 1=true), I2C address of the backlight RGB controller, and the red, green and blue values to use for the backlight.
- Q_I2CREAD (30)
- Returns the contents of the Solas I2C read buffer. This buffer will be filled based on the most recent I2CREAD command, which specifies the address and number of bytes to read. If more bytes are read than were requested, the additional bytes read are undefined and could contain garbage.
- Q_FLASHLOADERVERSION (40)
- Returns 2 bytes representing the current version, followed by the current revision, of the flashloader module used for updating the main firmware.
Connector Pinouts and Functions
Details are provided here to assist connecting and developing additional hardware to Solas. Please be aware that incorrect connections can damage the Solas board and the A1200. Please check critical connections with a multimeter before powering up, as errors in this documentation are possible. If in doubt, ask me.
Solas connects to the standard A1200 clockport and acts like a standard buffered 4-port clockport splitter. Address lines A14 and A15 are provided from elsewhere (e.g. ROM adaptor, Gayle adaptor) and determine which of the four ports are being accessed. Solas itself uses port 3 internally (address $D8C001), while ports 0, 1 and 2 are available for connecting other clockport devices. Port 0 is the same address as the native clockport ($D80001), Port 1 is $D84001 and Port 2 is $D88001. Thus, the Solas board can replace another clockport splitter in an A1200. Please not that the splitter functionality will not work on other clockports, e.g. Zorro cards, or when connected via another clockport splitter.
The RTC_CS line is connected to all three ports, meaning that all support the use of an RTC module. However, only one should be connected at any one time, and mechanically only ports 1 and 2 are suitable for the common mini-RTC modules.
Address lines A14 and A15 have pull-ups; when these are left disconnected, the splitter functionality is disabled and Solas will act as a stand-alone clockport device, responding at the address of the port to which it is attached.
Pinouts of the clockports on Solas are identical to those of the native A1200 and so won't be detailed here. Pins are numbered 19-40, as per the A1200 motherboard, to try and minimise confusion and the risk of improper connections.
Solas has a 5V connection from the clockport, which is enough for use with modest LED strips. However, the LED strips require a 5V supply, and so if a long strip is being connected, supplementary power is recommended. Additionally, powering a 12V fan requires the supplementary power connection as there is no 12V supply from the clockport. The passthrough is a standard floppy-style EI connector with all pins passed through so both connectors are functionally identical, allowing power to be passed through to the floppy drive. Pin 1 is closest to the LED strip connectors, though the connectors are polarised so incorrect connection is difficult.
This connector is a general-purpose 5V feed available for additional hardware, e.g. a Bifrost Heimdall module or a 5V LCD module. Pin functions are labelled on the board; pin 1 is closest to the edge of the board.
This connector is a double 5-pin connector, with all 5 pins connected through so both sides are functionally identical. This allows a passthrough of the A1200 keyboard LED signals, and the FDD, HDD and CC0 signals are used by Solas to react to drive activity. These signals are active high, and pull-downs are provided on the Solas board so connection of some or all of these signals is optional.
1: Power LED (LED)
2: Floppy LED (MTR0)
3: Hard Drive LED (IDE_LED)
4: PCMCIA activity (CC_ENA)
5: Ground (Note: not connected to Solas ground in rev 1.3 PCB and above)
These two connectors use machined round pins and are mechanically and electrically compatible with addressable 5V LED connectors commonly found on PC motherboards. One pin is removed to ensure correct polarity. Pin 1 is closest to the edge of the PCB. The data pin carries a 5V TTL-level serial stream using the protocol for common WS2812B and similar RGB LEDs. For more details on the protocol, see the WS2812B datasheet.
Temperature Sensors 1 & 2
These two temperature sensor inputs expect a voltage that is linearly proportional to temperature. There are various suitable sensors, but the intended use is for LM-35 sensors. These take a 5V power supply and output a voltage of 10mV per degree C, so 400mV is 40 degrees C. This makes them very easy to work with.
1: Temperature input
Temperature Sensor 3
This sensor differs from the other two in that it's intended for use with a thermistor. These are notorious for their non-linear, and their specs vary wildly, so it's difficult to get an accurate reading. Nevertheless, this input is useful for having a rough idea of temperature, and is compatible with the internal thermistor of the 68060 CPU, for example. A thermistor connected to this input is connected between ground and the input to the ADC, with a 1K pull-up provided. Thus, a thermistor with a relatively low resistance is recommended, as a very high resistance here will result in a very small change in the resulting potential divider. Polarity is unimportant for typical thermistors.
2: Temperature input
The fan connectors use a variable voltage to control the fan's speed. While this is less precise than a dedicated PWM signal to the fan, it allows almost any fan to be connected and controlled. Fan tachometer readings are not supported. One fan connector is wired for 5V, the other is wired for 12V. Please note that ground switching is used to generate the variable voltage, thus the fan is connected between the power rail (5V or 12V) and the variable voltage, as opposed to between the variable voltage and ground.
1: Variable voltage (Fan ground)
2: Power rail (5V or 12V)
The audio input feeds into a simple amplifier and rectifier to produce a positive-going representation of the output audio level, which is then fed into the ADC of the controller. It is intended to take a mono audio feed, as found at pin 1 of the RF modulator on the A1200 (and A600), but that feed could be from any source in the vague ballpark of 1Vp-p. A ground pin is provided, but typically not necessary. The input pin is labelled SIG. Note that no coupling capacitor is provided, so if the alternative source has a DC offset, a coupling capacitor (e.g. 1uF ceramic) should be provided externally.
The 4-pin I2C connector provides a convenient bus for expansion modules like sensors and LCD modules. It uses 3.3V signalling and runs at 100kHz. 3.3V power is available at the connector, though it is of limited capacity so be wary of attaching heavy 3.3V loads. Some I2C devices require a 5V supply, which can be sourced at the Aux 5V connector.
I2C pinouts do not follow any particular standard or convention. Please double-check the documentation of any device you wish to connect for proper pinouts and assemble as required.
2: SCL (Clock)
4: SDA (Data)
This 7-pin header connects to the spare GPIO pins on the controller and is intended for future expansion. One possible use of these pins is to use Solas to program JTAG devices, e.g. CPLDs on other hardware. The pins are labelled as such, though no support is currently available for any functionality on these pins. Note that unlike most of the connectors, pin 1 on the Spare connector is away from the edge of the board.
1: TMS (C7/Rx)
2: TDI (C6/Tx)
3: TDO (C5)
4: TCK (A4)
This 5-pin connection is used for programming the controller chip, and follows the common pinout for Microchip PIC chip programmers. Suitable programmers can be used to flash the board with the current firmware directly using this connector, which will recover a "bricked" board in the case of a corrupted firmware update using SolasControl software causing the board to become unresponsive.
Solas can be flashed while installed in the Amiga, but for this, the 5V pin must not be connected to the programmer. The programmer should be connected, then the Amiga powered on. Once programming is completed, removing the cable should boot the board. Programming outside the Amiga can be done too, so long the programmer can provide enough current on the 5V pin to power the whole board.
4: PGD (Data)
5: PGC (Clock)