RCX Manual

Ole Caprani, University of Aarhus, Department of Computer Science,
ocaprani@daimi.au.dk

Last updated 6.2.06.


Contents

Introduction
The H8/3292 Microcontroller
The RCX: CPU, Memory and Input/Output Devices
The RCX CPU
The RCX Memory
The RCX Input/Output Devices
Access to RCX Device Registers
RCX Interrupts and Interrupt Handlers
Buttons
RCX Input Ports and Sensors
Infrared Transmitter/Receiver
Liquid Crystal Display (LCD)
Speaker
RCX Output Ports and Actuators
The RCX Executive
Communication with the RCX Executive
The Request/Reply Protocol
The Byte Protocol
The Bit Protocol
The RS232 Connected Infrared Transmitter/Receiver
A Program to Communicate with the RCX Executive
The RCX Executive as a Run-time Environment
LCD Routines
Compilation of Programs for the RCX
How to Install Cross-Assembler and Cross-Compiler
Translation of Assembly Language Programs
Compilation of C-Programs
Download of Programs to the RCX
References

Introduction

The LEGO MindStorms Robotics Invention System allows you to build an autonomous car that can drive through a maze avoiding obstacles or to construct a measuring device like a digital thermometer that can show the minimum, maximum, and mean temperatures over a period of time. A programmable controller, called the RCX, a component of the MindStorms System, provides the means for controlling a car or monitoring the temperature. The RCX is build into the car or the digital thermometer and the RCX is programmed to control the behaviour of the car or to monitor the temperature measurement sampling of the thermometer.

Embedded into the RCX is a microcontroller, a Hitachi H8/3292, with a CPU, called the H8/300 CPU Core. This CPU runs the control program. Through the H8/3292 based device controllers the control program access RCX input/output devices like buttons, a speaker, and a special purpose Liquid Crystal Display (LCD). Furthermore, sensors like a touch sensor or a temperature sensor can be connected to the RCX input ports providing sensor input to the control program and the control program can activate actuators like motors connected to the RCX output ports. Stimuli from the environment - a car bumping into an obstacle - can be registered by a sensor, e.g. a touch sensor, and transformed into input values for the control program. The resulting response - turning the car - can be accomplished by the control program through values output to actuators, e.g. a motor.

The RCX is equipped with the following input/output devices:

Input devices
Four buttons labelled Run, OnOff, View, Prgm
Three input ports labelled 1,2,3
Battery voltage level
Timers
Infrared receiver

Output devices
Liquid Crystal Display
Speaker
Three output ports labelled A,B,C
Infrared transmitter

The RCX interacts with the environment through these input/output devices and sensors/actuators connected to the RCX input/output ports. The following sensors/actuators are available:

Sensors Examples of stimuli
Touch sensor Obstacle encountered, go signal on a touch button
Light sensorColor reflection, ambient light
Rotation sensorAngle turned by wheels, movements of shaft
Temperature sensor Body temperature, outdoor temperature

ActuatorsExamples of response
MotorMovements of car, elevator going up
LampFlashing light, red alarm light
Sound elementBuzz sounds

The development of control programs takes place on a host computer (a PC or a UNIX machine). The control program is brought to the RCX through a download on a serial communication link provided by the infrared transmitter/receiver. The control program can be developed in different programming environments offered by LEGO: ROBOLAB, a graphical programming environment hosted on a PC; Software Developers Kit (see the entry on LEGO MindStorms), an environment hosted on a PC that uses Visual Basic as a host language for download of rather low level machine-code like control programs.

This manual describes a simple programming environment hosted on a UNIX machine. Programs can be written in the high level language C and in assembly language for the H8/300 CPU. Programs are cross-compiled/cross-assembled to native H8/300 code and downloaded to the RCX by means of a simple protocol provided by the on-chip ROM resident RCX executive running on the H8/3292 after power up and reset. After download the program is started and the RCX executive can serve as a run-time environment for the program providing services like I/O routines for access to the RCX input/output devices, e.g. the LCD. Also, this manual gives details that makes it possible to program direct access to the RCX input/output devices through the memory mapped device registers interfacing the CPU to the device controllers.

This manual and the UNIX programming environment can be used as tools to develop simple control programs for the native RCX but it can also be used as tools for developing programming environments for the RCX like a Real-Time Operating System.

The H8/3292 Microcontroller

The single-chip microcontroller embedded into the RCX is a Hitachi H8/3292 of the H8/3297 Family. The chip integrates the three main components of a computer: an H8/300 CPU, memory and input/output. The components are connected by an on-chip address/data/control bus.

The H8/300 CPU is based on a general register architecture. The instruction set include register-register arithmetic and logic operations. The addressing modes include most of the common addressing modes like register direct, register indirect, program counter relative, and memory indirect. The address space is 16-bit (64 Kbytes) for program and data combined.

The on-chip memory consists of 16 Kbytes mask programmable ROM and 512 bytes RAM. Furthermore, a 128 bytes on-chip register field is used as memory mapped registers to interface to the on-chip input/output circuitry. The memory map defines how the on-chip memory and possible external off-chip memory maps into the 16-bit address space. The memory map is partly defined by the input level on two pins on the chip (called MD1 and MD0; these can be accessed as bit 1 and bit 0 of the Mode Control Register at address 0xffc5 in the register field). These two bit select an operating mode of the microcontroller (mode 1, 2 or 3). In all modes the on-chip RAM and the on-chip register field maps to the same addresses. In mode 1 and 2, called expanded modes, it is possible to access external off-chip memory and off-chip device registers through the address/data pins of the microcontroller chip. In mode 3, called single-chip mode, only on-chip ROM and RAM, and the on-chip register field is available. When external memory is used it is mapped into the address space by means of the external logic for address decoding.

On-chip input/output includes three types of timers (a 16-bit free running timer, 8-bit timers, and a watch dog timer), a serial communication interface, an Analog/Digital converter, and input/output ports. The timers can be used without off-chip circuitry. The serial communication interface can act as a device controller for an external serial transmitter/receiver. Similarly, the 10-bit A/D converter can be turned into a device controller for up to eight analog channels. The external analog input on an input line connected to one of the eight pins of the A/D converter can be sampled by an on-chip sample-and-hold circuit and converted to a 10-bit value available in a device register. An on-chip analog multiplexer can operate in both a single shot and scan mode. Scan mode allows continuous conversion on more channels delivering digital results in different device registers. The pins of the input/output ports can be connected to off-chip input or output lines. When the processor reads from a device register corresponding to an 8-bit input port, the byte value returned reflects the 1's and 0's on the input lines. With almost no external circuitry an external button can be directly connected to an input line and the state of the button can be input from the input port. When the processor writes into a device register corresponding to an 8-bit output port, the byte value of 1's and 0's placed in the register is output to the pins of the output port and the output lines connected to the pins can be used directly to drive external circuitry like a Light Emitting Diode (LED)

