This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

An Iambic Morse code keyer--my first MSP430 project, developed with LaunchPad

Other Parts Discussed in Thread: MSP430G2211, MSP430G2231, TPL9201

Greetings.  I've recently completed my first project using a Value Line MSP430G2211 chip that came with my LaunchPad.  It is a Morse code iambic keyer.

Background.  To send high speed Morse code, amateur radio operators use a set of "paddles" and an electronic keyer.  Morse paddles are really just two switches set up for use between the thumb and forefinger and are closed by squeezing.  When the left paddle is closed, the electronic keyer sends a series of "dits."  When the right paddle is closed a series of "dahs" is sent.  When both are closed together, the keyer sends alternating dits and dahs, dit-dah-dit-dah-dit-dah-... (or the dah comes first,).  Dits are one "element" long followed by an element of silence.  Dahs are three elements long, followed by one element of silence.  When they alternate the sound resembles iambic pentameter from poetry, hence the name.  By "send" I mean that the keyer's output closes a circuit which causes a transmitter to send a radio frequency carrier.  Morse code just turns this carrier on and off in certain patterns (but with suitable smoothness for changes in the amplitude to keep bandwidth small).

Speed in Morse code is measured in Words per Minute (WPM).  The standard word is PARIS and the space following it.  Skipping even more boring details, the length of one element in milliseconds is given by the equation  Element length (ms) = 1200 / WPM.

I have built several simple keyers (no fancy features, just sending speed change capability) using PIC or Atmel chips, so it was natural for me to try a keyer with the MSP430G2211 that came with my LaunchPad.  I did this after reading the first few chapters of John Davies' book.  What was really new for me (other than learning another assembly language) was the low power capabilities of the MSP430 line.  I was able not only to put the MCU to sleep between sending sessions, but by using a Timer A interrupt for up mode I could induce sleep while sending the dits and dahs, waking only for transitions.  The consequence was that current consumption was 0.7 microamps in idle and 84 microamps when a single paddle was closed (and about double that when both are closed in iambic mode).   With one hour a day of Morse code contacts on the air, I expect my CR2032 button cell powering the unit to last about 18 years.  I am impressed.

Basic design decisions:  32768 Hz clock crystal for ACLK for accurate Morse timing, DCO calibrated at 1 MHz for normal operations, Timer A from ACLK/1.  Used LPM3 so ACLK remains active during sleep.  (The oscillator does not awake quickly enough if I go to LPM4.)  Uses pin change ISR for waking from idle periods and uses Timer A interrupt to wake after sending (or not sending) for an element of time.

The basic algorithm is to check for a paddle closure and set a flag accordingly.  (The program calls the flag a buffer, but this is a misnomer.)  Then if the the corresponding flag is set a dit or dah is sent and the paddles are checked again.  Using the flags eliminates debounce and multiple closure problems. 

If you are interested in this project or would consider constructive criticism of my use of MSP430 features, you can find a zip file under FILES in my personal profile which contains the assembly code, a schematic, and a pdf file with a bit more discussion.

Best regards to all.

