This is what I do for fun… I spent my weekend at my place in Wisconsin.
Working on CC110L Wireless BoosterPack Code
I have once again started to look through the code for the wireless CC110L wireless booster pack. The Anaren example source code is basically unusable to me. Within each file there will be something which appears to be a function, yet when traced to it’s location, one finds that it is merely a preprocessor definition. One then figures that the actual function has been found, but no, when traced to the next layer it is found to be yet another preprocessor definition (usually a completely useless one). Layers upon layers of preprocessor #defines, #ifdefs and so on lead one down a trail that provides little information with a lot of verbosity. It gives one an extreme dislike of preprocessing as an entire concept and even a dislike of the C language itself. This helps to explain my recent divergence into assembly language… anything to escape the ugly world of C preprocessor macros!
Faced with this situation I started to look for other code examples for this Boosterpack. I found out about TI’s SLAA325a datasheet and code library. This code is actually readable by a human, however it has a limitation in that it does not have a Launchpad board defined (several others are defined, however). I thought I could get this code working anyway though if given enough time.
Asking about it on the 43oh forum, I was directed to a thread about the Anaren TI CC110L RF AIR Booster Pack. Here one of the forum members has modified the TI code to include support for the Launchpad board. You can get a copy of his code from Github. He has one repo for IAR and another for MSPGCC.
I was able to get his code to compile under MSPGCC and it seems to be working although I didn’t really have time to test it yet. The code is decent enough. With some cleanup I think it will be really good. There are some warnings emitted by GCC and there is some code formatting inconsistencies due to have it having multiple authors.
Besides studying that wireless code, I have also been studying some of the more powerful processors out there like ARM and MIPS. I have been putting a lot of time into learning the MSP430, and I want to be sure that this is something that will still be in wide use in the future. I don’t want to spend tons of time learning a 16-bit microcontroller only to find that it is about to become obsolete and to be replaced by 32-bit microcontrollers. From what I can tell, it appears that the MSP430 will be around for a while. I like it because it seems to have a cleaner structure and a much stronger assembly language than ARM or MIPS, but I have really only looked at them briefly and have not had enough time to learn much more.
Also, humorously, the whole reason for me to learn all this stuff – my wireless lighting project – is somewhat irrelevant now. I repaired my trailer lighting several weeks ago, so I don’t even need wireless lights any more. I just rewired the trailer with conventional wiring. At this point I am simply continuing to learn because I find it interesting. I was thinking that even if I don’t need a wireless lighting system, maybe someone else does and I can still sell it as a product. However, really it only took me a couple hours to repair the lights on my trailer, so why would anyone else pay $250 (or whatever) for wireless lights when it only takes a couple hours to repair with conventional wiring? I am not sure whether I am really filling any demand or if I am building a product that no one wants.
I do have several other ideas for electronic projects but I have no way of gauging what the market wants so I have no idea which one I should work on!
How to Use MSP430 Addressing Modes
The MSP430 features several different addressing modes. This is covered pretty well in the MSP430x2xx Family User’s Guide section 3.3. However, it is one thing to read about it, and it is a completely other thing to actually use it. To ensure that I really understand it, I decided to try each mode out. I am using Naken430Asm and MSPDebug in these examples below. If you are using CCS/IAR, the assembly language will be the same, but there might be a few directives that are different.
Below is the program I will be stepping through with the debugger. I am not going to explain how to use the debugger or how to assemble the code, since I covered it in the preceding two videos I posted on this blog.
.include "msp430g2553.inc"
.include "launchpad.inc"
;; Setup MCU
.org 0xFFFE
dw setup ; interrupt vector for Reset
.org 0xC000
setup:
mov #WDTPW|WDTHOLD, &WDTCTL ; disable watchdog
; clear registers
clr SR
clr R4
clr R5
clr R6
clr R7
clr R8
clr R9
clr R10
clr R11
clr R12
clr R13
clr R14
clr R15
; use immediate mode to copy the constant 0x0280 to the stack register
mov #0x0280, SP ; initialize stack pointer
eint ; enable maskable interrupts
; copy clock speed calibrations using absolute addressing mode
mov.b &CALDCO_1MHZ, &DCOCTL ; DCO frequency set to 1 MHz
mov.b &CALBC1_1MHZ, &BCSCTL1 ; DCO range set to 1 MHz
clr.b BCSCTL2 ; MCLK and SMCLK set to use DCO
mov.b &LFXT1S_2, &BCSCTL3 ; LXFT1 set to VLO (not crystal)
;; Main program to demonstrate addressing modes
main:
; register addressing mode
mov #0xAAAA, R4 ; put a temporary value in register 4
mov R4, R5 ; copy contents of register 4 to register 5
; indirect register addressing mode
mov #0xCCCC, &0x0286 ; put a temporary value in RAM at 0x286
mov #0x0286, R7 ; put the memory address in register 7
mov @R7, R8 ; copy the contents of address 0x286 to register 8
; indexed addressing mode
mov #0xBBBB, &0x0282 ; put a temporary value in RAM
mov #0x0280, R6 ; put the memory address in register 6
mov 2(R6), 4(R6) ; copy contents of address 0x282 to address 0x284
; indirect autoincrement addressing mode
mov #0xDDDD, &0x0288 ; put a temporary value in RAM at 0x288
mov #0xEEEE, &0x028A ; put another temporary value in RAM
mov #0x0288, R9 ; put the memory address in register 9
mov #0x028C, R10 ; put the destination RAM address in register 10
mov @R9+, 0(R10) ; copy the contents of address 0x288 to 0x28C,
; then increment the address in register 9
mov @R9+, 0(R10) ; copy the contents of address 0x28A to 0x28C,
; then increment the address in register 9
end:
jmp end
The first and simplest mode is immediate addressing mode. This one can be seen in line 10 and line 28 in the code above. Essentially what I am doing is copying an explicitly stated constant value to some location in memory. On line 28, I am copying a hexadecimal value, 0280 to the stack register (SP). To specify an immediate address, I use the # symbol. You will note that there is no # symbol in front of SP. That is because SP is a register which doesn’t require it. The register is part of the assembly language and when I type SP it knows what I mean. Furthermore, you can see I have a leading 0 in front of the hex value. I don’t think this is strictly required by the assembler, but it is a good reminder that you are dealing with a 16-bit (word) value. For this program I am using all word values and no bytes.
On line 10 I am using some constants logically ORed together to shut off the watchdog timer. The constants aren’t an address… they are just collections of configuration bits which are placed into the WDTCTL address. WDTCTL is called the Watchdog Timer Control and is part of the peripheral memory, which is used for communication with the assorted peripherals on the MSP430. If you go to the msp430g2553.inc file, you can see the constants defined:
WDTCTL equ 0x0120 ; Watchdog Timer Control WDTHOLD equ 0x0080 WDTPW equ 0x5A00
The logical ORing is translated by the assembler when the code is assembled. After it has been assembled, that line looks like the following:
MOV #0x5a80, &0x0120
Next, at line 32, 33, and 35 you can see that there are quite a few & symbols. This is called absolute addressing mode. What it is doing is rather than copying the constants as immediate mode does, it is copying the values at the addresses. To understand this, think about the wall of mailboxes at the post office. Every box has a number (po box number) and inside the box there may be some mail. When you think of computer memory, it is the same. Each location in memory has an address as well as a value inside the address. In this example of copying clock speed calibrations, I am actually copying the values inside the addresses, not the addresses themselves.
Those two addressing modes are the main ones I’ve used while teaching myself assembly, but there are five others supported by the MSP430.
One of these is register addressing mode. This one is pretty simple. It just means you are copying a value from one register to another and you can see this illustrated in lines 40 and 41. Check out the mspdebug output as I step through these two, paying close attention to R4 and R5 (which I cleared earlier to make them zero):
(mspdebug) step
( PC: 0c03c) ( R4: 00000) ( R8: 00000) (R12: 00000)
( SP: 00280) ( R5: 00000) ( R9: 00000) (R13: 00000)
( SR: 00008) ( R6: 00000) (R10: 00000) (R14: 00000)
( R3: 00000) ( R7: 00000) (R11: 00000) (R15: 00000)
0xc03c:
0c03c: 34 40 aa aa MOV #0xaaaa, R4
0c040: 05 44 MOV R4, R5
0c042: b2 40 cc cc 86 02 MOV #0xcccc, &0x0286
0c048: 37 40 86 02 MOV #0x0286, R7
(mspdebug) step
( PC: 0c040) ( R4: 0aaaa) ( R8: 00000) (R12: 00000)
( SP: 00280) ( R5: 00000) ( R9: 00000) (R13: 00000)
( SR: 00008) ( R6: 00000) (R10: 00000) (R14: 00000)
( R3: 00000) ( R7: 00000) (R11: 00000) (R15: 00000)
0xc040:
0c040: 05 44 MOV R4, R5
0c042: b2 40 cc cc 86 02 MOV #0xcccc, &0x0286
0c048: 37 40 86 02 MOV #0x0286, R7
0c04c: 28 47 MOV @R7, R8
0c04e: b2 40
(mspdebug) step
( PC: 0c042) ( R4: 0aaaa) ( R8: 00000) (R12: 00000)
( SP: 00280) ( R5: 0aaaa) ( R9: 00000) (R13: 00000)
( SR: 00008) ( R6: 00000) (R10: 00000) (R14: 00000)
( R3: 00000) ( R7: 00000) (R11: 00000) (R15: 00000)
0xc042:
0c042: b2 40 cc cc 86 02 MOV #0xcccc, &0x0286
0c048: 37 40 86 02 MOV #0x0286, R7
0c04c: 28 47 MOV @R7, R8
0c04e: b2 40
0c050: bb bb
You can see how the 0xAAAA value is propagated into the R4 and R5 registers as I single-stepped through the instructions.
The next addressing mode is called indirect register addressing mode. You can see it in action on lines 43 through 46 in the code. This one is somewhat like register addressing mode. However, rather than operating on a value in the source register, the source address is stored in the source register, which in turn references a value out in memory somewhere. The destination register receives the value (not the address) of the memory location the source points to. Confused yet?
Well, I am not sure what this mode is useful for in real code. Maybe after I learn more I will be able to tell you. It also has the somewhat surprising restriction that only the source can point to an address. You can’t use the @ symbol on the destination register.
Next up is the indexed addressing mode (lines 48-51 in the code). This one makes a little more sense to me. Essentially what it does is to add a number (any number you specify) to the addresses in the registers and it copies the value from one address to another address. I can imagine one would use this to implement memcpy() in a high level language like C. You would just call it multiple times sequentially with different numbers in front of the register names until you reached the “size” value, which I assume would be stored in a third register along with a counter in a fourth register to store the adder. The first two registers would just be holding the base addresses for the source and destination.
The last addressing mode I am demonstrating in the code is indirect autoincrement addressing mode (lines 53-61). According to the MSP430 User’s Guide, this is useful for table processing. What it does is to copy different source values from memory into a single destination register. Each time you call it, it increments the source address by one or two bytes depending on whether you are working at bytes or words. It replaces whatever is in the destination register with the value from memory. I don’t really know what this mode is good for, but I guess when I need to do some table processing, I’ll revisit it.
There is one more addressing mode which I haven’t demonstrated in my code. It is called symbolic addressing mode. The reason I don’t have a demonstration of it is because I couldn’t get it to work with Naken430asm version 10/30/11. I assume it does work in Code Composer (I didn’t try). Of course the problem could also be that I am using it wrong, but I don’t think so.
How I believe this mode is supposed to work is that it copies a value from a label in assembly (e.g. at a ‘dw’ value) to a destination address in memory (RAM I would normally assume). I tried to setup a label with a value, but after it was assembled, the code was copying it from the wrong location in memory. So my guess is that this is an uncommon addressing mode and that the Naken author just hasn’t implemented it yet. If I ever need this mode, I’ll just email him, but I don’t see it as being all that useful to begin with though so it isn’t a big concern to me.
I hope this has clarified to you how the addressing modes work on the MSP430. My advice is to load the code above on your microcontroller and step through each line one by one to get a better understanding of how it works. This exercise has certainly helped me understand it. Additionally, as always, if you see any mistakes in my code or my writeup, let me know in the comments below!
How to Program and Debug the MSP430 with MSPDebug (Video)
This is a video demonstration of programming and debugging a simple assembly language project with MSPDebug. Remember to check out the MSP430x2xx Family User’s Guide – this has an example for every assembly language command in section 3.4.6!
How to Program the MSP430 in Assembly Language (Video)
In this video I explain what software to use to program in Assembly Language under Linux/Unix for the MSP430. I also show a simple assembly language program I am developing as an example of assembly programming.
Tools used in this video:
MspDebug
Naken430Asm
MSP430 Launchpad (the device I am programming)
Assembly Language is Fun! (Video)
I explain that assembly language is fun to learn and use. I also cover the architecture of the MSP430 microcontroller.
This video was prompted by an article I read about schools no longer teaching C or assembly.
How to Use Clocks on the MSP430 Microcontroller
Before configuring clocks on the MSP430, you might wonder what a clock is used for on a microcontroller and why should you care? Well, the clock is used for timing by the processor and peripherals. For example, if you set the master clock to 16 MHz, the processor will be going really fast and consuming full power, however if you set it to 1 MHz, it will be running slower and using less power. It is also used by the peripherals (such as the serial interface) to coordinate when they should send/receive data.
The MSP430 has three clocks. They are called the MCLK (master clock), SMCLK (sub-main clock), and ACLK (auxiliary clock). Each of these clocks must be assigned to a clock source. There are four possible clock sources: DCOCLK (internal digitally controlled oscillator), LFXTCLK1 (external clock source such as a crystal), XT2CLK (high frequency external clock source), VLOCLK (internal low frequency oscillator). To further complicate matters, not all clock sources are available to all clocks.
First I wondered why there is a need for three different clocks. Wouldn’t one be enough? Well, it appears that the reason for this is so that different peripherals can operate at different speeds. The two high speed clocks, MCLK and SMCLK, are used for high speed peripherals and the processor. MCLK is used for the processor and SMCLK is used for peripherals. The lower speed ACLK is used for slower peripherals. Furthermore, the reason for having two high speed clocks I assume is because one is normally used only for controlling the processor speed (MCLK) and the other one (SMCLK) is used for peripherals, which may need to be high speed, but not necessarily the same speed as the the processor.
Next you may wonder why there are different sources that the clocks can base their speed off of. The purpose of this is so that you can have different accuracy in your clocks. It is possible to use a highly accurate crystal if you need precise timing (such as if you were building an electronic wristwatch), however in many cases it will be adeqate to use the internal clocks which are somewhat inaccurate and vary their speed based on the chip’s temperature and other things.
Of the four clock sources, DCOCLK and VLOCLK are both internal to the microcontroller. You don’t have to add anything to your board to use these. Of the two external clock sources, XT2CLK is not in any microcontroller that I was able to find. It is an optional feature. However, you will probably have LFXT1CLK (the documentation states that only MSP430G22x0s don’t have it).
If you have the MSP430 Launchpad, along with the board and two sample chips you will have received a 32768 Hz crystal. On one of my boards I soldered it on, but for the rest I left it off. By soldering the crystal on to your Launchpad, you can have a accurate clock, if that is important to you. It is used for one of the lessons that are included with the Launchpad, however if I recall correctly, it interferes with the Anaren Wireless BoosterPack, so don’t solder it on if you are using that.
The configuration of the clocks is controlled through four registers: DCOCTL and BCSCTL1 through 3. By default, the MCLK and SMCLK are set to use the DCO as a clock source, and the DCO is configured for 1 MHz. The ACLK is set to use LFXT1, an external crystal. If these settings work for you, I’d suggest not trying to change them since the process is somewhat cumbersome.
Probably the most frequent things you will want to change are the master clock speed and the ACLK source.
First, let’s talk about the ACLK source. To change it from an external crystal to the internal 12 kHz VLO, in C you would do “BCSCTL3 = LFXT1S_2;”. However, according to the documentation, the VLO is not available in all the MSP430s. Apparently it is only available in certain models. To find out whether your MSP430 supports the VLO (or XT2CLK), check the datasheet. On my G2553 datasheet, which is named SLAS735E, I found it on page 2, under the section titled Description. There is a table which shows the features of each chip and under the Clock column you can find out what you have. Mine reads “LF, DCO, VLO” which tell me the three choices I have for a clock source.
Second, you might want to change the master clock speed. If you try reading the MSP430 Family User’s Guide to figure out how to do this, you might get a headache. It seems really complicated to me. Fortunately there are some preprocessor definitions for some standard settings which have been calibrated from the factory. The header files are located under C:\Program Files (x86)\Texas Instruments\ccsv4\msp430\include if you are on Windows with Code Composer 4. In msp430g2553.h, I found the calibrated MHz settings at line 830 (search for the phrase “Info Mem”). Here I found that there are four calibrated settings: 1 MHz, 8 MHz, 12 MHz, and 16 MHz.
To change the speed, you have to configure the DCO. This is done through the DCOCTL and BCSCTL1 registers. For example, to set my chip to 8 Mhz, I did this:
DCOCTL = CALDCO_8MHZ; // DCO frequency set to 8 MHz
BCSCTL1 = CALBC1_8MHZ; // DCO range set to 8 MHz
Besides what I’ve discussed so far, there are some additional features you should be aware of. One is that clock sources can be further modified by dividers. The default divider is 1 (no division), but you could reduce the frequency by dividing it by 2, 4, or 8. Also there is an ability to send the clock output to a pin, in case it is needed externally. Finally, there is a clock oscillator fault detector which you can enable. This will cause an interrupt in the case of a crystal malfunctioning on your board.
As you can see, clocks are a very complex subject. (Or at least it seems complex to me, as someone trying to learn.) I have not even gotten into the possibility of turning off clocks by going into a low power mode. That will have to be a different post.
What I have found most helpful for learning clocks is the end of chapter 5 in MSP430 Microcontroller Basics, the MSP430 Family User’s Guide (chapter 5 “Basic Clock Module+”), and experimenting with the Grace plugin for Code Composer. Although Grace is not working for me due to an inexplicable low voltage error, I found it is still helpful because you can go to the Power User button under BCS+ and visually configure the clocks. After you’ve done that you can click on the Registers button to get an idea of how the registers should be setup. I then go into a text editor on my other PC and code the register settings in C and compile the code with MSPGCC. This is sort of a weird way of doing it but it is better than nothing. I don’t know why Grace isn’t working for me (it was working earlier), but I’ll investigate it more later.
If anyone finds any mistakes in this post, please mention it in the comments below!
MSPGCC Example Makefile and Pinout for Wireless BoosterPack
I have been making some progress with the MSP430 and the CC110L Wireless BoosterPack. Anaren’s BoosterStack Lite software isn’t really relevant to me, since I am writing all my own code instead. That is why I didn’t bother reading the user manual before shooting a video on it. I just wanted to give people a quick look at it and it is not really something I am ever going to use.
Writing my own code requires a little research, and in fact on Wednesday I read the entire MSP430 Tutorial I linked to earlier. That ebook is sort of like a shorter version of the MSP430 Microcontroller Basics book which I also have. I thought the Tutorial was pretty good, although it does have a lot of typos and has less detail than the Basics book. However, I won’t complain – it was free and made for quick reading.
Today I created a GNU Makefile by hand (something I haven’t done for a long time). For my wireless lighting project I am going to have two codebases – one for the controller (car) module and another for the lights. Each one will have a separate Makefile and separate source code, although some source files might be shared between the two. The whole thing is under one directory and I will probably be setting up a Subversion repository so others can take a look at the code. However, for the time being I am just going to paste the code to my blog.
Here is the makefile. I called one makefile Makefile.car and the other Makefile.lights. I’ll just post the car one since the lights one is pretty much the same.
#
# This Makefile is compatible with GNU Make.
#
MCU = msp430g2553
TARGET = wireless_car
#
# Directories
#
BASEDIR = $(PWD)
OBJDIR = $(PWD)/obj_car
SRCDIR = $(PWD)/src_car
#
# Programs
#
CC = msp430-gcc
OBJCOPY = msp430-objcopy
MAKETXT = srec_cat
SIZE = msp430-size
TAGS = ctags
#
# Flags
#
CFLAGS = -g -pipe -mmcu=$(MCU) -Os -std=c99 -Wall -Wno-main
CFLAGS += -DBASEDIR=\"$(BASEDIR)/\"
LDFLAGS = -Wl,-Map=$(TARGET).map
#
# Libraries
#
#LIBS = -lm
#
# Obj files
#
OBJS = $(OBJDIR)/main.o
#
# Rules
#
all: clean depend $(TARGET).elf $(TARGET).hex $(TARGET).txt
asm: $(TARGET).lst
tags: $(SRCDIR)/*.[ch]
$(TAGS) $(SRCDIR)/*.[ch]
depend:
$(CC) $(CFLAGS) -MM $(SRCDIR)/*.c > .depend
$(TARGET).elf: $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) $(OBJS) -o $@
$(SIZE) $(TARGET).elf
%.hex: %.elf
$(OBJCOPY) -O ihex $< $@
%.lst: $(SRCDIR)/*.c
$(CC) -c $(CFLAGS) -Wa,-anlhd $< > $@
$(OBJDIR)/%.o: $(SRCDIR)/%.c
$(CC) $(CFLAGS) -c $< -o $@
%.txt: %.hex
$(MAKETXT) -O $@ -TITXT $< -I
clean:
-rm -f .depend $(TARGET).* $(OBJDIR)/*.o *.core tags
Hopefully that will save someone the immense amount of time I spent writing it! There might be a few mistakes, but overall I think it is a good skeleton makefile.
Note if you have trouble with the makefile not working, try checking that is indented with tabs rather than spaces. This is a common incompatibility with makefiles – I don’t know if GNU Make has the problem but I tabbed mine just in case. Another thing to check is that if you are using OpenBSD rather than Linux, as I am, GNU Make is invoked as “gmake” rather than “make.” This is because BSD has their own Make program. To invoke this file I just run: gmake -f Makefile.car && mspdebug rf2500 "prog wireless_car.elf" The MSPDebug part just uploads the code to the MSP430 Flash memory. You can also run MSPDebug interactively and type out the prog command if you prefer.
Since I have two separate microcontrollers, I run two copies of MSPDebug in the foreground and it seems to be smart enough that it just detects that one of the devices is already attached with MSPDebug, so it attaches to the second one. I don’t actually invoke MSPDebug like I just posted in the command above — I always leave two instances of it running in a separate window. The order the devices are attached to the MSPDebug process are the same order as they were plugged in to the USB cable.
The second thing I was doing was examining the datasheets to find what pins go where between the transceiver (CC110L) and microcontroller (MSP430 Launchpad). Here is a little map of it I made in a C comment:
/* * ---[ Pinout Summary ]--- * * Transceiver <-> Microcontroller * SCLK < P1.5 * SO/GDO1 > P1.6 * SI < P1.7 * CSn < P2.7 (XOUT) * GDO0 > P2.6 (XIN) * GDO2 > P1.0 * * Transceiver pin meaning: * SCLK - SPI bus clock signal * SO - SPI bus data out from radio when CSN is low, and general purpose I/O pin when CSN is high * SI - SPI bus data into radio * CSn - SPI bus select (active low) * GDO0 - General purpose port * GDO2 - General purpose port */
This I think will be easier to reference than constantly flipping back and forth between datasheets. The microcontroller communicates with the wireless radio via Serial Peripheral Interface (SPI). I may add more to it later once I learn what I am doing. This is my first serious electronics project and the first time I’ve used SPI manually (not counting Parallax Propeller objects)!!
MSP430 Launchpad and CC110L Wireless BoosterPack Demo
In this video I demonstrate the Anaren CC110L Wireless BoosterPack for the Texas Instruments MSP430 Launchpad. This is a low-cost solution which allows microcontrollers to communicate wirelessly. I also explain how to pair nodes with the free BoosterStack Lite software.
UPDATE: I was not doing the pairing right… after I made this video I read the manual (lol, right?) and it explains it better.
Wireless Tow Lights Teardown
This weekend my parents visited me and my dad brought his wireless trailer tail lights. He brought them because although they are “wireless”, there is a still a wire between the two lights. The problem he had was that he broke the wire between the two lights and they no longer worked. This is pretty stupid, in my opinion – why would a company sell wireless tail lights that have a wire between them? The wireless feature is that it is wireless from the vehicle to the lights (there is no trailer wiring), however the lights themselves are still connected to one another.
Anyhow, to fix the problem we soldered the wires back together. However, since I am building my own wireless tail lights, I decided to have a closer look at his to see how someone else had implemented the idea. Maybe I can learn a few things from their design.
Here are the photos I took. You can click on them to get a bigger view.