An on-chip interrupt controller provides an interrupt mechanism for both internal and external interrupts. Internal interrupts are generated caused by events in the on-chip input/output components. Each separate event (e.g. end of A/D conversion and timer overflow) interrupts though a separate interrupt vector. External interrupts are generated caused by external events signalled through pins on the microcontroller chip (e.g. a pin for Non Maskable Interrupt (NMI)). All interrupts can be globally or individually disabled or enabled (except NMI).

The RCX: CPU, Memory and Input/Output Devices

The RCX is a programmable controller that integrates the three major components of a computer, processor, memory, and input/output devices into a single LEGO brick.

Physically, the electronics of the computer inside the RCX consists of a printed circuit board and a 9V battery based power supply. On the circuit board chips and other electronic components are mounted and connected, e.g. the H8/3292 single-chip microcontroller, a 32Kbytes RAM chip, chips for motor control, LCD screen and LCD controller chips, a speaker, connections to the RCX input/output ports on the plastic cover, and contacts for the four rubber buttons. Pictures of a disassembled RCX with a detailed list of components can be obtained from RCX Internals.

The logically structure of the RCX controller is that of a simple low-end personal computer with a single bus used to connect the processor, memory and input/output devices. Input/output is memory mapped and each device consists of two parts: one containing the electronics interfacing the device to the bus, and one containing the mechanical and electronical components of the device itself. Examples of mechanical and electrical components of devices in the RCX includes buttons, LCD screen, and speaker but also the mechanical and electrical constructions build out of LEGO bricks including the sensors and and actuators interfacing these application dependent devices to the RCX. This shows that the level of abstraction determines what is to be considered as the interfacing part and what is to be considered as the device itself. The interfacing part is normally referred to as the device controller.

It is the logically structure that is useful to think of when programming the RCX controller. The components of the logically structure will now be described from a programmers point of view.

The RCX CPU

The processor seen by the programmer is the H8/300 CPU. It is driven by a system clock with the frequency 16 MHz. The CPU has eight general purpose 16-bit registers (r0 - r7, r7 is used as stack pointer (sp) ), a 16-bit program counter (pc), and an 8-bit condition code register (cc). The condition code register includes arithmetic status bits like carry, overflow, and zero, and furthermore the interrupt mask bit that controls global disable/enable of interrupts. The instruction set includes register-register arithmetic, e.g. 16-bit addition, 16-bit subtraction, 8-bit multiplication, and 16-bit/8-bit division. Furthermore, there are the usual logic operations xor, or, and, not, shift operations, bit manipulation, branch, call and return from subroutine, return from exception (interrupt), and the sleep instruction to enter low power consumption mode. The data types include bit, 4-bit nibbles (packed BCD), byte, and word (2 bytes). The addressing modes are:

Address mode Assembly language
Register direct rn
Register indirect@rn
Register indirect with 16-bit displacement@(d:16,rn)
Register indirect with post-increment @rn+
Register indirect with pre-increment @-rn
Absolute address (8 or 16 bits) @aa:8, @aa:16
Immediate (8-, or 16-bit data) #aa:8, #aa:16
pc-relative (8-bit displacement) @(d:pc)
Memory indirect @@aa:8

The RCX Memory

The H8/3292 chip of the RCX operates in mode 2. The mode can be read as the values of bit 1 and bit 0 in the Mode Control Register at address 0xffc5. In mode 2 the on-chip ROM, RAM, and register field are enabled. Furthermore, the 32 Kbytes external RAM chip is mapped into the 16-bit address space by external address decoding logic. We can only access the external RAM chip when we use adresses in those parts of the address space that are not occupied by the on-chip memories.

The memory map is thus determined by the choice of mode 2 and the external address decoding. The resulting memory layout is as follows:

Addresse range Memory type Contents
0x000 - 0x3fff on-chip mask programmable ROMH8/3292 interrupt vectors, RCX executive
0x8000 - 0xefffoff chip RAMprogram/data
0xf000off-chip registerdevice register for RCX output ports
0xfd80 - 0xff7fon-chip RAMRCX interrupt vectors/program/data
0xff88 - 0xffffon-chip register field H8/3292 device registers

The RCX Input/Output Devices

The RCX input/output devices consists of two parts: the RCX input/output device controller and the RCX input/output device itself. The RCX device controller is the device as seen from the inside, i.e. as seen from the programmers point of view, the RCX input/output device itself is the device as seen from the outside. Seen from the inside, the four buttons are four bits in the memory mapped registers of two H8/3292 input/output ports; seen from the outside the buttons are plastic buttons placed on the plastic cover of the RCX. Since we are going to describe the RCX devices from the programmers point of view, we will mainly describe the RCX device controller part.

A program running on the RCX CPU communicate and synchronize with the RCX devices in the usual way through device registers and interrupts. Hence, the communication and synchronization interface for each RCX device controller is the RCX device registers and RCX interrupts that is provided by the RCX device controller.

Most of the RCX device controllers are based on the H8/3292 input/output components. The memory mapped device registers of the H8/3292 input/output component is also used as the RCX device registers and the interrupts provided by the H8/3292 input/output component are also used as RCX device interrupts. The only exception is the RCX output ports. These are based on external electronic components; hence, the RCX output port controller do not use the H8/3292 input/output components. The device registers of the RCX output controller is accessed through the address/data pins of the H8/3292. This means that they are memory mapped into the address space not used by on-chip memories. Therefore, the RCX device registers of the RCX output ports are not part of the on-chip register field address range.

The RCX device controllers are based on the H8/3292 componets as follows:

RCX device controlled Device registers Interrupts
buttons device registers of I/O port 4 and 7. Two input lines of port 4 and two of port 7 are used. IRQ0, IRQ1 device registers Run is connected to IRQ0, OnOff to IRQ1
input portsdevice registers of A/D converter and device registers of I/O port 6. Three output lines of port 6 are used A/D interrupt
battery voltage leveldevice registers of A/D converter A/D interrupt
timersdevice registers of timers timer interrupts
infrared transmitter/receiverdevice registers of SCI, I/O port 4, and timer 1. One output line of port 4 is used SCI interrupts, timer 1 interrupts
LCD device registers of I/O port 6. Two lines of port 6 are usedno interrupts
speaker device registers of I/O port 6 and timer 0. One output line of port 6 is usedtimer 0 interrupt
output ports device register in external address spaceno interrupts

Access to RCX Device Registers