PS.  This is obviously a hobbyist project.  No insult is intended to you professional engineers out there on this forum.  It just seems to me that TI is trying to capture some of the microcontroller hobbyist and student market with the LaunchPad, and this is a consequence of that.  My next project is a little development board which fits on top of the LaunchPad and contains a 20-pin ZIF socket, a socket for a crystal or ceramic resonator, and several pushbuttons and LEDs connected to headers.

  • Nice work, congratulations.

     

    I think the self discharge rate of even a lithium battery might cause it to fail before 1-decade even if just left sitting on the shelf, but certainly it is impressive to be able to operate for years whatever the exact number on a small battery for a useful gadget!  One is used to being able to do that with a wristwatch, but it is high time that more 'appliance' gadgets gained the ability to run for weeks, months, years without maintenance -- calculators, phones, radios, whatever.  Chips like the MSP430 will help this occur, as well as advances in technologies like low cost and environmentally friendly small solar cells, fuel cells, energy harvesting, et. al.

    If you check out some of the energy harvesting and solar powered marketing and discussions around MSP430 I suspect you'd also find some ideas about how you might even be able to get such a project to work and self-recharge its battery / capacitor either via ambient room / day light with a small solar celll or by possibly harvesting some of the mechanical energy of the user's grip or whatever during use.

    It would be interesting to see some kind of little SWL receiver or QRP transmitter that could keep itself powered for years when idle and which could self recharge very capably based on either solar or mechanical energy harvesting from its movement while being carried around or by a small crank generator that would weigh only a couple of ounces or whatever.

    There are some sites like opencollector, openh, or whatever to share open source / open hardware designs in addition of course to amateur radio related forums, and of course  resources like batchpcb to help people prototype and share PCB designs such as possibly the one you're contemplating for a next model unit that might be of assistance to your efforts unless you've got other approaches and resources in mind.

     

    Good luck!

     

  • Thanks, C. Hayes.  I hadn't considered the self-discharge rate of lithium button cells, although I should have considering how self-discharge annoys me with NiCd and NiMH battery packs, especially the latter.  If that cuts down the battery life to five years or so, I can live with it., though.  ;->

    Those are some very interesting ideas about energy harvesting for small radio-related projects.  I've used portable solar panels to recharge gell and AGM batteries for portable QRP operations, but energy harvesting sounds like a whole different ball game.  I've seen the TI development board for that, and I'll now take another look.

    Finally, thanks for the information on other sites, both in the post here and in your response to my other post.  Much appreciated.

    Best regards.

  • Great!  Very impressive. Here are some of my random thoughts.

    You are a bit too extravagant. This project fits nicely in a 34-cent G2001, but you used a 49-cent G2112. You wasted 15 cents!

    It is obvious that you are a hobbyist. Professionals do what they do for a living, while hobbyist do what they do for the joy of it. Your work is interesting and full of joy.

    For some unknown reason, I see images of flamenco dancers, and hear the sound of castanuela. What is your next project?

    -- OCY

  • Thank you, old yellow cow!  Yes, very definately a hobbyist.  I hoped you noticed that at least I used the less expensive of the two chips provided with the LaunchPad.  And the enclosure I put it in is an old off-brand mint tin rather than the more expensive Altoids name-brand.  And if you look at total development costs, since my development board cost $4.71 (Newark jacked up the price from the list of $4.30), I'm in pretty good shape.  ;->

    As for a next project, I'm not sure what it will be, although I've set aside parts for a board to plug on top of the LaunchPad with a ZIF socket, LEDs, pushbuttons, etc.  I've just finished a round of projects with another line of MCUs (***cough*** Atmel AVR*** cough***) and am a bit played out.  Plus, I have to get back to working though The Art of Electronics and it's Student Guide.  I've gotten up to the chapter on op amps, and I look forward to finally getting into that subject.  And I'm only into Chapter 7 of John Davies' book on the MSP430. 

    Ever since I retired I've been trying to get in touch with my "Inner EE."  When I was in high school in the early 60's I had intended to go to Purdue and become an electrical engineer.  But one day my science club attended a particularly boring lecture by an engineer and my career track got sidelined into mathematics and statistics.  My last year in grad school I realized I was a closet engineer, but it was too late to change careers.  I did go into industry and had some interesting applied work to do, but thirty years after high school I finally discoverd ham radio and ten years after that microcontrollers, and I'm having so much fun in retirement it should be illegal.

    Cheers.

     

  • Mathematics and Statistics! Very cool! I think a lot of engineers downplay the usefulness of those topics. I really need to spend some more time learning the details of statistics in order to help me with my algorithms for pattern recognition and whatnot.

    For the next project you mentioned about the expansion board, could you link in this thread if you make a post about it? I've been throwing around the idea of writing up a proposal for standardizing LaunchPad shields and would be really curious as to what you think about that considering your already in the process of making a "shield". Personally I would prefer to call them expansion boards, but I think a standard like this would be more for the hobbyist community who I think would prefer the word shield. I could be completely wrong though, I come from the weird mix of being a professional but also being a hobbyist.

    old cow yellow said:

    Professionals do what they do for a living, while hobbyist do what they do for the joy of it. Your work is interesting and full of joy.

    The lucky professionals do what they do not only for a living, but also for the job of it! :-)

    -NJC

    ______________________________

    http://msp430launchpad.blogspot.com

  • Hi NJC.  I am now working on the LaunchPad expansion board.  It is point-to-point wiring on a perf board, so it is slow and tedious.  Basically it uses the headers supplied with the LaunchPad for connection to it (male on the LaunchPad, female on the expansion board) connected to a 20-pin ZIF socket.  I also added connections for the two ground and one Vcc pin on the LP.   There are male headers connected to all these on the expansion board.

    The additional items are planned to be two 10-segment bar graph displays, with only 8 LEDs used in them, dropping resistors for these (active high configuration), four pushbuttons (active low but with no external pull-up resistors), a reset pushbutton with 47K pullup resistor and pulldown 0.0022 uF cap, and a 10K multiturn pot.  All these items will be connected to the MCU headers with "squid" cables from their own headers. 

    Pretty basic stuff, but more than is on the LaunchPad!  When I finish it (whenever that is) I'll either post here or with a new forum topic.  I might even take a picture.

    Cheers.

  • Andrew,

    I have a suggestion to enhance your Iambic Morse Code Keyer. (-; Gilding the lily ;-)

    The suggestion is to add some code to eavesdrop on your existing code and send ASCII characters to a PC via the existing LaunchPad USB interface.

    First you need to modify your existing code.

    (a) Use the Timer in a slightly different way. Set it up to count ACLK in the continuous-mode and do not change TAR or TACTL from that point onward. When you need it to wake up the CPU, first set TACCR0=TAR+[delay]; then set TACCTL0=CIE;. This will cause an interrupt after [delay] clocks. Doing it this way frees the TACCR1 and TACCTL1 for the eavesdropper to use in the same fashion.

    (b) Whenever you are going to send a Dit or a Dah, call the eavesdropper and tip it with what you are about to do.

    Next, you need to implement the eavesdropper code. This code figures out the Morse code from the tips it receives from your existing code and send the corresponding ASCII code to the PC the same way the LaunchPad demo program sends the temperature reading.

    If you like, I can write the code for you. But I cannot test it because I do not know how to send Morse code and I do not have a LaunchPad.

    --OCY

  • @Andrew
    Another question for you. Do you plan on multiplexing the expansion board at all? I'm not sure there will be enough I/O pins for 8 LEDs and 4 push buttons alone. Cool idea though for an expansion board.

    -NJC

    ______________________________

    http://msp430launchpad.blogspot.com

  • Dear OCY, your ideas are quite interesting.  First, using Timer A in continuous mode to free up registers for a USB connection to the PC, and second decoding the Morse and sending it to the PC via USB. 

    I've been meaning to look at how the application supplied on the LaunchPad MSP430G2231 chip does USB communications, but haven't gotten that far yet in my exercises.  I've done RS232 with other chips, but haven't tried anything having to do with USB yet.  The PC side of things in my experience has been only a terminal emulation program to read or write from the MCU via a COM port, so the LaunchPad application on the PC side is also new to me.   To be honest, I haven't yet tried installing the PC side of this example application.

    Even more daunting is decoding the Morse from the dits and dahs into characters.  The program would have to detect when a character is complete (a space of three elements or more), then use, say, a binary tree lookup or something like that to determine the combination that was just sent.  A space character would be sent if there is a delay of seven elements or more.  I've been meaning to try writing a program to do this, as it could be the basis of a feature to record and play back commonly used sequences of characters.  (Most commercially available keyers have this record and play back feature.) 

    You have given me a lot to think about and this would take me out of my comfort zone, which is good.  It will take some time, though, perhaps more than I'd care to admit.

    Cheers.

  • NJC, All the stuff on the board will be connected using male header pins, and my plan is to only use what is needed for a particular project.  So I'm basically putting several items on the board just in case they are needed, but I don't envision needing them all at once.  Thus, no multiplexing will be used.  By the way, there will be 16 LEDs in anticipation of the 20-pin Value Line MCUs having two full 8-bit ports (if no external crystal is used). 

    Thanks for your interest.  I do fear that what I come up with will be so simple it will disappoint you.  I mainly wanted to attach a ZIF socket to the LaunchPad and then decided to add a few standard items (LEDs, pushbuttons) since there was room on the board for them. 

    Cheers.

  • Another suggestion, yet not applicable for the small MSP: replace the switches by capacitive touchpad. It requires a timer with one capture channel per pad (improved version uses n capture inputs for 2n-1 pads). Only one diode is required per pad and the pad itself is on PCB. The MSP may be more expensive, but the costs for the switches are saved. :)

    How it works: CCR0 defines the scanning frequency and toggles an output pin on each overflow. It can also trigger an ISR if you want to read the result of the last scan. (else just read the results when you want it)
    The output pin charges the capacitors, formed by the isolated pad and the surrounding ground through a schottky diode. (e.g. BAT42). When the pin goes low again, the pads discharge through the CCR inputs and the leakage current of the diode. Depending on the capacitance, it takes different time. Tipping the pad with your finger greatly increases the capacitance of the pad and significantly increases the discharge time. The moment when the pad voltage falls below the schmitt-trigger input level is captured and gives the current timer count which is proportional to the discharge time.

  • FYI there is an interesting decoder diagram for a dichotomic search tree for morse code here:

    http://en.wikipedia.org/wiki/Morse_code

    http://en.wikipedia.org/wiki/Dichotomic_search

    That would be an easy enough thing to code up as a state machine though you'd still have to have some adaptive timing to recognize the nominal lengths of dih and dah based on the sending speed, but that wouldn't be too hard, and you could just hard code something that would work over a modest WPM range even with fixed timing.  Automatic level control to recognize the noise vs signal level would be another consideration before triggering the start detection time of a potential dih or dah.

    There are some SPI or I2C based I/O port expanders that give you multiple IOs for only one set of SPI/I2C links to control the expander.  IIRC the TPL9201 is an 8-channel high current NPN open collector driver that takes SPI in, and Maxim and others have various others too.

    Of course the value line MSPs are inexpensive enough that one almost might as well just order a dozen or so in the DIP-14 pin package, and use two of them linked by I2C or whatever if you need a few extra IOs on a peripheral board with the advantage that of course you could use them singly for independent projects as needed too.

    It would be nice if they had some more options in the SOIC 28 pin package or something like that with a few more I/Os and still a 1mm pin pitch though.

     

     

  • Andrew,

    I would like to figure out an algorithm to decoding the Morse from the dits and dahs into characters.

    I intend to include only the following sub-set of Morse.

    [A..Z] 26 capital letters
    [0..9] 10 digits
    [/] — · · — ·
    [(] — · — — ·
    [&] · — · · ·
    [=] — · · · —
    [+] · — · — ·
    [.] · — · — · —
    [,] — — · · — —
    [?] · · — — · ·
    ['] · — — — — ·
    [!] — · — · — —
    [)] — · — — · —
    [:] — — — · · ·
    [;] — · — · — ·
    [-] — · · · · —
    [_] · · — — · —
    ["] · — · · — ·
    [@] · — — · — ·
    [$] · · · — · · —
    [~] any other Dit/Dah combinations

    Could you tell me if any of the above can be omitted? Any additions? Any mistake?

    --OCY

  • Many thanks, Jens-Michael!  I have seen commercial versions of Morse keyers with touchpads and have always wanted to try one.  I've printed out your suggestions and will see what I can do with this one.  Of course, I am still an MSP430 neophite, so it will take some time.

    Cheers, Andy

  • Thank you very much, C. Hayes.  The references will undoubtedly prove most helpful.  I have a bit of experience with I2C on a basic level with AVRs.  For the keyer application the software knows the sending speed, so the timing issues would only be determining if a space is between characters within a word (three elements) or between words (at least seven elements). 

    I have had a complete Morse decoder project in the back of my mind for some time now.  After I get more of Davies' book under my belt I'll see what I can do with both the within-keyer version (for recording messages) and the more general decoder.

    Cheers.

  • Dear OYC.  Subset?!  I think you got all the characters I know of.  ;-> 

    Depending on the application, some of the punctuation could be omitted.  Hams having contacts on the air normally use at most the question mark, equals sign (see why below), slash, comma, and the period.  Also, the official amperstand (di-dah-di-di-dit) means something else and "ES" is used as an abbreviation for "and."  On the other hand, if one is translating written text into Morse, all the symbols you include would be needed.  An example of this is the American Radio Relay League's Morse practice broadcasts (see www.arrl.org) where they send text from one of their periodicals.

    Another fine point is something called pro-signs (the "pro" is for procedural).  As I mentioned above, the equals sign (dah-di-di-di-dah), written BT with an overscore to indicate it is the same as B and T sent together as a single character, is one of these pro-signs and means "break."  It is often used in place of a period between sentences.

    Common prosigns are (without the overscores):  BT - Break (same as "="), AR - End of message (same as "+"), SK - End of transmission, KN - Over to you (same as "(")

    I would ignore the pro-signs and code up all the characters you listed just to be inclusive.  Put in a * for anything not translated.

    One caveat.  Decoders work great on machine-sent Morse and on code sent by hams with good "fists" using an electronic keyer.  Unfortunately, many hams on the air send far-from-perfect code and it can be difficult for even an experienced listener to understand them.  The group of people who use Morse is shrinking due to the aging of the ham population and the fact that one no longer needs to know Morse to get a ham license.  But there are still plenty of us out there who want to preserve this historic mode of communication.

    Cheers.

  • Andrew Palm said:
    Decoders work great on machine-sent Morse

    That is exactly the same problem I faced when doing the touchpad detection. The absolute capacitance may vary, so the system needs to self-adjust, detecting what's short and long based on the difference between the signals it gets. If a signal is more than x% shorter/longer than the other, it must be a different state, if is differs less, it is a variation of the same state and must be considered as a drift etc.

    Translating the '.' and '-' into characters is the easy part. Deciding what's a '.' and what's a '-' is by far more difficult :)

  • Andrew Palm said:

    ...  First, using Timer A in continuous mode to free up registers for a USB connection to the PC, and second decoding the Morse and sending it to the PC via USB. ...

    I am taking a blind shot at the first part. if this still work, I will follow with the second part.

    Does it still work after my modification? (Marked with ";ocy")

    ;-------------------------------------------------------------------------------
    ;   asmTinyKeyer3.s43 - Simple iambic keyer program with pushbutton to
    ;                       set speed
    ;
    ;   This is a simple iambic keyer.  If the pushbutton is held down while
    ;   the dit paddle is closed, the speed is incremented by one wpm.  If the
    ;   dah paddle is closed instead, the speed is decremented by one wpm.
    ;
    ;   If a mono plug is inserted prior to power-up (or the dah paddle is closed
    ;   during power-up), the keyer goes into straight key mode until power is
    ;   removed, keying from the dit contact.
    ;
    ;   Hardware:
    ;     MSP430G2211 with 32.768 clock crystal for ACLK, DCO calibrated at 1 MHz
    ;       for normal system clock.  Clock crystal is 12.5 pf type.
    ;     Pin assignments:
    ;       P1.0  = Dit input
    ;       P1.1  = Dah input
    ;       P1.2  = Pushbutton for speed control
    ;       P1.3  = Output to keying MOSFET gate
    ;       P1.6  = Output to send ASCII code                                   ;ocy
    ;       XIN, XOUT  = 32.768 KHz, 12.5 pf clock crystal
    ;       RST/NMI = 47Kohm pullup resistor, 0.0022 uF pulldown cap
    ;
    ;   Notes:
    ;     When there is no paddle input, MCU is put in LPM3.  It awakens when
    ;     there is a paddle closure.  We must use LPM3 rather than LPM4 if a
    ;     clock crystal is used for Timer A, as the crystal-based oscillator does
    ;     not get up to speed quickly enough when the ISR is exited.
    ;
    ;     During the delays for dits and dahs, the MCU is put in LPM3 with Timer A
    ;ocy  running off ACLK setting the delay time.  The timer is run in single shot
    ;ocy  up mode.  The associated ISR stops the timer.
    ;     CCR0 to delay and wake up the CPU.                                   ;ocy
    ;
    ;
    ;     The timer count for the current sending speed is determined from a
    ;     table in program flash memory.  The time for a single Morse element
    ;     (dit = 1 element on, 1 element off; dah = 3 elements on, 1 element off)
    ;     is calculated by
    ;
    ;         Element (ms) = 1200 / WPM
    ;
    ;     where WPM = sending speed in words per minute.  If the ACLK frequency
    ;     is changed from 32768 Hz the table will need to be recalculated.
    ;
    ;     In straight key mode, the processor is put in LPM3 between changes in
    ;     the key closure.
    ;
    ;
    ;   Andy Palm 2010.07.26
    ;-------------------------------------------------------------------------------

    ;-------------------Includes, defines, equates----------------------------------
    #include "msp430.h"                         ; #define controlled include file

    ; I/O pin definitions
    DIT         EQU     BIT0                    ; Dit contact input
    DAH         EQU     BIT1                    ; Dah contact input
    BUTTON      EQU     BIT2                    ; Speed pushbutton input
    TX          EQU     BIT3                    ; Output to keying MOSFET gate
    TXDn        EQU     BIT6                    ; Output to send ASCII code     ;ocy

    ; Program constants
    WPM_MIN     EQU     10                      ; WPM limits, timer count lookup
    WPM_MAX     EQU     30
    WPM_INIT    EQU     23                      ; Default keyer speed
                                                ; Must be between limits above
    ; Register variables
    ;   R4 = Input buffer bits
    ;   R5 = Current speed in wpm
    ;ocy R7 = WPM table offset
    ;   R7 = Current speed in # of ACLKs                                        ;ocy
    ;   R12 = For local scratch or passing argument to subroutine               ;ocy
    ;   R13, R14, R15 = To be used by ASCII output                              ;ocy

    ;-------------------------------------------------------------------------------
                RSEG    CSTACK                  ; Pre-declaration of segment

    ;-------------------Main Routine------------------------------------------------
                RSEG    CODE                    ; Place program in 'CODE' segment

    Reset:      mov.w   #SFE(CSTACK), SP        ; Set up stack
                mov.w   #WDTPW+WDTHOLD, &WDTCTL ; Stop watchdog timer

    ; Set DCO for calibrated 1 MHz
                mov.b   &CALBC1_1MHZ, &BCSCTL1  ; Set DCO range
                mov.b   &CALDCO_1MHZ, &DCOCTL   ; Set DCO step and modulation
                mov.b   #LFXT1S_0|XCAP_3, &BCSCTL3     ; Select ACLK from LFXT1
                                                ; Set for 12.5 pf internal caps
    ; Configure Port P1
                clr.b   &P1OUT                  ; Set all P1 pins to ground
                bis.b   #0xFF, &P1DIR           ; Set all P1 pins to output

                bic.b   #DIT|DAH|BUTTON, &P1DIR ; Set input pins
                mov.b   #DIT|DAH|BUTTON, &P1OUT ; For pull-up direction
                mov.b   #DIT|DAH|BUTTON, &P1REN ; Pull-up on input pins
                bis.b   #TXDn, &P1OUT           ; De-activate TXDn              ;ocy

                bis.b   #DIT|DAH, &P1IES        ; Interrupt on falling edge

    ;ocy ; Set up Timer A: Clock from ACLK/1, stopped
    ;ocy        mov.w   #TASSEL_1, &TACTL
    ; Set up Timer A: Clock from ACLK/1, continous                              ;ocy
                mov.w   #TASSEL_1|MC_2, &TACTL  ; Do not change TACTL or TAR    ;ocy
    ;ocy        bis.w   #CCIE, &TACCTL0         ; Enable interrupts on Compare 0

    main:
    ; Initialize varibles
                clr.w   R4                      ; Clear input buffer
                mov.w   #WPM_INIT, R5           ; Initialize speed
                call    #Load_Count             ; Timer count for one element
                clr.w   R13                                                     ;ocy
                clr.w   R14                                                     ;ocy
                clr.w   R15                                                     ;ocy

                call    #Straight_Key           ; Check for mono plug/straight key
    Loop:
    ; Test input pins, set buffer bits accordingly
                bit.b   #DIT, &P1IN             ; Dit paddle closed?
                jnz     No_Dit                  ; No
                bis.b   #DIT, R4                ; Yes, set dit bit in buffer
    No_Dit:
                bit.b   #DAH, &P1IN             ; Dah paddle closed?
                jnz     No_Dah                  ; No
                bis.b   #DAH, R4                ; Yes, set dah bit in buffer
    No_Dah:
                tst.w   R4                      ; If no pending output, go to sleep
                jnz     Send_Dit                ; Otherwise, process input

    ; Go to LPM3 sleep to wait for paddle input
                bis.b   #DIT|DAH, &P1IE         ; Enable P1 pin change interrupt
    Sleep:
                clr.b   &P1IFG                  ; Clear any pending interrupts
                tst.b   &P1IFG
                jnz     Sleep
                bis.w   #LPM3|GIE, SR           ; Wait for input in LPM3

    ; Test input pins after awakening, set buffer accordingly
                bit.b   #DIT, &P1IN             ; Dit paddle closed?
                jnz     No_Dit1                 ; No
                bis.b   #DIT, R4                ; Yes, set dit bit in buffer
    No_Dit1:
                bit.b   #DAH, &P1IN             ; Dah paddle closed?
                jnz     No_Dah1                 ; No
                bis.b   #DAH, R4                ; Yes, set dah bit in buffer
    No_Dah1:

    ; If dit buffer bit set, send a dit
    Send_Dit:
                bit.b   #DIT, R4                ; Dit buffer set?
                jz      No_Send_Dit             ; No
                bit.b   #BUTTON, &P1IN          ; Speed change button pressed?
                jnz     Send_Dit1               ; No
                call    #Incr_Wpm               ; Yes, increment speed
    Send_Dit1:
                bic.w   #DIT, R4                ; Reset dit buffer
                bis.b   #TX, &P1OUT             ; Key TX output
    ;ocy        bis.w   #MC_1|TACLR, &TACTL     ; Clear timer and start count up
                mov.w   &TAR, &TACCR0                                           ;ocy
                add.w   R7, &TACCR0                                             ;ocy
                bis.w   #CCIE, &TACCTL0                                         ;ocy
                clr.w   R12                                                     ;ocy
                call    #Listener                                               ;ocy
                bis.w   #LPM3|GIE, SR           ; Sleep in LPM3 while waiting
                bic.b   #TX, &P1OUT             ; Unkey TX output

                bit.b   #DAH, &P1IN             ; Dah paddle closed?
                jnz     No_Dah1A                ; No
                bis.b   #DAH, R4                ; Yes, set dah bit in buffer
    No_Dah1A:

    ;ocy        bis.w   #MC_1|TACLR, &TACTL     ; Clear timer and start count up
                mov.w   &TAR, &TACCR0                                           ;ocy
                add.w   R7, &TACCR0                                             ;ocy
                bis.w   #CCIE, &TACCTL0                                         ;ocy
                bis.w   #LPM3|GIE, SR           ; Sleep in LPM3 while waiting
    No_Send_Dit:

    ; Test input pins, set buffer accordingly
                bit.b   #DIT, &P1IN             ; Dit paddle closed?
                jnz     No_Dit2                 ; No
                bis.b   #DIT, R4                ; Yes, set dit bit in buffer
    No_Dit2:
                bit.b   #DAH, &P1IN             ; Dah paddle closed?
                jnz     No_Dah2                 ; No
                bis.b   #DAH, R4                ; Yes, set dah bit in buffer
    No_Dah2:

    ; If dah buffer bit set, send a dah
    Send_Dah:
                bit.b   #DAH, R4                ; Dah buffer set?
                jz      No_Send_Dah             ; No
                bit.b   #BUTTON, &P1IN          ; Speed change button pressed?
                jnz     Send_Dah1               ; No
                call    #Decr_Wpm               ; Yes, decrement speed
    Send_Dah1:
                bic.w   #DAH, R4                ; Reset dah buffer
                bis.b   #TX, &P1OUT             ; Key TX output
    ;ocy        bis.w   #MC_1|TACLR, &TACTL     ; Clear timer and start count up
    ;ocy        bis.w   #LPM3|GIE, SR           ; Sleep in LPM3 while waiting
    ;ocy        bis.w   #MC_1|TACLR, &TACTL     ; Repeat twice for a three element
    ;ocy        bis.w   #LPM3|GIE, SR           ; long dah
    ;ocy        bis.w   #MC_1|TACLR, &TACTL
                mov.w   &TAR, &TACCR0                                           ;ocy
                add.w   R7, &TACCR0                                             ;ocy
                add.w   R7, &TACCR0                                             ;ocy
                add.w   R7, &TACCR0                                             ;ocy
                bis.w   #CCIE, &TACCTL0                                         ;ocy
                mov.w   #-1,R12                                                 ;ocy
                call    #Listener                                               ;ocy
                bis.w   #LPM3|GIE, SR
                bic.b   #TX, &P1OUT             ; Unkey TX output

                bit.b   #DIT, &P1IN             ; Dit paddle closed?
                jnz     No_Dit2A                ; No
                bis.b   #DIT, R4                ; Yes, set dit bit in buffer
    No_Dit2A:
    ;ocy        bis.w   #MC_1|TACLR, &TACTL     ; Clear timer and start count up
                mov.w   &TAR, &TACCR0                                           ;ocy
                add.w   R7, &TACCR0                                             ;ocy
                bis.w   #CCIE, &TACCTL0                                         ;ocy
                bis.w   #LPM3|GIE, SR           ; Sleep in LPM3 while waiting
    No_Send_Dah:

                jmp     Loop

    ;-------------------Interrupt Service Routines----------------------------------
    ;-------------------------------------------------------------------------------
    Input_ISR:
    ; Interrupt service routine for inputs on Port P1
                bic.b   #DIT|DAH, &P1IE         ; Disable P1 pin change interrupt
    Input_ISR1:
                clr.b   &P1IFG                  ; Clear any pending interrupts
                tst.b   &P1IFG
                jnz     Input_ISR1

                bic.w   #LPM3|GIE, 0(SP)        ; Clear LP and GIE bits on exit
                reti

    ;-------------------------------------------------------------------------------
    TA0_ISR:
    ; Interrupt service routine for TACCR0, called when TAR = TACCR0.
    ;ocy        bic.w   #MC_1, &TACTL           ; Stop timer
                bic.w   #CCIE, &TACCTL0                                         ;ocy
                bic.w   #LPM3|GIE, 0(SP)        ; Clear LP and GIE bits on exit
                reti

    ;---------------------------------------------------------------------------;ocy
    TA1_ISR:                                                                    ;ocy
    ; dummy place holder                                                        ;ocy
                mov.w   &TAIV, R15                                              ;ocy
                reti                                                            ;ocy

    ;-------------------Subroutines-------------------------------------------------
    ;-------------------------------------------------------------------------------
    ; Run in straight key mode, keying from dit paddle.
    Straight_Key:
                bit.b   #DAH, &P1IN             ; Dah paddle closed?
                jz      SK1
                ret                             ; No, return to normal operation
    SK1:
                bit.b   #DIT, &P1IN             ; Dit contact closed?
                jnz     SK2
                bis.b   #TX, &P1OUT             ; Yes, key TX output
                bic.b   #DIT, &P1IES            ; Interrupt on leading edge
                jmp     SK3
    SK2:
                bic.b   #TX, &P1OUT             ; No, unkey TX output
                bis.b   #DIT, &P1IES            ; Interrupt on falling edge
    SK3:
                bis.b   #DIT, &P1IE             ; Enable P1 pin change interrupt
    SK4:
                clr.b   &P1IFG                  ; Clear any pending interrupts
                tst.b   &P1IFG
                jnz     SK4
                bis.w   #LPM3|GIE, SR           ; Wait for change in LPM3

                jmp     SK1
                ret                             ; Should never get here

    ;-------------------------------------------------------------------------------
    ; Increment speed by one wpm in R5 and load new timer count
    Incr_Wpm:
                cmp.w   #WPM_MAX, R5            ; wpm < WPM_MAX?
                jlo     Incr_Wpm1
                ret                             ; No, return
    Incr_Wpm1:
                inc.w   R5                      ; Yes, increment wpm
                call    #Load_Count             ; and load new timer count
                ret

    ;-------------------------------------------------------------------------------
    ; Decrement speed by one wpm in R5
    Decr_Wpm:
                dec.w   R5
                cmp.w   #WPM_MIN, R5            ; wpm - 1 >= WPM_MIN?
                jhs     Decr_Wpm1
                inc.w   R5                      ; No, restore value
                ret                             ; and return
    Decr_Wpm1:
                call    #Load_Count             ; Yes, load new timer count
                ret

    ;-------------------------------------------------------------------------------
    ; Given wpm speed in R5 load Timer A count for single time element.
    ; Uses R7 for calculation of table offset value.
    Load_Count:
                mov.w   R5, R7                  ; Calculate table offset
                sub.w   #WPM_MIN, R7            ; = WPM - WPM_MIN
                rla.w   R7                      ; Multiply by 2 for word addr
    ;ocy        mov.w   WPM_Table(R7), &TACCR0  ; Load timer
                mov.w   WPM_Table(R7), R7       ; # of ACLKs                    ;ocy
                ret

    ;---------------------------------------------------------------------------;ocy
    Listener:                                                                   ;ocy
    ; dummy place holder                                                        ;ocy
                ret                                                             ;ocy

    ;-------------------Flash RAM Data----------------------------------------------
    ;-------------------------------------------------------------------------------
    ; Table giving Timer A count for Words per Minute when using clock crystal
    ; at 32768 Hz for timer clock, divide by 1.  The formula for the table
    ; values is
    ;
    ;           Count = (1.2 / WPM) / (1 / 32768) = 39321.6 / WPM
    ; where
    ;           Length of dit/element = 1.2 / WPM  seconds
    ;
                RSEG    DATA16_C                ; Segment for flash data
    WPM_Table:
                DW  3932 ; WPM 10
                DW  3575 ; WPM 11
                DW  3277 ; WPM 12
                DW  3025 ; WPM 13
                DW  2809 ; WPM 14
                DW  2621 ; WPM 15
                DW  2458 ; WPM 16
                DW  2313 ; WPM 17
                DW  2185 ; WPM 18
                DW  2070 ; WPM 19
                DW  1966 ; WPM 20
                DW  1872 ; WPM 21
                DW  1787 ; WPM 22
                DW  1710 ; WPM 23
                DW  1638 ; WPM 24
                DW  1573 ; WPM 25
                DW  1512 ; WPM 26
                DW  1456 ; WPM 27
                DW  1404 ; WPM 28
                DW  1356 ; WPM 29
                DW  1311 ; WPM 30

    ;-------------------Interrupt Vectors-------------------------------------------
    ; Interrupt vector table
                COMMON  INTVEC                  ; Segment for vectors in flash
                ORG     PORT1_VECTOR
                DW      Input_ISR
                ORG     TIMERA0_VECTOR
                DW      TA0_ISR
                ORG     TIMERA1_VECTOR
                DW      TA1_ISR
                ORG     RESET_VECTOR
                DW      Reset

                END

  • OYC, I programmed another MSP430G2211 with your code and popped it into the keyer.  Worked just fine.  I really like what you have done so far.

    Is there a way to download the code in a post besides cutting and pasting? 

    I look forward to Phase Two.

    Cheers.

  • Nice work.

    One thing: the (dummy) TA1_ISR is silently destroying the R15 content. If it is ever called, the program will likely start behaving erratically.
    Does writing to R3 work as a dummy write? I never tried.

  • Andrew,

    I am also working on a similar project. Can you tell me one thing how you compared the input value from two pins with the stored data so as to produce an ASCII value.

    Actually, i am trying this using an array and it is becoming complicated. So, if you can suggest me something else that would be apt in this case.

     

    Regards

    QWERT

  • Dear QWERT,

    All I have developed so far is my basic keyer code.  (See the *.zip file under my personal profile for the assembly code.)  I have not yet tried to write a program that recognizes the dits and dahs being sent and decodes them into characters.  Since each closure of the dah (dash) paddle produces a dah, and each closure of the dit (dot) paddle produces a dit, the main problem is determining when a character is finished by recognizing the three-element (or more) space between characters (which includes the one element space after each dit or dah) and the seven element space (or more) between words.  I'm guessing that you would use Timer A in capture mode to do this, monitoring the keyed output.

    As for storing the dit and dah patterns for each character, in past projects I used a code that uses one byte for each dit/dah pattern.  The portion of C code below shows such a table, with the characters ordered by their LCD value.  (In this project, characters were typed on a keyboard, put into a buffer displayed by an LCD, and then sent.)  In each stored byte, start with the lsb and move to more sig. bits until you reach a start bit 1 which is not sent.  Then for the remaining bits send a dit for a 1 and a dah for a 0.  They are left-justified.  For example, B which is dah-di-di-dit is 11101000.  I "borrowed" this encoding some years back and it is completely arbitrary.  It is just what I am used to working with. 

    For this project I would reorder the array for quicker look-up or use some kind of data structure like a binary tree, but I have not worked out any details.  I'm hoping that Old Yellow Cow comes up with something slick and I won't have to do it myself.  ;->

    I hope this helps some.  Best regards, Andy.

    // Lookup table for Morse code.  Index is calculated from LCD char
    // value.  Reading from least to most sig. bit:
    //
    //   Filler zeros (not sent)
    //   Start bit (not sent)
    //   Bits to be sent, 1 = dit, 0 = dah (reverse order)

    const char CODE_TABLE[54] = { 0b00000001,  // Flag to send blank
                                  0b10000110,  // '
                                  0b10010100,  // (
                                  0b01001010,  // )
                                  0b00000000,  // * - not used
                                  0b10101100,  // + or AR
                                  0b00110010,  // comma
                                  0b01111010,  // minus or long break
                                  0b01010110,  // period
                                  0b10110100,  // slash
                                  0b00000100,  // 0
                                  0b00001100,  // 1
                                  0b00011100,  // 2
                                  0b00111100,  // 3
                                  0b01111100,  // 4
                                  0b11111100,  // 5
                                  0b11110100,  // 6
                                  0b11100100,  // 7
                                  0b11000100,  // 8
                                  0b10000100,  // 9
                                  0b11100010,  // colon
                                  0b10101010,  // semicolon
                                  0b00000000,  // less than - not used
                                  0b01110100,  // equals or short break BT
                                  0b01011110,  // grtr than = SK
                                  0b11001110,  // question mark
                                  0b10100110,  // @ symbol
                                  0b01100000,  // A
                                  0b11101000,  // B
                                  0b10101000,  // C
                                  0b11010000,  // D
                                  0b11000000,  // E
                                  0b10111000,  // F
                                  0b10010000,  // G
                                  0b11111000,  // H
                                  0b11100000,  // I
                                  0b00011000,  // J
                                  0b01010000,  // K
                                  0b11011000,  // L
                                  0b00100000,  // M
                                  0b10100000,  // N
                                  0b00010000,  // O
                                  0b10011000,  // P
                                  0b01001000,  // Q
                                  0b10110000,  // R
                                  0b11110000,  // S
                                  0b01000000,  // T
                                  0b01110000,  // U
                                  0b01111000,  // V
                                  0b00110000,  // W
                                  0b01101000,  // X
                                  0b00101000,  // Y
                                  0b11001000,  // Z
                                  0b00000000}; // Null - send nothing

  • Andy,

    Sorry, I did not write the code as I proposed yet. (I am still waiting for my LaunchPat to arrive.)

    Here is the scheme I intend to use.

    I will have a static variable “State” to represent the Dits and Dahs that have not been translated yet.  The 1st and the 2nd columns in the Table below show this relation.

    Three kinds of event may happen in each “State”: (a) Dit is detected, (b) Dah is detected, or (c) time-out. These are listed in 4th, 5th, and 3rd column respectively.

    --OCY

    State Comment  ASCII   Dit   Dah
    ===== =======  =====   ===   ===
     00           [space]  01    02
     01   .         E      03    04
     02   -         T      05    06
     03   ..        I      07    08
     04   .-        A      09    10
     05   -.        N      11    12
     06   --        M      13    14
     07   ...       S      15    16
     08   ..-       U      17    18
     09   .-.       R      19    20
     10   .--       W      21    22
     11   -..       D      23    24
     12   -.-       K      25    26
     13   --.       G      27    28
     14   ---       O      29    30
     15   ....      H      31    32
     16   ...-      V      33    34
     17   ..-.      F      66    66
     18   ..--      *      35    36
     19   .-..      L      37    38
     20   .-.-      *      39    66
     21   .--.      P      66    40
     22   .---      J      41    66
     23   -...      B      42    43
     24   -..-      X      44    66
     25   -.-.      C      66    45
     26   -.--      Y      46    66
     27   --..      Z      47    48
     28   --.-      Q      66    66
     29   ---.      *      49    66
     30   ----      *      50    51
     31   .....     5      66    66
     32   ....-     4      66    66
     33   ...-.     *      52    66
     34   ...--     3      66    66
     35   ..--.     *      53    54
     36   ..---     2      66    66
     37   .-...     &      66    66
     38   .-..-     *      55    66
     39   .-.-.     +      66    56
     40   .--.-     *      57    66
     41   .----     1      58    66
     42   -....     6      66    59
     43   -...-     =      66    66
     44   -..-.     /      66    66
     45   -.-.-     *      60    61
     46   -.--.     (      66    62
     47   --...     7      66    66
     48   --..-     *      66    63
     49   ---..     8      64    66
     50   ----.     9      66    66
     51   -----     0      66    66
     52   ...-..    *      66    65
     53   ..--..    ?      66    66
     54   ..--.-    _      66    66
     55   .-..-.    "      66    66
     56   .-.-.-    .      66    66
     57   .--.-.    @      66    66
     58   .----.    '      66    66
     59   -....-    -      66    66
     60   -.-.-.    ;      66    66
     61   -.-.--    !      66    66
     62   -.--.-    )      66    66
     63   --..--    ,      66    66
     64   ---...    :      66    66
     65   ...-..-   $      66    66
     66   [else]    *      66    66

  • OYC, a very cool approach.  I look forward to seeing the code.  The last time I looked, Mouser was saying mid-September for the new run of LaunchPads to come in, so there is lots of time.  ;-> 

    I'm currently looking at the Timers chapter of Davies' book on the MSP430 but had a brief detour to write code for displaying program results on a 16x2 character LCD and adapting it for 3.3V operation.  Not low power, but it's what I had in the junk box.

    Cheers, Andy.

  • hey OCY,

    if i am not wrong, then you are going to develop a code for getting the keying mechanically in the form of morse code and send the corresponding ASCII value on the display using LaunchPad.

    And, both of the chips that come with launchpad(i.e. G2211 and G2231) have only one timer that will be used with UART so as to transmit the data from MCU to PC.

    So how are you planning to control the timing between characters or words while transmission and Can you please explain your last post once again so as to how you are planning to use the data that you have posted.

    regards

    QWERT

  • Both G2211 and G2231 have one Timer with two Capture/Compare channels. I suggested Andy to use only one channel, TACCR0 and TACCTL0, duing the generation of Morse Code. This has already been accomplished with my modifications of Andy's code.

    The other channel, TACCR1 and TACCTL1, can be used to send ASCII code to the PC. This I have not done yet.

    See my earlier replies posted on 08-02-2010 11:51 PM and on 08-05-2010 3:23 PM under the current subject.

  • Both G2211 and G2231 have one Timer with two Capture/Compare channels. I suggested Andy to use only one channel, TACCR0 and TACCTL0, duing the generation of Morse Code. This has already been accomplished with my modifications of Andy's code.

    The other channel, TACCR1 and TACCTL1, can be used to send ASCII code to the PC. This I have not done yet.

    See my earlier replies posted on 08-02-2010 11:51 PM and on 08-05-2010 3:23 PM under the current subject.

  • OCY, 

     

    can you please tell me what does the numbers under DIT and DAH mean in your 4th and 5th column as mentioned.

  • At any moment in time, the Listener is in one of the 67 States (00 to 66) shown in column 1. Initially, it is in State 00. Later on, depending on what happens, it may go to other State as described below.

    Each of these States means the Listener already heard the dits and dahs shown in column 2.

    The Listener will stay in that State for a limited amount of time. If this limit runs out and nothing else is heard, the Listener will send the ASCII code shown in column 3 to the PC and go back to State 00.

    But if it received a dit before time runs out, it will change to the State listed in column 4 (without sending anything to the PC).

    Likewise, if it received a dah before time runs out, it will change to the State listed in column 5 (without sending anything to the PC).

    For example, let us assume that the Listener was in State 12. Find 12 in column 1 and read that row. State 12 means it has already heard “dah dit dah” (according to column 2).  If nothing else is heard and time runs out, it sends ASCII for K (according to column 3) and goes back to State 00. But if a dit is heard before time runs out, it changes to State 25 (according to column 4). If you look at the row with 25 in column 1, it means “dah dit dah dit” is heard (according to column 2). Correct? Likewise if a dah is heard while waiting in State 12, it will change to State 25 (according to column 5) and State 25 means it heard "dah dit dah dah". Correct?

    Note that all unknown Morse Code will end up with ASCII Code for * (following Andy’s recommendation).

  • OCY, 

    This information is great but how can we store or in which form this huge set of data can be stored in our program so as to keep it as reference to compare with the input values.?????

    Thanks 

    QWERT

  • "Huge" is in the eyes of the beholder.

    void main( void )
    {
      printf ("Hello, world!\n");
    }

    Is this "huge"? Try to run this with the G2xx1.

  • OCY,

    I wasn't in the mood of making fun of anything. Anyhow, i am almost done with my code. Now i will try to use the hashing code for the same technique and will try to sort it out more.

    regards

    QWERT

  • Something funny happened to my LaunchPad order at TI e-store. I checked the order status at their website every once in a while. At first, a few days after I placed the order, they said it was shipped. After a week or so, they said it was back-ordered instead. Now, after over two months, they said I have never ordered anything.

    Anyway, I modified Andrew’s code to send ASCII code of what was keyed via a soft-uart at 2400 b/s. I also generated audible square-waves to drive a piezo-effect buzzer.

    The soft-uart output is on the P1.6 pin. I think you can connect P1.6 of the chip to J3-pin4 (called BRXD) of the LaunchPad board. If your PC has either IAR or CCE installed, when you plug the LaunchPad USB cable to an USB port of the PC, I think you should see a VCP in the Device Manager of your PC. When you are not using IAR or CCE, a terminal emulator (such as the HyperTerminal) should be able to use that VCP. Set it up to use 2400 b/s, 8 data-bits, no parity, 1 stop-bit, and no flow control. I think you should be able to see the ASCII characters.

    To hear the audible, you need to connect a piezo-effect buzzer between P1.5 and P1.4. My code drives these two pins alternatively between 0 and 3V to produce 6V peak-to-peak. If you do not have such buzzer, you can connect either P1.5 (and Gnd) or P1.4 (and Gnd) to a headset or other audio device. The audible frequency is between 541 Hz (~C#5) at 10 WPM and 1638 Hz (~G#6) at 30 WPM.

    Here is the modified code.3463.Weird.zip Please let me know if it works. (As I do not have a LaunchPad and do not know how to send Morse code.)

    -- OCY

  • Dear OCY,

    I've successfully gotten your code into my PC.  I'll try to test it out sometime in the next week or two prior to our vacation.  Since I built an expansion board for my Launchpad that includes a piezo speaker I should be able to set things up for sound.  I haven't tried the USB/VCP thing with my LaunchPad yet, but hopefully it will go OK. 

    I haven't been doing much in the way of MSP430 work lately, so getting your program installed on my LaunchPad will help keep things MSP430-ish refreshed in my mind. 

    Cheers, Andy

  • OC Y-- It works!!  After writing the previous message I decided to dig in right away and try running it as I could sense your frustration with not having a LauchPad yet.  (Mouser is now indicating the last week in September for the two I have on backorder.)

    I had a bit of trouble getting the hardware connected (the setup is quite ugly and was done in haste) and even more trouble getting the serial port to work properly (I'm not real familiar with the Device Manager) but finally the letters showed up in my Tera Term Pro terminal program.  On my laptop the TI VCP was COM4.  My piezo speaker has one terminal connected permanently to ground, but driving it from just P1.4 worked fine.  I tested the output to the transmitter with an LED.

    There was just one tiny software problem.  The numeral "1" came out as unrecognized, displaying as "*".   All the other numerals, letters, and punctuation were OK to the best I could tell.

    The spacing between characters and words is somewhat demanding when sending, but I got the hang of it.  This is pretty typical of Morse decoders from my limited experience with them.  When people send code on the air, even if they use an electronic keyer the spacing often deviates from the standard. 

    I am very impressed with what you have done.  When I get the time I will have to crawl through your code, figure out how you did it, and then steal your ideas.  ;->

    Cheers and thanks again for doing this, Andy

  • Andy,

    You are fast!

    Sorry about the mistake for 1.

    In my 08-13-9010 11:26 AM posting, I had an erroneous entry in the table.

    State Comment  ASCII   Dit   Dah
    ===== =======  =====   ===   ===
     ~~
     22   .---      J      4166  6641
     ~~


    The numbers 41 and 66 are transposed. As a result, “.---.” was recognized as 1 and “.----“ was recognized as *.

    To correct this mistake, please change the corresponding tables in the code as follows:

    Dit_tbl:
      DB 01,03,05,07,09,11,13,15,17,19
      DB 21,23,25,27,29,31,33,66,35,37
      DB 39,66,4166,42,44,66,46,47,66,49
      DB 50,66,66,52,66,53,66,66,55,66
      DB 57,58,66,66,66,60,66,66,66,64
      DB 66,66,66,66,66,66,66,66,66,66
      DB 66,66,66,66,66,66,66
    Dah_tbl:
      DB 02,04,06,08,10,12,14,16,18,20
      DB 22,24,26,28,30,32,34,66,36,38
      DB 66,40,6641,43,66,45,66,48,66,66
      DB 51,66,66,66,66,54,66,66,66,56
      DB 66,66,59,66,66,61,62,66,63,66
      DB 66,66,65,66,66,66,66,66,66,66
      DB 66,66,66,66,66,66,66


    About the timing, please try to make the following change and see if it becomes less demanding. The 3rd and 4th instruction after the label TA1_8: are both “add.w R7, R12”, insert another one between them.

    Regards,

    OCY



  • There is another place that may need to be changed. After the label “TA1_Bz2:”, you may want to insert another “add.w R7, R12” between the existing two.

  • Hi OYC.  I corrected the tables and '1' now displays correctly.  I tried both timing increases.  The first one helped in spacing between words, the second one made forming words harder.  So I kept the first mod (in TA1_8) and removed the second one (in TA1_Bz2). 

    The only tricky hardware issue was with the clock crystal.  I had to mount the chip to the LaunchPad rather than the satellite board to keep the crystal connections short.  (No surprise there--I did a previous post on this point.)  Oh, and I had to connect P1.6 to BRXD with a clip lead (rather than the usual squid cable) because of board clearance problems.  This didn't seem to hurt the serial port communicaitons, though. 

    So you did it, and I am very impressed.  I hope in the future to build a decoder that will capture the audio from a receiver, but that will require some analog signal processing and speed detection.  I need to study up on a number of things before I take this one up.

    I hope your LaunchPads get to you soon.  They are fun.

    Cheers, Andy

  • Andy,

    In retrospect, you may not really need the 32.768 kHz crystal for this project. The VLO may be good enough as ACLK to generate the WPM delays. DCO/8 can be used as SMCLK to generate the audible tones and the soft-uart bit clock.

    You could also leave P1.1 and P1.2 for TXD and RXD respectively even if you do not use them. And if you use one LED, put it on P1.0. If you use two LEDs, put the second one on P1.6. Keep the button at P1.3 as you did.

    By the way, was the buzzer laud enough when driven from one side only? Was the frequency used appropriate?

    When you listen over the air, what is the frequency of the audible tone? Is there a standard? Is it generated by the remote transmitter or by the local receiver?

    -- OCY

  • OYC,

    The buzzer was loud enough driving one side, at least for me.

    On the air, the frequency heard by the receiving station is determined by their receiver's offset from the transmitted signal, so they can generally listen at any frequency they find acceptable by where they tune.  Typically hams like something between 400 to 800 Hz.  Less expensive rigs set the listening frequency to something fixed, but most rigs allow a choice.  On the better rigs, the sidetone heard in the transmitting station's speaker is selectable and equal to the offset used upon receiving.

    I used the clock crystal because if I just used the DCO it would not recover quickly enough upon waking up from sleep.  (I tried the DCO approach first.)  I wanted maximum sleeping time to preserve the coin cell battery that powers the original keyer.  If one built the keyer with a display for the letters sent or a computer connection, then power saving would likely be a moot point and with no sleeping the DCO could be used as you say.  At least that is my understaning of things.

    Again, thanks so much for doing this.

    Andy

  • This is a little off the topic. I post it here in order to catch the eyes of Andrew Palm.

    Mike Staines of NY is trying to use Launchpad to generate RF at one of the P1 pins as an exciter (for a class-D RF amplifier and antenna) to make a beacon. see: http://tech.groups.yahoo.com/group/msp430/message/47454

    Anyone interested in this?

    --OCY

**Attention** This is a public forum