Languages, Assemble!

Look what I found in my closet:

Motorola 68HC11 on an eval board made by Axiom Manufacturing

This is my old Motorola 68HC11 microcontroller board. Here’s a close up photo of the microcontroller itself:

Motorola 68HC11 Microcontroller IC

For those who aren’t familiar with these terms, a microcontroller is basically a computer on a chip. They are often very tiny and low powered, and are ubiquitous whether you realize it or not.

This is what I learned assembly language and machine language on in 2001. Machine language is basically the language of the CPU. Everything that a computer runs is in machine language. All other programming languages are compiled or interpreted down to machine code. Assembly language is a bare bones one-to-one mapping from machine codes to symbols that are barely human-readable.

I had encountered assembly language before 2001 in 3D game code, but I didn’t totally understand it, especially registers.

An Aside on 3D Game Programming

Wolfenstein 3D

The reason I was reading 3D game code: After playing Wolfenstein 3D in the 1990s, I wanted to make similar games. So I got a book about ray casting engines. Ray casting was a method of generating the pseudo 3D graphics of early “3D” games; it was used because it was fast enough to run on those slow processors we had back then (and the GPU race had only just begun). There were a lot of tricks involved, like using trig look-up tables and sections of assembly code.

The reason they used assembly language in middle of high level code for games is that it’s an old-fashioned optimization trick—make the slowest part of the code go faster by writing it in a lower-level language. The premise is that the compiler, for instance of C++, will not make code as fast as your own version in assembly language. Compilers are very good nowadays, so this is often not worth the effort.

Unfortunately, by the time I was learning about ray casting in the late 1990s, the gaming world had already evoloved beyond that and started using BSP trees and polygonal 3D objects. I did start playing with BSP trees in 2001 by making a little Java 3D program that used BSP trees to lay out the walls (it was called the Garbage Collector, which is a joke).

title screen from a small 3D Java game I made

screenshot from my 3D Java game

And then in 2002 I was playing with polygonal 3D rendering by making a multiplayer (client-server TCP) 3D boat shooting game in C++ using Direct3D (part of DirectX) for graphics rendering.

screenshot from Smoke on the Water, my little multiplayer 3D boat shooting game

It didn’t have much of an engine—if I recall correctly, I did a minimal amount of culling and then threw all the objects at Direct3D to render. I was also trying to make my own design of an octree based engine but it never amounted to much.

Assembly Language Education

Education-wise, I suspect that learning assembly and machine language for a relatively simple architecture like an 8-bit microcontroller is much better than learning on a more complicated architecture like Intel x86. I tutored students at NHTI for 68HC11 and Northeastern University for x86. I found that either way, assembly language was quite difficult for a lot of students to learn—and even comprehend. But it was far worse with x86.

And, with an embedded platform, the labs can be set up so you actually make lights blink and motors move. That’s way more awesome then just seeing some debug text print out on a console. It also seems to force people into the mindset of understanding what layers they are dealing with in computer architecture better and isolate their development realm (e.g. writing code in a text editor and cross-compiling) from the world of the computer processor loading the machine code and executing it.

Making Motors Move

If you want to see what the 68HC11 assembly code looks like, here you go:

(Note: all the HC11 code mentioned here can be downloaded on Github.)

* CP108 Digital Devices
* designed for M68HC11E9 EVBU
* Program: 2-Stage Falling-Edge J-K Counter Emulator
* Programmer: Sam Kenyon
* Desc: States are set to be a Grey Code Generator
* Revisions:

* Data Segment			
TIC1	EQU	$1010
TCTL2	EQU	$1021
TMSK1	EQU	$1022
TFLG1	EQU	$1023
PVIC1	EQU	$00E8	
APORT	EQU	$1000	* greycode output port
PACTL	EQU	$1026	* Port A Control

        ORG     $170
QBA0	FCB	%00110000	* states (QB, QA, QB_NOT, QA_NOT)
QBA1	FCB	%01100000	*   (buffered to be one byte)
QBA2	FCB	%11000000	
QBA3	FCB	%10010000

* Code Segment			
	ORG	$100