The bits of the RCX device registers can be accessed directly by bitmanipulation in a program written in assembly language or C. We will use C to illustrate e.g. how a single bit can be cleared or set in a device register. The following types and names ease access to the bytes and words of the device registers:
typedef unsigned char byte; typedef unsigned short int word; /* A/D converter */ /* A/D Control/Status Register */ #define ADCSR *((volatile byte *) 0xffe8) #define ADF ( 1 << 7 ) /* A/D Flag , bit 7 */ #define ADST ( 1 << 5 ) /* A/D Start, bit 5 */ /* A/D Data Register A */ #define ADDRA *((volatile word *) 0xffe0)
The typecast in the first define turns the address constant 0xffe8 into a pointer to a byte. The *( ...) takes the content of the byte pointed to by the address. The volatile qualifier is needed to prevent an optimizing compiler to read the content of the byte or word only once e.g. outside a loop that waits for the value of the device register to change. These types and definitions can be used to e.g. start a conversion of A/D channel 0, wait for end of conversion and read the resulting 10 bits from the A/D data register A:
ADCSR = 0; ADCSR |= ADST; /* Start conversion */ while ( ! ( ADCSR & ADF ) ); /* Wait for end of conversion */ ADCSR &= ~ADF; /* Read register and clear ADF */ Port3 = (( ADDRA >> 6 ) & 0x03ff); /* Shift to an integer in [0..1023]*/
Bitwise operations in C are described in Kernighan & Ritchie, p. 48, 49 and p. 149, 150.

RCX Interrupts and Interrupt Handlers

The H8/3292 vector table starts at address 0x0000 and the last vector in the table is at address 0x0048. The entries of this table are fixed by the on-chip ROM. Each entry contains an address that points to an interrupt dispatcher in on-chip ROM, one dispatcher for each interrupt vector. For each interrupt dispatcher there is an entry in a table in on-chip RAM that is used as an address of a routine to dispatch to when an H8/3292 interrupt has occurred. This table in on-chip RAM can be used to install an interrupt handler for each of the interrupts handled by the H8/3292 interrupt hardware. Hence, the H8/3292 hardware interrupt mechanism has been turned into an RCX interrupt mechanism by the content of the on-chip ROM with the RCX interrupt vectors in on-chip RAM. The implementation of this mechanism can be described as follows:
H8/3292 interrupt vector address: address of interrupt dispatcher interrupt dispatcher: push r6 mov @RCX interrupt vector address, r6 jsr @r6 pop r6 rte RCX interrupt vector address: address of RCX interrupt handler RCX interrupt handler: save registers needed for interrupt handling handle interrupt restore registers saved return to interrupt dispatcher (rts)
The stack content on entry to the interrupt handler is determined by the H8/3292 interrupt mechanism and the interrupt dispatcher. The content is:
address content sp return to dispatcher sp - 2 r6 of interrupted program sp - 4 cc of interrupted program sp - 6 pc of interrupted program
Furthermore, interrupts are disabled on entry to the RCX interrupt handler until the instruction rte is executed by the dispatcher unless the interrupt bit of cc is explicitely cleared by the RCX interrupt handler. Hence, when the I-bit is not cleared, the actions of the RCX interrupt handler is an indivisible, non-interruptable, atomic operation (MOS, chapter 2), since non-maskable interrupts are not used on the RCX.

RCX interrupt handlers can be programmed and installed in assembly language and C. We will use C to illustrate how to install an RCX interrupt handler for the Run button. The following definitions ease installation of an RCX interrupt handler:

#define Int_Handler(RCX_Vector_Addr) ( *(void (**)(void))(RCX_Vector_Addr) ) #define IRQ0_Addr 0xfd94 /* RCX IRQ0 Interrupt Vector Address */ #define Run_Button_Interrupt_Handler Int_Handler(IRQ0_Addr)
The typecast turns the RCX_Vector_Addr into a pointer to a routine that takes no parameters and returns no result. The last define can be used to install e.g. the C routine RunInt as the interrupt handler for the Run button:
Run_Button_Interrupt_Handler = RunInt;
where the routine RunInt is defined e.g. as follows:
int16 Count; void RunInt (void) { asm("push r0 push r1 push r2 push r3 push r4 push r5 "); /* Increment global counter when Run is pressed */ Count = Count + 1; asm("pop r5 pop r4 pop r3 pop r2 pop r1 pop r0 "); }
To enable interrupts from the Run button and define the event that triggers the interrupt, we have to access the IRQ device registers:
/* IRQ Sense Control Register and IRQ Enable Register */ #define ISCRaddr 0xffc6 #define IERaddr 0xffc7 #define ISCR *( (byte *) ISCRaddr ) #define IER *( (byte *) IERaddr )
To trigger an interrupt by the falling edge of the state of the Run button (when the Run button is pressed) and to enable Run button interrupts, the device registers should be initialized as follows:
ISCR = 1; IER = 1;

Buttons

On the upper side of the RCX there are four buttons: View, On-Off, Prgm and Run.

Figure X The four buttons View, On-Off
Prgm and Run. The leJOS Tutorial, (1.2.2006),
Controlling the Hardware: Buttons.

The four buttons are connected to four input lines of the H8/3292 input/output ports. Two of the buttons can also initiate external interrupts. The details are:

Button Input portAddressBitpositionInterrupt
Run port 4 0xffb7bit 2IRQ 0
OnOffport 4 0xffb7bit 1IRQ 1
Viewport 70xffbebit 6no interrupt
Prgm port 70xffbebit 7no interrupt

The bit value obtained on a read is 0 when the button is pressed and 1 when the button is released.

The bit value for each button can be accessed directly from the device registers by bitmanipulation. We will use C to illustrate how button states can be used as input to a C program. We can define the following names to ease access to e.g. the state of the Run button:

#define port4_addr 0xffb7 #define port4 *((volatile byte *) port4_addr) #define Run ! ( port4 & ( 1 << 2 ) )
The last define makes it possible to use Run as an expression that has the value 1 when the Run button is pressed and 0 when it is released. The value of Run can be used e.g. to stop a loop:
while ( ! Run ) { ... }

RCX Input Ports

On the upper side of the RCX it is possible to connect sensors to the RCX input ports labelled 1, 2 and 3.

Figure X The three RCX input ports.
The leJOS Tutorial, (1.2.2006),
Controlling the Hardware: Sensors.

The sensors are of two types: passive and active sensors. The passive sensors are the touch and temperature sensors. The active sensors are the light and rotation sensors. From a programming point of view the two types are treated differently.

Figure X The five standard LEGO
sensors. The leJOS Tutorial, (1.2.2006),
Controlling the Hardware: Sensors.

