Sunday, April 6, 2014

Optimizing MSP430 Code Size with GCC

I’ve started using the prerelease version of Code Composer Studio 6.0, which comes with a GCC 4.8 compiler support. For now, I’m just working on getting used to how it differs from TI’s compiler.
One of the problems I’ve been having is that adding in unused source files causes the compiled code to balloon in size. For instance, adding in my commonly used libraries caused the binary to take up 3172 bytes for a simple UART loopback program. Removing some files I knew never got included shrunk it to 1344 bytes.
I eventually realized this has to do with how GCC, and possibly all compilers, work. It compiles each source file individually, then links them together. By default, all unused functions in each source file are still included, because it can’t tell what is and isn’t used when compiling each file. This seems somewhat obvious in retrospect, but isn’t it always?
To get around this, you can tell GCC to place each function and data item into its own section using the flags -ffunction-sections and -fdata-sections. This makes it possible for the linker to identify function code and data items after compilation. To actually have the linker optimize unused sections out, you’ll want to add the flag --gc-sections. See the images below for where these options can be checked off in Code Composer Studio.
With these options on, my code size is now 1288 bytes. I’m certain there are other optimizations I could do here to make the code even smaller, but this at least allows me to include source code libraries.



Monday, November 26, 2012

Followup on Reading IR Remote Codes: DVB-T Dongle Remotes

While I have the IR reader set up, I thought it might be prudent to read the codes from the only other IR remote control I own: the remote that came with my DVB-T dongle.

Quick background: if you haven't heard of the rtl-sdr project, fix that now. Essentially you can get a dongle meant for receiving TV broadcasts for about $20, which in fact can receive any radio signal in the range of around 50-1700 MHz. Basically, you can started with software-defined radio (SDR) for practically nothing.

The SDR dongle I purchased came with a remote, shown below. While grabbing the IR codes for my RGB LED strip remote, I discovered that the SDR dongle remote used an almost identical coding scheme. Not surprising, considering how similar they are in their construction.



Oddly enough, while the RGB LED remote has an address byte, a data byte, and their inverses, this remote encodes two separate address bytes, followed by the inverse of the data byte, then the data byte. Don't forget that I'm operating under the assumption that a short pause is a 1 and a long pause is a zero; if you are using the opposite, then the address bytes are inverted and the data byte and its inverse change places. Anyway, the address that I read out was 0x79 0x94. This shows that the address is definitely useful for distinguishing between remotes that use identical coding schemes. As for the data bytes, they're shown below in the following table:


Mute
13
EPG
11
Live TV
1C
Power
12
1
01
2
02
3
03
Stereo
0D
4
04
5
05
6
06
S. Shot
19
7
07
8
08
9
09
Zoom
10
Recall
0A
0
00
CH Up
0B
VOL Up
0C
Teletext
1B
REC
1D
CH Dwn
15
Vol Dwn
18
Stop
0E
Pause
1E
Source
0F
Favorite
1A

So with that, if you ever find yourself using this remote in a project, you'll have an idea of where to start!

Custom RGB LED Strip Control, Part 1: The Remote Control

I recently acquired two 5m lengths of RGB LED strip, both of which came with control boxes, remote controls, and power supplies. Right now they're basic mood lighting for a room in my apartment. The problem is that the control boxes each drive their own strips, but work off of the same remote control. As such, I'm controlling them "together" by virtue of having taped their IR sensors next to each other. This...doesn't always work properly.

So instead, I would like to make a custom control box, one that can control the strips separately or in tandem, but will still function using the included remote control. I will be adding an increased brightness range and individual control over the red, green, and blue channels in the process. The MCU driving all this will be an MSP430G2553. If possible, I will also add an audio input that the MSP430 can use to sync the lights to music / sound.

The LED strip remote. Source


The first step is reverse engineering the remote control and writing control codes for it. Thankfully this part has been taken care of for me, thanks to this post by Mohonri. Using a TSOP34838 38 kHz IR receiver and a Saleae Logic Probe, I was able to confirm that the IR protocol is the same from Mohonri's post.

The protocol works by sending IR pulses at a 38 kHz rate when active. The start of a sequence is indicated by an active period of around 9 ms, followed by an inactive period of around 4.5 ms. After this, data is transmitted by sending a short pulse of around 650 us, then pausing either 650 us or 1.65 ms before sending another short pulse. A short pause indicates a 1, and a long pause indicates a 0. Decoding the data this way, I verified Mohonri's statement that 4 bytes are sent: the inverse of the address byte, the address byte, the inverse of the data byte, and the data byte. If a short pause were taken to be a 0 and a long pause to be a 1, then the bytes and their inverses would be swapped. So really, it can be taken either way.

Anyway, after decoding the data this way, I noted that the address byte is 0x00, that the data byte varies depending on the button pressed. After a bit of mucking around, I realized that the most logical arrangement is if the data is read as being sent least significant bit first. Decoding the button presses this way yielded the following layout:

RGB Remote Codes
Up
5C
Down
5D
Forward
41
Power
40
Red
58
Green
59
Blue
45
White
44
54 55 49 48
50 51 4D 4C
1C 1D 1E 1F
18 19 1A 1B
Up Red
14
Up Grn
15
Up Blu
16
Quick
17
Dwn Red
10
Dwn Grn
11
Dwn Blu
12
Slow
13
DIY1
0C
DIY2
0D
DIY3
0E
Auto
0F
DIY4
08
DIY5
09
DIY6
0A
Flash
0B
Jump3
04
Jump7
05
Fade3
06
Fade7
07

Notice how the codes mostly make sense once you get past the third row of colors. It kind of annoys me that the sensible layout gets ditched for the top part of the remote, but oh well; it wouldn't have made a difference in the code anyway.

Rather than manually decode these button presses, I used some MSP430 coding to get the data for the above table. Using the MSP430 Launchpad, I connected the IR receiver output directly to the TimerA1 CCR0 module and had it trigger an interrupt every time the line changed. I used some simple state machine coding to have it detect the initial pulse, then to start reading out data based on the length of each pause. The TimerA1 was configured to count to 0xFFFF continuously, so I could detect length of pauses by subtracting a second capture value from a previous capture value. CCR1 was used to reset it to initial conditions if no state change occurred after a certain period of time. The interrupt routine stored the data to a circular buffer, which I then read out using the USCI peripheral, which was set up as a UART transceiver.

(Side note: The Launchpad, for whatever reason, has the TX and RX lines hooked up wrong for the MSP430G2553. I had to swap them with some jumper cables. That little detail held me up a bit...)

I have uploaded all of my code, written in the Code Composer Studio 5.2 IDE, to Google Drive. Also included are my personal VT100 library and my BCD converter assembly function, which I find useful any time I'm dumping data out over a terminal.

Link to CCS Project: https://docs.google.com/open?id=0B5dybbS2PoDtV1dIaWNVLWhZWTA

With this code implemented, it should be easy to deal with IR remote data in the main program loop, especially if I just have it read in the data to a 4-byte buffer instead of a circular buffer, like I am now.

In my next post, I'll be working out how I'm going to actually drive all the channels on the LED strips.

A Statement of Intent

The goal of this blog is to serve as a) documentation of my personal projects, and b) a place where I can rant about technology. Having spent uncountable hours lurking on Hackaday and similar blogs, I thought it high time I start posting stuff myself. After all, I've learned plenty from reading about the projects of others; hopefully people can learn something from my own projects as well.

That said, let the writing begin.