INIT	LDS	#$0041
	LDAA	#$7E	* JMP opcode
	STAA	PVIC1	* IC1 pseudo vector byte 1
	LDX	#ISR1	* Address of IC1 service routine
	STX	PVIC1+1	* IC1 pseudo vector bytes 2,3

	LDAA	#$80
	STAA	PACTL	* PA7 = output	(6,5,4 ARE ALSO OUTPUT)

	LDAA	#$20
	STAA	TCTL2	* falling edges trigger mode
	LDAA	#$04	
	STAA	TFLG1	* clear all flags (we're using bit 2(IC1F))

	CLI		* enable interrupts

DO1	BRA     DO1	* loop forever

* Subroutine: ISR1
* Desc: X acts as a static variable PSTATE
* Size: ? bytes
* Stack Size:  bytes
	CPX    	#$174
	LDX	#QBA0	* next 4-state cyclE

NONEXT	LDAA	0,X	* send output to port A
	STAA	APORT	*   bits 7-4 (QB, QA, QB_NOT, QA_NOT)	

	LDAA    #$04 
	STAA	TFLG1	* clear all flags (we're using bit 2(IC1F))

	RTI		* Return from service routine

I wrote this code for for an exercise to control a stepper motor with gray code. The motor was small and low-power enough to be run directly off of an HC11 output. The program was a J-K flip-flop circuit emulator (it could actually emulate any 4-state counter if one modified the states in the data segment). It took an input from a function generator to define the frequency which determined the speed of the motor.

Making Motors Move with PWM

One of the most popular ways to control motors and other analog devices is with PWM (Pulse Width Modulation). Here is an example of PWM motor control that I wrote in 68HC11 assembly. Skip to the next section for my explanation of PWM.

* Program: PWM Motor Control
* Programmer: Sam Kenyon
* Desc: Uses the TOF and OC2 interrupts to control output
*	line A7 to provide PWM (Pulse Width Modulation)
*	control of a DC motor.
* Revisions:

* Data Segment			
* Constants:
TMSK1	EQU	$1022
TMSK2	EQU	$1024
TFLG1	EQU	$1023
TFLG2	EQU	$1025
TOC2	EQU	$1018	* Timer Output Compare 2 Register Pair (2 bytes)
TCTL1	EQU	$1020	
APORT	EQU	$1000	* output port
EPORT	EQU	$100A	* input port
PACTL	EQU	$1026	* Port A Control
PVTOF	EQU	$00D0	* Pseudo Vector address
PVOC2	EQU	$00DC	* Pseudo Vector address

* Variables:
        ORG     $180
Toggle	FDB	$7FFF

* Code Segment			
	ORG	$B600
INIT	LDS	#$0041

* Pseudo Vectors (3 bytes):
	LDAA	#$7E		* JMP opcode
	STAA	PVTOF		* TOF PV byte 1
	STAA	PVOC2		* OC2 PV byte 1
	STX	PVTOF+1		* TOF PV bytes 2,3
	STX	PVOC2+1		* OC2 PV bytes 2,3

	CLR	TCTL1		* timer disconnected from output
	LDAA	#$40
	STAA	TMSK1		* OC2 enable
	LDAA	#$80
	STAA	TMSK2		* overflow enable
	STAA	PACTL		* PA7 = output	
	CLI			* enable interrupts


* Subroutine: TOF_ISR
* Desc: Timer Overflow ISR
* Size: 23 bytes
* Stack Size: 0 bytes
	STAA	APORT		* high ouput
	LDD	Toggle
	LDAA	EPORT		* input new duty cycle
	STD	Toggle		* ->Toggle_MSB	
	STD	TOC2		* new duty cycle affects how often OC2 interrupts
	LDAA	#$80
	STAA	TFLG2		* reset flag
	RTI			* return from service routine

* Subroutine: OC2_ISR
* Desc: Output Compare 2 ISR
* Size: 9 bytes
* Stack Size: 0 bytes
OC2_ISR	CLR	APORT		* low output
	LDAA	#$40
	STAA	TFLG1		* reset flag
	RTI			* return from service routine

 What is PWM?

light switch

For those who want a simple explanation of PWM: Imagine flipping a light switch on and off a thousand times per second. But sometimes you leave it on longer or off longer. For example, you have it on 700 times but off only 300 times in that one second. The overall effect is that the light is on at 70% brightness during that time.

PWM is like that. Imagine hooking your switch to a motor. If you switch it with 70% ONs the motor will spin at 70% full speed.

The other key concept is that PWM is typically used as an interface between the digital world of the computer and the analog worlds of motors. A computer processor deals with ones and zeroes—ONs and OFFs. There are outputs on computers  for instance on a microcontroller like the 68HC11 in this article. The ones and zeroes are represented on those outputs with HIGH and LOW voltages. All the other devices connected will use the same standard for what is HIGH and what is LOW, e.g. 5 volts as HIGH and 0.0 volts as LOW. (That’s a bit simplified but I won’t bore you with other details right now).

So the problem is how to get those HIGHs and LOWs to control a motor, which just wants voltage. If it’s a tiny motor it can run directly off of the logic voltage (e.g. 5 V), but that’s not generally a good option. In fact, you usually want the motor power lines isolated from the computer lines.

So PWM (remember, switching really fast) is used. The computer outputs a square wave (HIGHs and LOWs) to a switch, which switches the power from another source (e.g. a battery) into the motor. The higher the percentage of ones (HIGHs) coming out of the computer, the faster the motor goes. Obviously if there is something heavy attached to the motor rotor, it won’t actually go faster, but it will try.

Why was this Exciting?

This was really awesome when I learned about it (and the aforementioned gray code exercise), because up until then my programming was not able to interface to motors. I could make a motor go by connecting a battery directly to the leads, and even add in a mechanical switch, but a single speed motor is not fun for very long.

Once you start learning how to get motors spinning from computer code, and also get inputs from sensors into the code, you start realizing that basic hobbyist robotics isn’t that difficult…

Of course, if you can’t code, then I guess you will be stuck doing the typical undergraduate mechanical engineering student trick of touching a wire from a battery directly to a motor in the contraption they just screwed together and watching the chaos unfold as it flings itself around the lab until they let go of the wire.


Image Credits:

  1. Samuel H. Kenyon
  2. Samuel H. Kenyon
  4. Samuel H. Kenyon
  5. Samuel H. Kenyon
  6. Samuel H. Kenyon
Tags: , , ,

One Response to “Languages, Assemble!”

  1. SynapticNulship » Blog Archive » Languages, Assemble! | Software Engineering Software Says:

    […] Visit link: SynapticNulship » Blog Archive » Languages, Assemble! […]

Leave a Reply

You must be logged in to post a comment.