The usage of sensors connected to the input ports requires an understanding of the electronics of the sensors and the input ports. A detailed description of this can be found in Internals of Input Ports and Sensors. Furthermore, it also require knowledge of RCX programming to be able to get values from the sensors connected to the input ports. This is described in the following.

To obtain an input value from a passive sensor we use the A/D converter. For an active sensor like the light sensor we also have to power up an illuminating light emmitting diode (LED) so the red light on the outside of the light sensor is turned on. This is accomplished through one of three output lines of I/O port 6. The rotation sensor also contains LED's that have to be powered up. These LED's are build into the blue LEGO brick and are not visible from the outside.

The three RCX input ports are connected to the channels of the A/D converter and the output lines of I/O port 6 as follows:

Input Port A/D Channel Output Line
1Analog input pin 2 (AN2)Port 6, bit 2
2Analog input pin 1 (AN1)Port 6, bit 1
3Analog input pin 0 (AN0)Port 6, bit 0

The sensor input value is obtained for both types of sensors through an A/D conversion. The device registers of the A/D converter is used to initiate a conversion, to monitor the end of conversion, and to access the resulting converted 10 bit sensor input value. The A/D control/status register is used to start conversion and to poll for the end of conversion. The end of conversion can also be signalled with an A/D end interrupt. The A/D data registers store results of conversions. The data register contains the 10 bit converted value in the 10 most significant bits of a 16 bit word. The data registers are connected to the A/D channels and the converted values can be read at the following addresses:

Input Port A/D Channel Register AbbreviationAddress
1AN2A/D data register AADDRC0xffe4
2AN1A/D data register BADDRB0xffe2
3AN0A/D data register CADDRA0xffe0

The A/D control/status register (ADCSR) is an 8 bit device register at address 0xffe8. The bits are used as follows:

BitNameAbbreviationMeaning
7A/D End FlagADFshould be cleared by program on end of conversion, set by converter to signal end of conversion
6A/D End Interrupt EnableADIE0: interrupt disabled; 1: interrupt enabled
5A/D StartADST0: conversion stopped; 1: start conversion
4Scan ModeSCAN0: single mode; 1: scan mode
3Clock SelectCKS0: slow conversion; 1: fast conversion
2 to 0Channel SelectCH2 to CH0Selects channel(s)

The channel select bits are used to select one of the three input ports for conversion (single mode) or select more than one (scan mode), e.g.:

Input Port CH2 to CH0Mode
1 010single
2001single
3000single
1,2,3010scan

An example of simple A/D convertion of a single pin value is shown in the module AD.h. The module InputPorts.h contains functions to input both passive and active sensor values. In RCX Programming, Lesson 1 these moduls are used to interprete the light sensor input as different colors.

Infrared Transmitter/Receiver

The RCX uses IR (InfraRed) light to communicate with a host computer or another RCX.

Figure X The infrared transmitter
and receiver. The leJOS Tutorial, (15.2.2004),
Controlling the Hardware: The IR Interface.

The IR Transmitter/Receiver is based on the on-chip Serial Communication Interface ( SCI, see Section 11 of Hitachi H8/3292 ). The SCI acts as a device controller for the serial infrared communication. Infrared light turned on and off with a frequency of 38.5 kHz is used as a carrier for the serial stream of bits: bit value 0 is represented as a time interval with the infrared light carrier turned on, bit value 1 as a time interval with no infrared light. The frequency of the carrier wave, 38.5 kHz, is provided by the timer output of Timer 1. The infrared transmission can be performed in two modes: Short and long range mode. Pin 0 of Port 4 determines the transmission mode, 1 for short and 0 for long range. The infrared light emitted is not only received by other IR receivers but also by the receiver on the transmitting RCX. This means that simultaneous transmission by two or more, i.e. collision, can be detected by inspection of the received bit stream. The duration of the time interval for a single bit is related to the baud rate selected on the SCI. With a baud rate of 2400 bit/sec the time interval is 417 usec = 1 bit/2400 bit/sec. The communication format used in the serial communication is selected through the device registers of the SCI. A declaration in C of these registers can be seen in the module SCI.h.

The IR transmitter/receiver can be used both program-driven and interrupt-driven as shown by the set of C-routines included in the module IR.h. In RCX Programming, Lesson 3 there is an example of RCX programs that communicate using this module

Liquid Crystal Display (LCD)

On the upper side of the RCX there is an LCD.

Figure X The LCD shows a LEGO man in walking
position, the number one to the right of the LEGO man
and a motor direction indication above the letter A.
The leJOS Tutorial, (1.2.2006),
Controlling the Hardware: LCD.

The LCD screen contains 43 segments. A segment is a figure or a symbol e.g. a dot, an arrow or the legs of a small LEGO man. Each segment can be controlled individually by turning it on or off. This is accomplished through an LCD controller. Communication with the LCD controller takes place on a serial line consisting of two wires. On the RCX these two wires are connected to I/O port 6, bit 5 and bit 6. Reading and writing these two bits is used to control the LCD from the RCX. The on-chip RCX executive uses a protocol on the serial line to implement a number of high-level operations on the LCD: An area of memory contains an LCD buffer with one bit for each segment; the RCX executive routines write to this buffer, and explicit calls to an RCX executive routine, refresh, (see LCD Routines), uses the protocol to update the screen so segments are shown or hidden corresponding to the actual bit values in the LCD buffer. Detailed knowledge of the protocol and the LCD buffer can be obtained from RCX Internals.

Speaker

The build in speaker can be controlled via the I/O port 6, bit 4. Before the speaker can be used, the Data Direction Register of I/O port 6 should be set to output e.g. as follows:
#define P6DDR *((volatile byte *) 0xffb9) #define P6DDR_ROM *((volatile byte *) 0xfd85) #define P6DR *((volatile byte *) 0xffbb) #define bit4 (1 << 4) #define SpeakerHigh P6DR |= bit4 #define SpeakerLow P6DR &= ~bit4 /* Initialize bit4 of port 6 as output. */ P6DDR_ROM |= bit4; P6DDR = P6DDR_ROM;
To make sounds bit 4 of the output port should be toggled with appropriate time intervals between toggling. E.g. a tone of frequency 500 Hz is produced by repeating:
SpeakerHigh; Wait one msec; SpeakerLow; Wait one msec;
The toggling of bit 4 can also be controlled by timer output of timer 0.

RCX Output Ports

The RCX has three output ports labelled A, B, and C. A variety of actuators can be connected to the output ports. The actuators available from LEGO are motors, lamps, and a sound elements. Each output port can drive one or more actuators. If e.g. a motor and a lamp is connected to a single port, the lamp will indicate when the motor is active.

