Mac 67 Posted May 31, 2011 Share Posted May 31, 2011 May I ask what is the purpose of your CIR capture device, please? Is it to help you identify an unknown protocol being used by a remote control? It provides all the necessary info needed to reproduce a remote's transmission or respond to a remote control. So, if you want to make your own remote or make something that responds to an existing remote, then this device will provide essential information. I guess I really meant to ask why you need the capability to measure the frequency? After you've identified a protocol (SIRC, RC5, etc.), can't you deduce the frequency? Quote Link to post Share on other sites
oPossum 1,083 Posted May 31, 2011 Author Share Posted May 31, 2011 No, the frequency is part of the protocol specification. Timing alone is not enough information. Quote Link to post Share on other sites
Mac 67 Posted May 31, 2011 Share Posted May 31, 2011 No, the frequency is part of the protocol specification. Timing alone is not enough information. Really! I didn't know that! I assumed the timing of the various protocols was enough. For example, the 12, 15, or 20 bits of SIRC with 2400/600 start bit, and 1200/600 and 600/600 data bits, was unique enough to identify it from other protocols. Live and learn... Regards, Mike Quote Link to post Share on other sites
oPossum 1,083 Posted June 1, 2011 Author Share Posted June 1, 2011 The MSP430 could calculate the carrier frequency and durations as explained in the previous post, but there is no need for it to do that. All it has to do is send the IR pulse count to the PC and let the PC do the calculations and display the results. Doing this in real time requires that each count be sent in less than the 100 microsecond gate time. The lowest standard bit rate that can do this is 115.2 kbps. The MSP430 assembly code to do this is explained in this thread. The rest of the code is setup, reading the Timer and driving the status LED. The main loop executes in exactly 100 cycles, so a timer is not needed. The UART on the Launchpad is limited to 9600 bps, so a board with a FTDI FT232R chip is used to transport the serial data to the PC. Launchpad FT232R Gnd -- Gnd Tx P1.1 -> Rx FC P1.5 <- RTS How to wire it up... Firmware for MSP430G2211 .cdecls C, LIST, "msp430g2211.h" ; Include device header file ; ; 1 Vcc - ; 2 P1.0 In PU Alt IR LED ; 3 P1.1 Out -- IO Txd ; 4 P1.2 In PU IO Rxd ; 5 P1.3 Out -- IO IR LED Gnd ; 6 P1.4 Out -- Alt SMCLK out ; 7 P1.5 In PD IO Flow Control ; 8 P1.6 Out -- IO Green LED ; 9 P1.7 Out -- IO Not Used ; 10 RST --- -- -- SBW ; 11 TEST --- -- -- SBW ; 12 XOUT - ; 13 XIN - ; 14 Vss - ; .text .global _main _main mov.w #0x0280, SP ; Initialize stackpointer ; ; Stop watchdog timer mov.w #WDTPW + WDTHOLD, &WDTCTL ; ; Use 1 MHz calibration clr.b &DCOCTL ; mov.b &CALBC1_1MHZ, &BCSCTL1 mov.b &CALDCO_1MHZ, R4 ; ;add.b #7, R4 ; Tweak cal if necessary mov.b R4, &DCOCTL ; ; ; mov.b #0xDA, &P1DIR ; See chart above for I/O assignment mov.b #0x25, &P1REN ; Pull up resistor for IR LED, Rxd, Pull down for Flow Control mov.b #0x07, &P1OUT ; Pull up, serial idle high mov.b #0x11, &P1SEL ; Enable Timer A external input, SMCLK output ; mov.w #0x0024, &TACTL ; External clock, continuous mode ; widget ; mov #0x20, R10 ; Setup flow control bitmask in R10 mov #0x40, R11 ; Setup status LED output bitmask in R11 mov #0x02, R15 ; Setup serial output bitmask in R15 bic.b R11, &P1OUT ; Status LED off ; wait bit.b R10, &P1IN ; Check flow control input jne wait ; Loop until low ; clr R14 ; Clear previous count bis #0x04, &TACTL ; Reset counter first mov TAR, R12 ; Get current count cmp R12, R14 ; Compare current to previous jeq first ; Loop if no change... jmp ledon ; Send initial count... ; loop ; mov TAR, R12 ; Get current count ; cmp R12, R14 ; Compare current to previous jne ledon ; bic.b R11, &P1OUT ; == LED off ; Start bit bic.b R15, &P1OUT ; 0 jmp bit0 ; ; ledon bis.b R11, &P1OUT ; != LED on ; Start bit bic.b R15, &P1OUT ; 0 jmp bit0 ; ; bit0 rrc R14 ; Bit 0 jc bit0h ; bic.b R15, &P1OUT ; 9 nop ; rrc R14 ; Bit 1 jc bit1h ; bic.b R15, &P1OUT ; 17 jmp bit2 ; bit0h bis.b R15, &P1OUT ; 9 nop ; ; bit1 rrc R14 ; Bit 1 jc bit1h ; bic.b R15, &P1OUT ; 17 jmp bit2 ; bit1h bis.b R15, &P1OUT ; 17 jmp bit2 ; ; bit2 rrc R14 ; Bit 2 jc bit2h ; bic.b R15, &P1OUT ; 26 jmp bit3 ; bit2h bis.b R15, &P1OUT ; 26 jmp bit3 ; ; bit3 rrc R14 ; Bit 3 jc bit3h ; bic.b R15, &P1OUT ; 35 nop ; rrc R14 ; Bit 4 jc bit4h ; bic.b R15, &P1OUT ; 43 jmp bit5 ; bit3h bis.b R15, &P1OUT ; 35 nop ; ; bit4 rrc R14 ; Bit 4 jc bit4h ; bic.b R15, &P1OUT ; 43 jmp bit5 ; bit4h bis.b R15, &P1OUT ; 43 jmp bit5 ; ; bit5 rrc R14 ; Bit 5 jc bit5h ; bic.b R15, &P1OUT ; 52 jmp bit6 ; bit5h bis.b R15, &P1OUT ; 52 jmp bit6 ; ; bit6 rrc R14 ; Bit 6 jc bit6h ; bic.b R15, &P1OUT ; 61 nop ; rrc R14 ; Bit 7 jc bit7h ; bic.b R15, &P1OUT ; 69 jmp bitstop ; bit6h bis.b R15, &P1OUT ; 61 nop ; ; bit7 rrc R14 ; Bit 7 jc bit7h ; bic.b R15, &P1OUT ; 69 jmp bitstop ; bit7h bis.b R15, &P1OUT ; 69 jmp bitstop ; ; bitstop nop ; Stop Bit jmp $ + 2 ; bis.b R15, &P1OUT ; 78 ; mov R12, R14 ; Move current count to previous ; nop ; ; bit.b R10, &P1IN ; Check flow control input jeq loop ; Keep sending data while low... jmp widget ; Start over if high... ; ; ; Interrupt Vectors .sect ".reset" ; MSP430 reset vector .short _main ; ; .end ; Windows software Next post will show how to use the captured data to reproduce the IR signal with an MSP430. bluehash, juani_c and RobG 3 Quote Link to post Share on other sites
oPossum 1,083 Posted June 4, 2011 Author Share Posted June 4, 2011 Circuit construction on a protoboard. fj604 1 Quote Link to post Share on other sites
fj604 34 Posted June 5, 2011 Share Posted June 5, 2011 As promised, I have posted the NEC protocol IR decoder code here: http://www.43oh.com/forum/viewtopic.php?f=10&t=1053 I also have code for the Sony IR protocol. Quote Link to post Share on other sites
oPossum 1,083 Posted June 15, 2011 Author Share Posted June 15, 2011 The capture software (IR Scope) presents a graphic representation of the captured IR signal as previously shown. It also saves the capture to a text file. The text file has a three line header followed by the on and off durations. The first line identifies the file as an ir capture with file format revision 0. The second line is the IR carrier frequency. The third line is the count of on/off durations that follow. An on duration is a positive integer followed by an optional cycle count. An off duration is a negative integer. The contents of the text file are simply reformatted for use in the MSP430 firmware. The carrier frequency is stored as (CPU_clock / IR_carrier) - 1. That gives the Timer A PWM period. Having the assembler do the calculation saves codes space and execution time. The on and off durations are the same as the capture except for values that will not fit in a 16 bit integer - they must be split up in to several words. The cycle count is not used. The list is terminated with a zero rather than storing the length- that makes manual editing easier. .word (1000000 / 38446) - 1 ; Carrier frequency .word 8952, -4422 ; On/off duration .word 578, -548 .word 578, -496 .word 604, -544 .word 556, -1670 .word 556, -544 .word 582, -544 .word 578, -522 ; more... .word 0 ; End of code Timer A PWM is used to generate the IR carrier frequency. A delay loop with one cycle granularity is used to time the on/off durations. The loop overhead has been adjusted so the timing is exact. This code simply transmits one IR code when the P1.3 pushbutton on the Launchpad is pressed. It could easily be expanded to handle a keypad and any number of IR codes. .cdecls C, LIST, "msp430g2211.h" ; Include device header file ; ; 1 Vcc - ; 2 P1.0 In PU IO Not Used ; 3 P1.1 Out -- IO Txd ; 4 P1.2 In PU IO Rxd ; 5 P1.3 In PU IO Switch ; 6 P1.4 Out -- Alt SMCLK out ; 7 P1.5 Out -- IO Not Used ; 8 P1.6 Out -- Alt IR Out ; 9 P1.7 Out -- IO Not Used ; 10 RST --- -- -- SBW ; 11 TEST --- -- -- SBW ; 12 XOUT - ; 13 XIN - ; 14 Vss - ; ; .text .global _main _main mov.w #0x0280, SP ; Initialize stackpointer ; ; Stop watchdog timer mov.w #WDTPW + WDTHOLD, &WDTCTL ; ; Use 1 MHz calibration clr.b &DCOCTL ; mov.b &CALBC1_1MHZ, &BCSCTL1 mov.b &CALDCO_1MHZ, R4 ; ;add.b #7, R4 ; mov.b R4, &DCOCTL ; ; ; mov.b #0xF2, &P1DIR ; See chart above for I/O assignment mov.b #0x0D, &P1REN ; Pull up resistor for switch and Rxd mov.b #0x0F, &P1OUT ; Pull up, serial idle high mov.b #0x50, &P1SEL ; Enable Timer A output, SMCLK output mov #0x0210, &TACTL ; Timer A config: SMCLK, count up ; ; wait bit.b #0x08, &P1IN ; Wait for switch down jnz wait ; ;mov #ir_test, R4 ; Setup pointer to IR data mov #ir_ac_cool, R4 ; Setup pointer to IR data call #tx_ir ; Send IR .if 1 ir_rpt mov #ir_ac_rpt, R4 ; Setup pointer to IR repeat data call #tx_ir ; Send IR bit.b #0x08, &P1IN ; Check if switch down jz ir_rpt ; Yes, send repeat code again... .endif jmp wait ; Loop... ; ; tx_ir mov @R4+, R12 ; Get carrier period mov R12, &TACCR0 ; Setup Timer A period rra R12 ; Setup Timer A compare mov R12, &TACCR1 ; ; ir_tx_loop mov @R4+, R12 ; Get duration tst R12 ; Check if zero jeq ir_done ; Yes, exit... jn ir_off ; If negative, turn off ir... ; mov #0x00E0, &TACCTL1 ; Turn on IR carrier (reset/set output mode) inv R12 ; Wait for on duration call #delay ; jmp ir_tx_loop ; Do next duration... ; ir_off mov #0x00A0, &TACCTL1 ; Turn off IR carrier (reset output mode) dec R12 ; Wait for off duration call #delay ; jmp ir_tx_loop ; Do next duration... ; ir_done mov #0x00A0, &TACCTL1 ; Make sure IR carrier is off ret ; Return ; ; ; delay add #32, R12 ; Adjust for overhead delay4 nop ; 4 cycle loop add #4, R12 ; jnc delay4 ; rla R12 ; One to four cycle remainder add R12, PC ; nop ; nop ; nop ; ret ; ; ir_test .word (1000000 / 40000) - 1 ; Carrier period .word 200, -200 ; .word 300, -300 ; .word 400, -400 ; .word 500, -500 ; .word 600, -600 ; .word 700, -700 ; .word 800, -800 ; .word 900, -900 ; .word 1000, -1000 ; .word 500, -10000 ; .word 0 ; ; ir_sony .word (1000000 / 40000) - 1 ; Carrier period .word 2400, -600 ; Lead in .word 1200, -600 ; 1 .word 600, -600 ; 2 .word 1200, -600 ; 3 .word 600, -600 ; 4 .word 1200, -600 ; 5 .word 600, -600 ; 6 .word 1200, -600 ; 7 .word 600, -600 ; 8 .word 1200, -600 ; 9 .word 600, -600 ; 10 .word 1200, -600 ; 11 .word 600, -600 ; 12 .word 600, -30000 ; Lead out .word 0 ; ; ir_ac_cool .word (1000000 / 38265) - 1 .word 8930, -4444 .word 578, -548 .word 578, -522 .word 578, -544 .word 556, -1670 .word 556, -544 .word 582, -544 .word 578, -522 .word 578, -548 .word 578, -1644 .word 556, -544 .word 582, -1644 .word 582, -544 .word 578, -1648 .word 552, -1670 .word 556, -1670 .word 556, -1670 .word 556, -1670 .word 552, -548 .word 578, -522 .word 578, -1644 .word 582, -544 .word 582, -518 .word 582, -544 .word 578, -522 .word 578, -548 .word 552, -1648 .word 578, -1670 .word 556, -544 .word 582, -1644 .word 578, -1648 .word 578, -1644 .word 582, -1644 .word 582, -30518 .word -10000, 0 ir_ac_rpt .word (1000000 / 38265) - 1 .word 8930, -2244 .word 556, -32000 .word -32000, -31170 .word 0 ; Interrupt Vectors .sect ".reset" ; MSP430 reset vector .short _main ; ; .end ; DanAndDusty 1 Quote Link to post Share on other sites
DanAndDusty 62 Posted June 15, 2011 Share Posted June 15, 2011 Thanks for that oPossum. It was fun reading the assembler code. I haven't done any assembler in a long time. I used to write in Z80, TMS9900 (on the TI-99/4A) and 8086 (moved to higher languages before the 80286 came out so haven't ever done anything with protected mode etc). Nice to see I can still read and understand it all (although Im not sure I could write from scratch) I assume that the lines starting with dots are compiler directives (.if 1). One question though.. You have a bit commented out that Im curious about. You load the DCO calibration into R4 and have commented out where you add 7 to it. Why is this? Have you tested the calibrations and found that 7 was closer, or did adding 7 come closer to the carrier frequency you wanted? Anyway, thanks again for a fun, educational read. Good luck in POTM Quote Link to post Share on other sites
oPossum 1,083 Posted June 18, 2011 Author Share Posted June 18, 2011 The .if/.endif are equivalent to #if/#endif in C. They are assembler directives that allow conditional assembly. In this case it allows the code for NEC style repeating codes to be easily disabled when it is not needed. I have tweaked the DCO value to be more accurate for the specific chip I am using. The calibration in flash is close, but tweaking it got the clock even closer to 1.00 MHz. The firmware enables SMCLK output on P1.4 so the clock frequency can be checked and adjusted if desired. Having a precise clock is usually not necessary for sending IR, but it is very desirable for IR capture. The TMS430 has a small and simple instruction set, so it is easy to learn. I think it is a good chip to learn assembly programming. For low power, high performance or cost sensitive applications it can be very useful to program in assembly or a mix of C/C++ and assembly. Quote Link to post Share on other sites
none 7 Posted July 5, 2011 Share Posted July 5, 2011 You probably meant to write "the MSP430 has a small and simple instruction set .." :-) So far I either used an oscilloscope or a photo diode hooked up to the audio input. Of course, those often have decoupling capacitors and filters so the signal will be distorted as any DC component will 'fade out'. With 38 kHz and a high sampling rate it works OK though. How did you create the signal imagery (something like http://drawtiming.sourceforge.net/)? Just a couple of other IR resources: LaunchPad IR Receiver viewtopic.php?f=9&t=358 "The code watches for pulses on P1.6 (IR_BIT) and accumulates pulse timings into an array. Once enough have been gathered they Quote Link to post Share on other sites
none 7 Posted July 6, 2011 Share Posted July 6, 2011 Problem (see solution below) When I try to build this as "main.asm" with TI's Code Composer Studio (CCS) inside an "empty assembly-only project" project template, I get lots of errors. Build output first lines below: **** Build of configuration Debug for project irscope **** C:\Program Files\Texas Instruments\ccsv4\utils\gmake\gmake -k all 'Building file: ../main.asm' 'Invoking: Compiler' "C:/Program Files/Texas Instruments/ccsv4/tools/compiler/MSP430 Code Generation Tools 3.3.3/bin/cl430" -vmsp -g --define=__MSP430G2211__ --include_path="C:/Program Files/Texas Instruments/ccsv4/msp430/include" --include_path="C:/Program Files/Texas Instruments/ccsv4/tools/compiler/MSP430 Code Generation Tools 3.3.3/include" --diag_warning=225 --printf_support=minimal --preproc_with_compile --preproc_dependency="main.pp" "../main.asm" "../main.asm", ERROR! at line 21: [E0002] Illegal mnemonic specified _main mov.w #0x0280, SP ; Initialize stackpointer Also errors: [E0001] Undefined symbol [E0004] Non-local label Solution When copying oPossum's embedded source code from this forum, everything was indented. Labels must not be indented! Everything else should be. irscope.asm.txt irscope.txt bluehash 1 Quote Link to post Share on other sites
bluehash 1,581 Posted July 6, 2011 Share Posted July 6, 2011 Thanks for that. ASM files may need to be attached instead of BBTAGGED. Quote Link to post Share on other sites
none 7 Posted July 7, 2011 Share Posted July 7, 2011 I was able to capture an Apple Remote 2G with an OSRAM LD274 IRED ( http://catalog.osram-os.com/catalogue/c ... owBookmark ) at very close range. A 5 mm IRED of unknown type did not work, neither did a large photodiode, which demodulated the signal (see oPossum's remark on the TIA). So thanks, nice project, and a well-written explanation. Some ideas in return (you probably thought of this): Ideally, it would be possible to use just a LaunchPad with the IRED to receive and send, using a cross-platform software :-) While the frequency is interesting, the pulse count can be estimated from burst times. Also, it would probably be practical if the SPACEs had an equivalent pulse count displayed. As I've not used MS VC before - maybe someone knows how to solve this problem? Can't import with Visual C++ 2010 Express : End tag 'xs:choice' does not match the start tag 'xs:sequence'. Quote Link to post Share on other sites
oPossum 1,083 Posted July 7, 2011 Author Share Posted July 7, 2011 Unfortunately the Windows software uses MFC, so it can't be build with the Express version of Visual C. I am working on new software that uses Qt, and will be testing on Windows and Mac. Interesting that the LED of unknown type did not work. I have used a variety of IR LEDs from various mfg and they all worked. Large photodiodes have substantial capacitance, so no surprise it didn't work. An external pullup resistor may help compensate for the capacitance. I have developed a novel and very simple method to send IR, but haven't had time to do a write up. I have it working on PIC12F and could easily port it to MSP430. Thanks for the comments and feedback. Good to know it was useful to someone. The IR Widget has become quite popular with the JP1 hackers. One forum member even sells them. Quote Link to post Share on other sites
davidnhutch 0 Posted May 7, 2012 Share Posted May 7, 2012 Hi oPossum, Fantastic work. You posted asm code for the sending of data. I'm only familiar with C code in CCS. Is there a way for you to convert that to C code and post it here, so I can understand what's going on and integrate this into some code I'm working on? Best regards, D Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.