View of one of the lights. It is no secret which company makes these! When assembled, both lights and the transmitter have big magnets on the bottom to attach them to a trailer or towed vehicle.

Wireless tow lights transmitter. This small plastic box transmits RF signals to the lights. Note the blue magnet at the bottom to attach it to the vehicle.

Inside the transmitter. You can see that there is not a lot to it. The LEDs come on when the lights are powered up. The black line around the top of the box is just a rubber gasket.

The circuit board for the light with the antenna. One of the lights has a "rubber ducky" antenna. The other light doesn't. The signal is passed through a wire from one light to another. This is less expensive to manufacture and simpler to build than having an antenna on each light. However, it seems like a cheap solution to me since you now have to have a wire running from one light to the other!

Circuit board from light with no antenna. This one is the same board as the other light, except that it has fewer chips.
Before I returned the lights to my dad, I recorded the letters and numbers from the integrated chips. I did this so that I could study their datasheets later. I haven’t actually done that yet but plan to. Here they are, with links to the datasheets.
Transmitter Circuit Board
Mfg: Holtek
Component: HT600
Serial: A748G5192#1
Purpose: Signal encoder
Light with Antenna Circuit Board
Mfg: Holtek
Component: HT614
Serial: A750K0332#
Purpose: Signal decoder
Mfg: MAXIM
Component: MAX1473
Serial: EUI 0810
Purpose: 300-400 MHz RF Receiver (there must be a corresponding sender on the transmitter, but I didn’t notice it anywhere)
Mfg: TI
Component: AC86
Serial: 81A867K G4
Purpose: Or Gate
Mfg: TI
Component: PS78601
Serial: 81CL22H
Purpose: Voltage regulator
Mfg: TI
Component: PS79533
Serial: 79JK6YE
Purpose: Voltage regulator
Additionally, these wireless tow lights are patented with US Patent #4859982. I haven’t actually read the patent yet, but I can tell from looking at the circuit boards that my design is significantly more complex than this one. I don’t know anything about patent law – perhaps I will still be able to sell the wireless tail lights I create if they are different enough.