Figure X The three RCX Output Ports A, B and C. From
The leJOS Tutorial, (10.2.2004), Controlling the Hardware: Motors.

The output ports are driven by the current from the 9 V battery power supply. The state of the current flow through the actuator connected to an output port is controlled by the content of the RCX output ports device register at address 0xf000. Each port is controlled by two bits in the 8 bit device register.

Output Port A B C
Bits bit 7 and 6 bit 3 and 2 bit 1 and 0

These output port bitfields can be accessed at the device register address. E.g. to set the state of output port A to 2 can be done in C as follows:

#define OutputPorts *(( volatile byte *) 0xf000 ): #define Amask 0xc0 byte temp; temp = OutputPorts; temp &= ~Amask; temp |= (2 << 6); OutputPorts = temp;

The four possible values of the two bits correspond to four different ways to control the state of the current flow through the actuator. The values 01 and 10 allows the current to flow in either of the two directions. This allows bidirectional control of the current flow. The value 00 disconnect the actuator from the power supply. The value 11 connects the two terminals of the actuator to the same polarity of the power supply. Internals of Output Ports and Actuators contains more details on the connection between the power supply and the output ports.

To make it easier to program the control of the actuators connected to the output ports a simple C-routine can be programmed for each port that sets the current state of the port. E.g. for port A it might look as follows:

#define Float 0 #define OnPos 1 #define OnNeg 2 #define Brake 3 void PortA( byte state ) { byte temp; temp = OutputPorts; temp &= ~Amask; temp |= (state << 6); OutputPorts = temp; }
A call to the routine Port A sets the state of the corresponding output port to one of the four current states (called Float, OnPos, OnNeg, and Brake) depending on the actual value of the parameter state. Such a set of C-routines are included in the module OutputPorts.h.

The effect the four states has on an actuator connected to the output port depends on the actuator:

Output Bits MotorLampFlashlightSound Element
00 float, i.e. free running mode no lightno lightno sound
01turn in one direction lightlight/flashing lightone alarmsound
10turn in the other directionlightlight/flashing lightthe other alarmsound
11 brakeno lightno lightno sound

Lets consider a car driven by to motors connected to port A and C and lets call the four current states for Float, OnPos, OnNeg, and Brake as before. State OnPos and OnNeg will make the wheel on the motor turn clockwise or counter-clockwise depending on how the wires are attached to the output ports and the motors. A change from a powered state OnPos or OnNeg to a non-powered state Float or Brake have very different effects on the locomotion of a car. A change to Brake will force the car to stop immediately. A change to Float allows the motors to spin freely and the car will be coasting.

Figure X Two motors connected to port A and C. From The leJOS Tutorial, (10.2.2004),
Controlling the Hardware:Motors.

The C-routines PortA, PortB and PortC allows us to use program-driven control of the output ports. E.g. to make a lamp on port A blink we could repeat the following:

PortA(OnPos); Wait one msec; PortA(Float); Wait one msec;
The C-routine can also be used to write C-routines for control of car locomotions. E.g.:
/* Defines the power states that make the wheels drive the car forward and backward. Connections between motors and ports should be change to make these states correspond to the actual car locomotions. */ #define Aback OnNeg #define Aforward OnPos #define Cback OnNeg #define Cforward OnPos void CarCoast ( void ) { PortA(Float); PortC(Float); } void CarBrake ( void ) { PortA(Brake); PortC(Brake); } void CarGoForward ( void ) { PortA(Aforward); PortC(Cforward); } void CarGoBackward ( void ) { PortA(Aback); PortC(Cback); } void CarSpinClockwise ( void ) { PortA(Aforward); PortC(Cback); } void CarSpinCounterClockwise ( void ) { PortA(Aback); PortC(Cforward); }

If the state changes on an output port happen fast enough, e.g. OnPos, Float, OnPos, Float, ... with a 1 msec duration of each state, the effect on a lamp is that it will not shine as bright as when powered all the time. This mode of actuator control is called puls width modulation (PWM). Each power-on state is called a puls and the duration of the puls is called the width of the pulse. The energy transfered to an actuator can be controlled by varying the puls width and the pattern of pulses. To implement PWM output port control, we can use the T0 timer of the H8/3292 to provide timer interrupts with a period of e.g 1 msec. These interrupts can be used to call a C-routine that provide a regular patterns of state changes of an output port. The module MotorControl.h uses PWM control to drive the output ports A and C. Each output port can be driven at 16 different energy levels provided by 16 different puls patterns. In RCX Programming, Lesson 2 there is an example of a C program that drives a car using routines in this module.

The RCX Executive

When the RCX has been powered up or reset a ROM based executive starts running and controls the RCX. Through the infrared transmitter/receiver another computer can communicate with the executive. The executive offers a simple protocol to perform a program download from another computer to the RCX. When a program has been downloaded, it can be started by the executive. Once running, the executive acts as a run-time environment for the program, offering services like I/O routines for access to the RCX input/output devices.

In Madvick and Donovan, Operating Systems, 1974, an executive system is described as follows:"As computers became more complex, especially with regard to I/O device management, executive systems were developed that permanently resided in memory and provided Input/Output Control Services (IOCS) for user jobs". This fits with the function of the ROM based system on the RCX. This is the reason for calling it an executive. Others call a similar system an On-board Monitor.

Communication with the RCX Executive

The executive communicates with another computer by means of a simple request/reply protocol: The computer sends a request; the executive does what is requested and sends a reply. The reply may contain data e.g. version numbers, but a reply may also be an acknowledgement meaning that the request has been serviced or that things are ok.

The Request/Reply Protocol

The following requests can be sent to the executive:
Alive: Checks whether or not the executive is running and that there is a good connection to the RCX.

GetVersions: Get the versions of the executive and the application program running on top of the executive. In the LEGO MindStorms applications, this is normally a bytecode interpreter, refered to as the firmware, see Software Developers Kit, Write RCX programs in Visual Basic, on LEGO MindStorms.

EnterDownloadMode: If a program is running on top of the executive the program is stopped. Now the executive is ready for a program download.

BeginDownload: Prepare the executive for a program download.

DownloadBlock: Download a block of bytes to the RCX memory.

RunProgram: Start execution of the program downloaded. A downloaded program can only be started if it contains the text "Do you byte, when I knock?", otherwise the executive refuse to run the program downloaded.
Each request/reply is sent as a packet of bytes. A packet contains the actual request/reply with a header added to the front and a trailer added to the end:
packet = header request/reply trailer
where
header = 0x55 0xff request/reply = bytesequence trailer = checksum
The checksum is obtained as the least significant byte of the sum of the bytes in the request/reply.

A request is thus represented as a sequence of bytes. The first byte is the request code, the following bytes contain the request data. A reply has a similar structure with the first byte being the reply code, the following bytes being the reply data. The reply code is the bit complemented value of the request code sent. For each request there are two request codes, the difference between the two codes is the value of bit 4 in the byte. This is a sequence control bit: The executive only executes the first of a sequence of requests with identical request codes, the second and beyond are not executed. The reply sent to the second request and beyond is the same as that sent to the first. To make sure the same request is executed twice in a row by the executive, use alternate sequence control bit values. This is needed in a sequence of DownloadBlock requests.

Now follows a detailed description of each request/reply. For each request/reply the two request codes/reply codes are given (in hex) together with the meaning and representation of the request data/reply data.

Request Request codes Request data Reply codes Reply data
Alive10/18none ef/e7none
GetVersions15/1dKey ea/e2ROMVersion, ProgramVersion
EnterDownloadMode65/6dKey 9a/92none
BeginDownload75/7dProgramEntryPoint, ProgramChecksum, Zero 8a/82Result
DownloadBlock45/4dBlockSequenceNumber, BlockLength, DataBlock, BlockChecksum ba/b2Result
RunPrograma5/adRunKey 5a/52Text

Key: Five bytes with the decimal values 1, 3, 5, 7, 11. The Key prevents a running program from being accidentally stopped.

ROMVersion: A four byte BCD represented version number of the ROM resident executive.

ProgramVersion: A four byte BCD represented version number of the application program. When no program is running, the four bytes are 0.

ProgramEntryPoint: A two byte little endian represented 16 bit address. This is the address where the executive starts the program downloaded.

ProgramChecksum: A two byte little endian represented 16 bit unsigned integer. This is the least significant 16 bits of the sum of all the program bytes downloaded in a sequence of DownloadBlock requests.

Zero: A fill in byte with the value 0.

BlockSequenceNumber: A two byte block sequence number. Starts with 1 in the first DownloadBlock request and increases by one with each successive request. A value of 0 is used for the BlockSequenceNumber in the last DownloadBlock request to mark the end of a series of DownloadBlock requests.

BlockLength: The number of bytes in the following DataBlock. Represented as a two byte little endian 16 bit unsigned integer.

DataBlock: A sequence of bytes of length BlockLength.

BlockChecksum: A byte computed as the least significant byte of the sum of all bytes in the DataBlock.

RunKey: The text "LEGO®" represented as the five ASCII values 76, 69, 71, 79, 174 (decimal).

Text: The text "Just a bit of the block!" represented as a sequence of 26 ASCII values.

Result: A byte value. A value of 0 means that the request was successfully processed by the executive. A non-zero result means that an error has occurred. In DownloadBlock the result values has the following meaning:
1 : not enough memory
2 : bad block format
3 : checksum error in this block
4 : program checksum error
6 : not in download mode

The Byte Protocol

Each request/reply is sent as a packet of bytes on a serial communication line between the computer and the RCX. This serial line consists of two infrared transmitter/receiver devices, one connected to the computer via an RS232 communication port, the other build into the RCX. The baud rate is 2400; this is the number of bits sent per second. To mark the start and end of each byte, a byte is sent preceeded by a start bit and followed by a stop bit. Also, a single parity bit is appended to the byte. The parity bit is chosen so the number of bits in the 9 bit value sent is odd. Hence, each byte is sent as 11 bits. Furthermore, each byte in a packet except the first, i.e. 0x55, is sent as two bytes, the byte itself and its bit complement. The result is a packet with an equal number of zero bits and one bits (the header byte 0x55 also has an equal number of zero and one bits). This allows an infrared receiver to compensate for a constant signal bias (caused by ambient light) simply by subtracting the average signal value. Hence, each 8 bit value in a packet, except the first, is sent as 22 bits in all. With a baud rate of 2400 this takes 22 bit /2400 bit/sec = 9 msec for each byte.

The Bit Protocol

Each bit transmitted between the two infrared transmitter/receiver devices is represented with bit value 0 as a 417 usec period of infrared light pulsed with a frequency of 38kHz, and bit value 1 as a 417 usec period with no infrared light. The duration of the period for a single bit is related to the baud rate as follows 1 bit/2400 bit/sec = 417 usec.

The RS232 Connected Infrared Transmitter/Receiver

The infrared transmitter/receiver connected to the RS232 serial port, echoes the bytes sent by the computer to the serial port. This means that the bytes received after sending a packet, is a copy of the packet in front of the reply packet received from the RCX executive.

A Program to Communicate with the RCX Executive

A simple program RCX_Request_Reply.c can be used to investigate the communication between a UNIX computer and the RCX executive. The infrared transmitter/receiver should be connected to a serial port given by a name defined in the program by the constant text named DEFAULT_RCX_IR. Change this if needed or use the environment variable RCX_IR to override the default setting.

The program inputs a request as a sequence of raw hexadecimal represented bytes. This is sent to the RCX executive. Then the program waits for a reply. After a while either a correct reply has been received or a failure has occurred. The program outputs either a reply as a sequence of raw hexadecimal represented bytes or the course of failure.

To check the liveliness of the connection and the RCX, we may use the program as follows:

RCX_Request_Reply 10 0000: ef
The Alive request is sent as the raw request code 10. The reply is ef, signalling that things are ok.

The versions of the programs running on the RCX are obtained by:

RCX_Request_Reply 15 1 3 5 7 b 0000: ea 00 03 00 01 00 00 00 00
No application program is running and the version of the executive is 3.1.

Now we want to download and run the following simple assembly language program - notice how the mandatory text is included by means of a .string directive in the data section:

.section .text .align 1 .global __start __start: mov.w @0,r0 jsr @r0 .section .data .string "Do you byte, when I knock?" .end
First we have to assemble it into an absolute program e.g. as hexadecimal bytes:
mov.w @0,r0 6b 00 00 00 jsr @r0 5d 00 Do 44 6f 20 you 79 6f 75 20 byte, 62 79 74 65 2c 20 when 77 68 65 6e 20 I 49 20 knock? 6b 6e 6f 63 6b 3f
Then we have to calculate the ProgramChecksum and the BlockChecksum.

To download the resulting program to the memory of the RCX we proceed as follows:
EnterDownloadMode:

RCX_Request_Reply 65 1 3 5 7 b 0000: 9a
BeginDownload, ProgramEntryPoint = 8000, ProgramChecksum = 09a8, Zero = 0:
RCX_Request_Reply 75 00 80 a8 09 00 0000: 8a 00
DownloadBlock, BlockSequenceNumber = 0, BlockLength = 0022, DataBlock = 6b 00 ... 3f 00 00, BlockChecksum = a8:
RCX_Request_Reply 4d 00 00 22 00 6b 00 .... 3f 00 00 a8 0000: b2 00
RunProgram, RunKey = 4c 45 47 4f ae (hex):
RCX_Request_Reply a5 4c 45 47 4f ae 0000: 5a 4a 75 73 74 20 61 20 62 69 74 20 6f 66 66 20 0010: 74 68 65 20 62 6c 6f 63 6b 21
The reply contains the hexadecimal represented ASCII values for the text "Just a bit off the block!". So things are ok and the program is running. Not for long, however. The two instructions of the program make an indirect jump through the reset vector at address 0. This will give back the control to the executive.

The RCX Executive as a Run-time Environment

A program running on the RCX can use services provided by the executive, e.g. routines for high level access to the LCD screen. In this section we will give some useful executive services and describe how to interface to these services from assembly and C-programs. A much more complete list of executive services can be obtained from RCX Internals.

As a simple example we will start with a routine for multiplication of 16-bit signed integers. It is available in the executive at the address 0x0130; this means that the multiplication routine can be called in assembly as a subroutine:

jsr @0x0130
The two operands are passed to the subroutine in registers r5 and r6, the result is returned in r6. This means that multiplication of e.g. 51 and 72 can be carried out in assembly as:
mov.w #51, r5 mov.w #72, r6 jsr @0x0130
The value of r6 is 3672 = 51*72 on return from the subroutine.

In a C-program we can wrap this assembly call into a C function as follows:

int16 imul( int16 a, int16 b) { int res; asm("mov.w %1,r5 mov.w %2,r6 jsr 0x0130 ; call imul mov.w r6,%0 ": "=r" (res) : "r" (a), "r" (b) : "r0", "r1", "r5", "r6" ); return res; }
This C function can be activated as usual in a C-program:
int16 p; ... p = imul(51,72);
C wrappers, like the one for the multiplication routine, can be programmed for the executive routines to ease access to the executive services.

A number of C wrappers can be collected and placed together with data types, constants, and global variables in an interface definition or header file , e.g. RCX_RTE.h. This simple interface also contains the main data types for the H8/300, like byte and word, the mandatory text "Do you byte, when I knock?" and a routine to reset the RCX. The interface can be included in the text of a C-program:

#include "RCX_RTE.h"
This simple interface to the RCX executive is an example of a run-time environment that can be based on the RCX executive. In the following the services provided for access to the LCD in this interface will be described in detail.

LCD Routines

In the executive there are routines that makes it possible to ignore the low-level details of LCD control through the two pins of H8/3292 I/O port 6. They also hide the details of how each bit in the LCD buffer maps to the segments on the screen. There are two executive routines to show or hide an icon on the screen. An icon is one or more segments. Furthermore, there is a routine for writing numbers on the screen. All routines operate on the contents of the LCD buffer in the memory. The changes to the LCD buffer have no effect on the screen unless an explicit call to an executive routine makes the changes to the LCD buffer visible on the screen. In the decription in the table below we will assume that the changes to the LCD buffer will appear shortly after on the screen e.g. by an explicit call to the routine that updates the screen.

LCD routineDescriptioncall address parameter names and type
refreshupdates screen with LCD buffer contents 0x27c8no parameters
clearclear screen0x27acno parameters
show_iconmake icon visible0x1b62icon (16-bit)
hide_iconhide icon 0x1e4aicon (16-bit)
show_numberan integer value is shown according to the format and scale parameters0x1ff2format (16-bit), value (16-bit), scalecode (16-bit)

The first parameter to the routines is passed in register r6, the remaining parameters are passed on the stack: the third parameter is the first to be pushed onto the stack, then the second parameter is pushed onto the stack. The parameters have the following meaning:

icon, a 16-bit code for one of the icons that the executive can handle, e.g. a LEGO man standing or walking. The icon's available are:

16-bit code Describtion
0x3006standing figure
0x3007walking figure
0x3008sensor 0 view selected
0x3009sensor 0 active
0x300asensor 1 view selected
0x300bsensor 1 active
0x300csensor 2 view selected
0x300dsensor 2 active
0x300emotor 0 view selected
0x300fmotor 0 backward arrow
0x3010motor 0 forward arrow
0x3011 motor 1 view selected
0x3012motor 1 backward arrow
0x3013motor 1 forward arrow
0x3014motor 2 view selected
0x3015motor 2 backward arrow
0x3016motor 2 forward arrow
0x3018datalog indicator
0x3019download in progress
0x301aupload in progress
0x301bbattery low
0x301cshort range indicator
0x301dlong range indicator
0x3020all segments

Repeated calls with the codes 0x3018, 0x3019, and 0x301a make a simple animation on the screen. This can be used to indicate a time consuming process in progress.

format, the show_number routine operates on six positions on the screen:
sign digit3 digit2 digit1 digit0 digit
The sign position can show a minus (-) or be empty. The other five positions can show the decimal digits 0,1,...9 , a minus (-), or be empty. Between digit3 and digit2, or between digit2 and digit1, or between digit1 and digit0, a decimal point can be shown as a dot. The parameter format controls how the 16-bit value passed as the second parameter is interpreted and made visible on the screen.

Format Meaning
0x3001 the 16-bit value is interpreted as a signed integer and shown as up to four decimal digits in positions 3, 2, 1, 0 with no leading zeros. If the value is less than -9999, -9999 is shown, if the value is greater than 9999, 9999 is shown
0x3017if the 16-bit value is in the range 0..9 it is shown in the digit position. Otherwise nothing is shown.
0x301fthe 16-bit value is interpreted as an unsigned integer and shown in positions 3, 2, 1, 0 with leading zeros. If the value is greater than 9999, 9999 is shown.

scalecode, determines the position of a possible decimal point. Applies only to format 0x3001 and 0x301f.

Scalecode Scalefactor
0x3002 1
0x30030.1
0x30040.01
0x3005 0.001

These executive LCD routines can be wrapped into C routines. Examples of such wrapped C routines have been included in RCX_RTE.h with names as in the table of the LCD executive routines prefixed with lcd_, lcd_refresh, lcd_clear,.... (see RCX_RTE.h description). Each routine ends with an explicit call to refresh to update the screen immediately after the changes have been made to the LCD buffer. To ease the use even further, also specialized calls to show_number have been included in RCX_RTE.h, such as lcd_show_int16 and lcd_show_digit. This shows how specialized routines can be based on the general routines provided by the executive.

Compilation of Programs for the RCX

We have already seen how a simple assembly language program can be translated manually into hexadecimal bytes representing the equivalent H8/300 machine code program. We have also seen how these bytes can be downloaded to the RCX through a series of explicit requests to the RCX executive, and also how the downloaded program can be started. However, this manual process is very tedious and error prone. In this and the following section we describe tools to ease the process. In this section we describe a cross-assembler and a cross-compiler that translates assembly language programs and C-programs into native H8/300 programs represented as a series of S-records. In the next section a program, RCX_Download, is described that performs a transformation of a series of S-records to a sequence of bytes and then sends requests to the RCX executive to download and start the transformed program.

How to Install Cross-Assembler and Cross-Compiler

If cross-assembler and cross-compiler is not installed on your UNIX machine an installation guide will show you how to obtain these tools.

Translation of Assembly Language Programs

The assembly program of the previous section e.g. contained in the file asm_reset.s can be translated into a series of S-records by the following UNIX command:
make asm_reset.srec
This command performs the translation of the assembly program into an S-record formatted RCX program in two steps: the first step translates the assembly program into an object module asm_reset.o, the second step transforms the object module into a sequence of S-records in asm_reset.srec. The two steps performed by the command are contained in the following Makefile:
# Makefile for H8/300 cross translation of assembler programs. # Path to assembler (as) and linker (ld). BINDIR = /users/kursus/dArk/solaris/h8300-hitachi-hms/bin/ AS = $(BINDIR)as LD = $(BINDIR)ld # Options for linker. LFLAGS = -Tasm_rcx.lds # Entries. # $< and $@ expands to the actual file name that matches the # right hand side and the left hand side of : (colon). %.o: %.s $(AS) $< -o $@ %.srec: %.o $(LD) $(LFLAGS) -o $@ $<
Here, as is a cross-assembler, not the native assembler on the UNIX host machine ; ld is a cross-linker. The linker works under the explicit control of the link script contained in the file asm_rcx.lds given after the option T. The linker script in asm_rcx.lds defines the transformation from the object file into the S-records. This file looks as follows:
/* * asm_rcx.lds * * GNU ld script for mapping an assembled object module into * an S-record represented absolute H8/300 program. The sections of * the object module is mapped into the memory of the RCX starting at * the load address 0x8000. The length of the program should not exceed * 0x6fff because the address 0xf000 is used as device register. * The program entry point is __start. * */ OUTPUT_FORMAT(srec) OUTPUT_ARCH(h8300) ENTRY(__start) MEMORY { mem : ORIGIN = 0x8000, LENGTH = 0x6fff } SECTIONS { .text : { *(.text) } > mem .data : { *(.data) } > mem }

The translation and transformation performed by make asm_reset.srec results in the following sequence of five S-records contained in the file asm_reset.srec:

S011000061736D5F72657365742E7372656350 S10980006B0000005D00AE S1188006446F20796F7520627974652C207768656E2049206B6B S10A801B6E6F636B3F000070 S90380007C
The first S0 record contains the name of the file as ASCII characters (r=72, e=65, ...). The terminating S9 record contains the entry point of the H8/300 program, 0x8000. The three remaining S1 records contains the native code, each byte is represented as a two digit hexadecimal number. The load address of the first S1 record is 0x8000, that is where the first byte of the program goes.

Compilation of C-Programs

A C-program reset.c, similar to the assembly program of the previous section, can be written as follows:
#include "RCX_RTE.h" void _start(void) { RCX_Reset(); }
In this program the reset is accomplished through a call to the C routine RCX_Reset in RCX_RTE.h (see RCX_RTE.h description). This program can be compiled into an object module and then transformed into a sequence of S-records in a way similar to the cross-assembly process described for assembly language programs. This time the UNIX command is:
make reset.srec
The result is an S-record formatted native program reset.srec for the RCX. The following Makefile was used:
# Makefile for H8/300 cross compilation of C and assembler programs. # Path to C compiler (gcc), assembler (as) and linker (ld). INSTDIR = /users/legolab/RCX BINDIR = $(INSTDIR)/`uname -s`/h8300-hitachi-hms/bin/ CC = $(BINDIR)gcc AS = $(BINDIR)as LD = $(BINDIR)ld RCXDOWNLOAD = $(INSTDIR)/`uname -s`/bin/RCX_Download # Options for C compiler and linker. CFLAGS = -O2 -Wall -I$(INSTDIR)/include LFLAGS = -T$(INSTDIR)/Manual.dir/rcx.lds # Entries. # $< and $@ expands to the actual file name that matches the # right hand side and the left hand side of : (colon). %.o: %.c $(CC) $(CFLAGS) -c $< %.o: %.s $(AS) $< -o $@ %.s: %.c $(CC) -S $(CFLAGS) $< %.srec: %.o $(LD) $(LFLAGS) -o $@ $< %.send: %.srec $(RCXDOWNLOAD) $<
This Makefile can also be used to compile a C-program into an object modul with the command:
make reset.o
To compile a C-program into an assembly language program use the Makefile as follows:
make reset.s
This is useful when there is a need to inspect the symbolic H8/300 code generated by the cross-compiler.

The link script rcx.lds specified in the T option of the linker is:

/* * rcx.lds * * GNU ld script for mapping a C compiled object module into * an S-record represented absolute H8/300 program. The sections of * the object module is mapped into the memory of the RCX starting at * the load address 0x8000. The length of the program should not exceed * 0x6fff because the address 0xf000 is used as device register. * The program entry point is __start. * */ OUTPUT_FORMAT(srec) OUTPUT_ARCH(h8300) ENTRY(__start) MEMORY { mem : ORIGIN = 0x8000, LENGTH = 0x6fff } SECTIONS { .text : { *(.text) *(.rodata) } > mem .data : { *(.data) } > mem .bss : { __bss_start = . ; *(.bss) *(COMMON) __end = . ; } > mem /DISCARD/ : { *(.vectors) } }
This link script controls the mapping from the object modul into an S-record formatted native program for the RCX.

Download of Programs to the RCX

To download a program to the RCX, first an S-record version of the program should be produced e.g. by the cross-assembly or cross-compilation described in the previous section. Then, turn on the RCX and download the S-record program as follows:
RCX_Download <filename of S-record program>
The program RCX_Download.c goes through all the steps needed to download and start the program in the file given by the filename. The infrared transmitter/receiver should be connected to a serial port given by a name defined in the program by the constant text named DEFAULT_RCX_IR. Change this if needed or use the environment variable RCX_IR to override the default setting.

References

Brian W. Kernighan, Dennis H. Ritchie, The C Programming Language, Second edition,Prentice Hall, 1988.

[MOS]
Andrew S. Tanenbaum:
Modern Operating Systems, Prentice Hall, 1992.

A lot of the information in this manual has been collected from RCX Internals, LEGO MindStorms Internals, and the legOS description.