Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


Reputation Activity

  1. Like
    jsolarski reacted to timotet in ringLight. A WS2812 led based light for my 3d printer.   
    I built a 3d printer last year and needed a small light to illuminate the build area, this is what I came up with.
    I call it the ringLight.

    I thought about using an Adafruit Neopixel ring, but due to the finished part being for a specific size I decided to roll
    my own. I used a MSP430G2452 in the TSSOP 14 pin package for the micro. I have to thank every one on the forum for
    the wealth of info related to the WS2812 leds, and a special thanks to @@oPossum for the led driver code he posted.
    The code is pretty straight forward. Once powered on the msp430 loads what ever value from flash that was
    used from the last time power was on, then waits for a button press. If the button gets pressed it will scroll through a few
    pre programmed colors or animations, per press. Then that value is re-written into flash for the next time.
    Here is the code:
    // 5/10/14 // For controlling the Mandelbots ringLight WS2812 leds // Thanks to Kevin Timmerman for the ws2811_hs.asm led driver code // Written by Larry Fogg and Tim Toliver // #include "stdint.h" #include "stdlib.h" #include <msp430g2452.h> void write_ws2811_hs(uint8_t *data, unsigned length, uint8_t pinmask); //prototype for ws2811_hs.asm #define button BIT3 #define ledPin BIT7 #define numColors 1972 static const uint8_t red[12] = { 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00 }; static const uint8_t green[12] = { 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00 }; static const uint8_t blue[12] = { 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF }; static const uint8_t purple[12] = { 0, 128, 128, 0, 128, 128, 0, 128, 128, 0, 128, 128 }; static const uint8_t yellow[12] = { 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00 }; static const uint8_t orange[12] = { 0x80, 0xFF, 0x00, 0x80, 0xFF, 0x00, 0x80, 0xFF, 0x00, 0x80, 0xFF, 0x00 }; static const uint8_t steelBlue[12] = { 130, 70, 180, 130, 70, 180, 130, 70, 180, 130, 70, 180 }; static const uint8_t pink[12] = { 20, 255, 147, 20, 255, 147, 20, 255, 147, 20, 255, 147 }; static const uint8_t aqua[12] = { 255, 0, 255, 255, 0, 255, 255, 0, 255, 255, 0, 255 }; static uint8_t z[12]; //GRB values for 4 LEDs uint8_t pressCount; //keep track of button presses uint8_t buttonPressed = 1; //start with true so stored pressCount is executed //for writing flash uint8_t * Flash_ptr = (unsigned char *) 0x1040; //location to write in flash info segment C void millisecDelay(int delay) { int i; for (i=0; i<delay; i++) _delay_cycles(10000); //roughly 1 msec. calibrate this } #pragma vector=PORT1_VECTOR __interrupt void PORT1_ISR(void) { _disable_interrupts(); pressCount++; //increment button presses buttonPressed = 1; //true millisecDelay(300); //for button debounce P1IFG &= ~button; //clear interrupt flag _enable_interrupts(); } void writeFlash(unsigned char data){ _disable_interrupts(); FCTL1 = FWKEY + ERASE; //Set Erase bit FCTL3 = FWKEY; //Clear Lock bit *Flash_ptr = 0; //Dummy write to erase Flash segment FCTL1 = FWKEY + WRT; //Set WRT bit for write operation *Flash_ptr = data; //Write value to flash FCTL1 = FWKEY; //Clear WRT bit FCTL3 = FWKEY + LOCK; //Set LOCK bit _enable_interrupts(); } void loadLED (int ledNum, uint8_t R, uint8_t G, uint8_t //load z[] for one LED { z[ledNum*3]=G; z[ledNum*3+1]=R; z[ledNum*3+2]=B; } void writeLEDs () { _disable_interrupts(); write_ws2811_hs(z, sizeof(z), ledPin); _enable_interrupts(); } void getRGB(int color, uint8_t *R, uint8_t *G, uint8_t * //this generates RGB values for 1972 rainbow colors from red to violet and back to red { float brightness = 0.3; //scale factor to dim LEDs. if they are too bright, color washes out if (color>=(numColors/2)) //adjust color for return from violet to red color=numColors-color; if (color < 199) { *R = 255; *G = 56 + color; *B = 57; } else if (color < 396) { *R = 254 - (color - 199); *G = 255; *B = 57; } else if (color < 592) { *R = 57; *G = 255; *B = 58 + (color - 396); } else if (color < 789) { *R = 57; *G = 254 - (color - 592); *B = 255; } else { *R = 58 + (color - 789); *G = 57; *B = 255; } *R*=brightness; //apply brightness modification *G*=brightness; *B*=brightness; } void allWhite(uint8_t intensity) //all LEDs stay white { int i; for (i=0; i<12;i++) z[i] = intensity; writeLEDs(); } void allBlack() //all LEDs off (black) { int i; for (i=0; i<12;i++) z[i] = 0x00; writeLEDs(); } void lightning () { uint8_t R, G, B; int color; //numeric index into color palette int flashDuration; while (!buttonPressed) { allBlack(); //clear LEDs color = rand()%numColors; if (color%7==0) //every so often, throw in a bright white flash { R=G=B=0xff; flashDuration = 10; //quicker for white flash } else { getRGB (color, &R, &G, &; //get random color flashDuration = 50; //slower for color flash. makes color more apparent } loadLED (rand()%4, R, G, ; //load color into random LED writeLEDs(); //flash the LED millisecDelay(flashDuration); allBlack(); //clear LEDs millisecDelay(rand()%500); //wait for next flash } } void drawSnake (int headLoc) //draw snake starting at headLoc { int shoulderLoc, torsoLoc, tailLoc; uint8_t R, G, B; //color of head getRGB (rand()%numColors, &R, &G, &; shoulderLoc = (headLoc+1)%4; //find correct array locations for body parts. keep within 0-3 range torsoLoc = (headLoc+2)%4; tailLoc = (headLoc+3)%4; loadLED (headLoc, R, G, ; //random color head loadLED (shoulderLoc, 0, 0, 0); loadLED (torsoLoc, 0, 0, 0); loadLED (tailLoc, 0, 0, 0); //black tail writeLEDs(); //draw the snake } void chaseSnakeTail () //white head, black tail. Snake goes in circles { int headLocation=0; //which LED is the head (white) int crawlSpeed; //delay between snake moves int slowSpeed=150; int fastSpeed= 10; int CWdirection = 1; //start with clockwise direction = true while (!buttonPressed) { for (crawlSpeed=slowSpeed; crawlSpeed>fastSpeed; crawlSpeed-=2) //speed up tail chasing { drawSnake (headLocation); millisecDelay(crawlSpeed); if (CWdirection) headLocation +=3; else headLocation++; headLocation%=4; //keep LED in range (0-3) if (buttonPressed) break; } CWdirection = !CWdirection; //reverse direction for next cycle for (crawlSpeed=fastSpeed; crawlSpeed<slowSpeed; crawlSpeed+=2) //slow down tail chasing { drawSnake (headLocation); millisecDelay(crawlSpeed); if (CWdirection) headLocation +=3; else headLocation++; headLocation%=4; //keep LED in range (0-3) if (buttonPressed) break; } } } void allColors() //display rainbow color progression, each LED out of phase with the others { uint8_t R, G, B; int color; int ledNum; //0-3 while (!buttonPressed) for (color=0; color<numColors; color++) //progress from red to violet and back to red { for (ledNum=0; ledNum<4; ledNum++) { getRGB ((color+ledNum*200)%numColors, &R, &G, &; //offset LED colors by 200 from neighbors loadLED (ledNum, R, G, ; } writeLEDs(); millisecDelay(4); if (buttonPressed) //allow exit from function break; } } void writeLeds(const uint8_t color[12]) { unsigned j; for (j = 0; j < 12; j++) { z[j] = color[j]; write_ws2811_hs(z, sizeof(z), ledPin); } } void main(void) { WDTCTL = WDTPW + WDTHOLD; // No watchdog reset DCOCTL = 0; BCSCTL1 = CALBC1_12MHZ; // Run at 12 MHz DCOCTL = CALDCO_12MHZ; //P1SEL &= ~ledPin | button; P1DIR |= ledPin; // ledPin is an output P1OUT = 0; // set port 1 low P1DIR &= ~button; // button is an input P1REN |= button; // pull down on button P1OUT &= ~button; // set pull down P1IES &= ~button; // Interrupt Edge Select - 0: trigger on rising edge, 1: trigger on falling edge P1IFG &= ~button; // interrupt flag for p1.3 is off P1IE |= button; // enable interrupt FCTL2 = FWKEY + FSSEL_1 + FN3; // MCLK/32 for Flash Timing Generator 12mhz/32 = 375hz // these both work has to be between 257-476 hz //FCTL2 = FWKEY + FSSEL_1 + 0x1A; // MCLK/27 for Flash Timing Generator 12mhz/27 = 444hz pressCount = *Flash_ptr; // load value written in flash _enable_interrupts(); while (1) { if (buttonPressed) { buttonPressed = 0; //reset switch (pressCount) { case 0: //bright white allWhite(0x80); break; case 1: //dim white allWhite(0x40); break; case 2: lightning(); break; case 3: allColors(); break; case 4: chaseSnakeTail(); break; case 5: writeLeds(red); break; case 6: writeLeds(blue); break; case 7: writeLeds(green); break; case 8: writeLeds(purple); break; case 9: writeLeds(yellow); break; case 10: writeLeds(orange); break; case 11: writeLeds(steelBlue); break; case 12: writeLeds(pink); break; case 13: writeLeds(aqua); break; default: pressCount = 0; //default to 0 buttonPressed = 1; //force execution of case 0 break; } writeFlash(pressCount); // write to flash for poweroff } } } I didn't use any kind of level shifting for the leds. It seems alot of folks on here had no trouble getting the leds to
    work with out it, and I didn't read about the level shifting until after I sent off for the boards. So I got lucky on that one.
    For powering the the board I wanted to use the existing 12volt supply for the printer, so I put a couple of LDO's on
    board for that. I of course used TI parts that I sampled from TI. (as a matter of fact I sampled the msp430 too thanks TI!!!)
    For the 3.6 volt side I used the TPS70936 and for the 5 volt side I used the LP2989. Both of the LDO's are able according to
    the data sheets to handle a 12 volt input.The 3.6 volt side worked out as expected but I must have done something
    wrong with the LP2989. The data sheet says the part will provide up to 500mA continuously, the WS2812 at full brightness
    pulls 60mA. I put 4 leds on the board so thats 240mA if they are all full blast. When I have all the leds on full the LDO gets
    HOT! As far as the layout goes I copied the shematic from the data sheet, and used the recommended parts.
    This is from the datasheet:

    This is from my schematic:

    To get around a full redesign I don't push them that hard, and it works. It does bug me though, so if anyone has any
    insight or suggestions let me know. I have one more pcb I can hack on and see if I can make it work better.
    Besides that I am happy with the design and it fits the machine perfectly. (Just like it supposed to!)
    It's nice to see what I am printing.
    Here are a couple more photos , and some video.


  2. Like
    jsolarski reacted to Samartist in 4x4x4 LED cube, using 3 pins of MSP430 launchpad   
    This is my 4x4x4 led cube project, done with MSP430, using only 3 pins of MSP, the circuit diagram is shown in the photos, the hardware consists of 3 shift registers, 74595, and 4 NPN transistors...

    you can learn how to make a 4x4x4 LED cube by instructables or youtube or some other sites, its easy to make...
    but make sure that you make exact same connections as shown in the cicuit diagrams... or else this code won't work in the new hardware...

    the hardware can be built as shown in the circuit diagram...

    the code is given below, you can changes it and make your own animation with it....
    this is what i have done with the cube...

  3. Like
    jsolarski reacted to jazz in SBW MSP430F550x based programmer   
    This topic was some kind of progress report. I had long holidays between June and October, without topic related activity. I have list of functions that must be supported by flasher. There are two points left, fuse blow and customized BSL firmware update for flasher itself. Everything else is done, and I will not make any significant updates. At the end I will publish interface (flasher / PC - commands / data exchange) here together with source of PC side, and it will be very easy to integrate it in Energia, or make customized flasher on any OS. If anybody have topic related questions or some requests, we can discuss it here.
    Complete SBW+ development hardware is here... 

    On the left side are MSP430x5xx target boards. Two on the left top are MSP430F5435. On the right side are MSP430x2xx target boards. Two on right bottom are MSP430G2553 (with DIP sockets). In the middle are 2 MSP430F5510 boards with all pins available. Upper one is armed with SBW+ connectors to 8 target devices and it is used as main board for project development. Another one is flashed by BSL with last stable firmware version and it is used as SBW+ flasher to main board. All target boards have 5-pin SBW+ connection. At the bottom are 5-wire flat cables used for connection between programmer and target devices. SBW+ target device connection pinout is...
    PX.0 (X=1, 2, 3... J)
  4. Like
    jsolarski reacted to maelli01 in PWM glitches, Analog Write   
    now I can do fun things with PWM
    feed a 1kHz sine wave into Pin2, go through this shortish sketch:
    void setup() {analogFrequency(20000);} void loop()  {analogWrite(9,analogRead(2)/4);} look at the signal on pin 9, blue trace, low pass filtered yellow trace.
    With the new library: nice 1kHz PWMded sinewave on a 20Khz carrier!
    With the old library: garbage.
    the loop() runs with 6.8kHz, should be fast enough for very low quality audio

  5. Like
    jsolarski reacted to simpleavr in Simulating a TI calculator with crazy 11-bit opcodes   
    Yes, you can make it relatively easily and cheap. I ordered from Elecrow. They now have a 10 x 10 cm green pcb special. Mine is like 8.5 x 5 cm and it cost me less than $20 including shipping.
    Bubble led you can get from Sparkfun for a few dollars. Buttons, coin cell holder etc are all from ebay / DX.
    I am not a good PCB designer. The layout is done w/ Fritzing, but it is not clean (and it works though), in that I did not clean up the schematic. I just dived in a place my buttons and start traces.
    I will upload in a few days, do you prefer Fritzing format or a zip package that you can place Elecrow PCB order?
    The current layout is not perfect. I had reserved another 8 buttons (w/ a smaller CR1212 battery) so that I might emulate a MK14 or some other calculators that requires more buttons. But on second thought, I would just accept a 20 button layout in the next pcb design and move them all north a little bit. The fact is it is kind of difficult to use one hand to hold and press the lower buttons.
  6. Like
    jsolarski reacted to Atas in Anaren CC110L RF BoosterPack with msp430 launchpad as Chronos eZ430 Access Point   
    I loved the eZ430-Chronos.
    On the Internet many projects made ??on the basis of this development tool. But one thing I did not like is that you need a computer to manage their programs. And without a computer Chronos watch can not control anything. So I bought Anaren CC110L RF BoosterPack (868 Mhz).
    But this kit does not work with Chronos. I looked a lot of information and code on this forum and on the internet. But always something was wrong, I did not want to rewrite the SimpliciTi protocol. And finally... 
      I did emulation of RF USB dongle. The project uses the unmodified Chronos Control Centre and firmware of sportswatch. But blurobin and wireless firmware update does not work. To me, this part is not important. I used code composer studio. And now I have a working SimpliciTI on msp430g2553 with CC110L. And Run many examples which are in SimpliciTi installation directory.

    Here is a video how it works.

    Thanks to @gwdeveloper, with post SimpiciTI Tutorial for CC2500
    Project attached CCS SimpliciTI MSP430 CC110L Anaren busterpack.rar
  7. Like
    jsolarski got a reaction from GeekDoc in Im back   
    im back, been really busy with life and work. (the quick update, lost a job, got a job, had a baby, adopted a family, moved...etc, basicly went from me to having me and 4 others in my household)
    looks like I missed a lot. now time to catch up on all the new posts.......
  8. Like
    jsolarski got a reaction from pine in Im back   
    im back, been really busy with life and work. (the quick update, lost a job, got a job, had a baby, adopted a family, moved...etc, basicly went from me to having me and 4 others in my household)
    looks like I missed a lot. now time to catch up on all the new posts.......
  9. Like
    jsolarski got a reaction from trungkiena6 in Im back   
    im back, been really busy with life and work. (the quick update, lost a job, got a job, had a baby, adopted a family, moved...etc, basicly went from me to having me and 4 others in my household)
    looks like I missed a lot. now time to catch up on all the new posts.......
  10. Like
    jsolarski reacted to oPossum in request: ultrasonic example   
    #include <msp430.h>
    #include <stdint.h>
    static const unsigned long smclk_freq = 16000000UL; // SMCLK frequency in hertz
    static const unsigned long bps = 9600UL; // Async serial bit rate
    static uint32_t upd = 0; // Ultrasonic Pulse Duration (500 ns resolution)
    #pragma vector = TIMER1_A1_VECTOR // Timer 1A vectored interrupt
    __interrupt void timer1_a1_isr(void) //
    { //
    static uint32_t rise = 0; // Pulse rise time
    static uint32_t fall; // Pulse fall time
    switch(TA1IV) { // TA0IV must be read to reset interrupt
    case 0x02: // 0x02 == CCR1 (capture/compare)
    if(TA1CCTL1 & CCI) { // - Rising edge
    rise = TA1CCR1; // Save rise time
    fall = 0; // Reset fall time
    } else { // - Falling edge
    if(rise) { // Make sure rising edge has occurred
    // Handle possible pending overflow interrupt
    if((TA1CTL & TAIFG) && (TA1CCR0 < 0x1000))
    fall += TA1CCR0; //
    fall += TA1CCR1; // Get fall time, add to overflow time
    if(!upd) upd = fall - rise; // Update time if mainline code is ready for it
    rise = 0; // Clear rise time to ensure next rising edge is used
    } //
    } //
    break; //
    case 0x0A: // 0x0A == TAIFG (overflow)
    fall += TA1CCR0; // Update overflow time
    break; //
    } //
    } //
    void putc(const unsigned c) // Output single char to serial
    { //
    while(!(IFG2 & UCA0TXIFG)); // Wait for ready (not busy)
    IFG2 &= ~UCA0TXIFG; // Reset busy flag
    UCA0TXBUF = c; // Tx char
    } //
    void puts(const char *s) { while(*s) putc(*s++); } // Output string to serial
    void print_u32(uint32_t n, const unsigned dp) // Print 32 bit unsigned with optional decimal place
    // 6 decimal digits (0 -> 999999)
    { //
    unsigned c; //
    c = '0'; while(n >= 100000UL) n -= 100000UL, ++c; putc(c);
    if(dp == 5) putc('.'); //
    c = '0'; while(n >= 10000) n -= 10000, ++c; putc(c);
    if(dp == 4) putc('.'); //
    c = '0'; while(n >= 1000) n -= 1000, ++c; putc(c);
    if(dp == 3) putc('.'); //
    c = '0'; while(n >= 100) n -= 100, ++c; putc(c);
    if(dp == 2) putc('.'); //
    c = '0'; while(n >= 10) n -= 10, ++c; putc(c); //
    if(dp == 1) putc('.'); //
    c = '0'; while(n) --n, ++c; putc(c); //
    } //
    void main(void) //
    { //
    WDTCTL = WDTPW | WDTHOLD; // Disable watchdog reset
    DCOCTL = 0; // Run at 16 MHz
    BCSCTL1 = CALBC1_16MHZ; //
    P1DIR = BIT2; // Setup GPIO
    P1SEL = BIT1 | BIT2; // UART
    P1SEL2 = BIT1 | BIT2; //
    P2OUT = 0; //
    P2DIR = BIT0; // Timer 1 capture/compare IO
    P2SEL = BIT0 | BIT1; //
    P2SEL2 = 0; //
    const unsigned long brd = (smclk_freq + (bps >> 1)) / bps; // Bit rate divisor
    UCA0CTL1 = UCSWRST; // Hold USCI in reset to allow configuration
    UCA0CTL0 = 0; // No parity, LSB first, 8 bits, one stop bit, UART (async)
    UCA0BR1 = (brd >> 12) & 0xFF; // High byte of whole divisor
    UCA0BR0 = (brd >> 4) & 0xFF; // Low byte of whole divisor
    UCA0MCTL = ((brd << 4) & 0xF0) | UCOS16; // Fractional divisor, oversampling mode
    UCA0CTL1 = UCSSEL_2; // Use SMCLK for bit rate generator, release reset
    // Timer 1 compare 0
    TA1CCR0 = (16000000UL / (8 * 2 * 20)) - 1; // 20 Hz (50 ms)
    TA1CCTL0 = OUTMOD_4; // Toggle mode
    // Timer 1 capture 1
    TA1CCTL1 = CM_3 | SCS | CAP | CCIE; // Rising and falling, sync, capture, interrupt
    // Timer 1 config
    TA1CTL = TASSEL_2 | ID_3 | MC_1 | TAIE; // SMCLK, /8, count up, overflow interrupt
    _enable_interrupts(); // Enable interrupts
    for(; { // For-ever
    if(upd) { // Check for pulse duration measuement available
    // Calculate inches
    const uint32_t in = ((upd * 5534) + (upd >> 1)) >> 14;
    // Calculate mm
    const uint32_t mm = (upd * 5623) >> 16;
    print_u32(in, 2); // Print inches
    puts(" in "); //
    print_u32(mm, 0); // Print mm
    puts(" mm"); //
    puts("\r\n"); //
    upd = 0; // Ready for next
    } //
    } //
    } //

  11. Like
    jsolarski reacted to JBUKarl in MSP430 Quadrotor ***attempt***   
    Hello fellow bloggers!
    My name is Karl Anderson, I am a junior at John Brown University, studying electrical engineering. I have been working with a colleague, David Bird (also a junior EE major at JBU) on a quadrotor project for the past six weeks. Below you will find a table with the parts we used:
    5g Brushless Motors * 4
    Turnigy Plush ESC 6A * 4
    10DOF Sensor Board
    Zippy 800 maH LiPo
    TX & RX
    Frame Tubing
    (window screen tubing)
    MSP430G2553 LaunchPad
    3.3V Regulator
    20 Pin DIP Socket
    20 Pin IC Breakout
    10k? Resistors * 3
    Jumper Wires
        Paid Total
    Complete Total
    Key: Paid/Donated
    And their links if purchased online:
    Hobby King
     (Had the charger for this battery already)
    RX & TX:
    The inspiration and foundation of our project was from another blogger, thanhTran, and below is a link to his completed project. We could not have gone as far as we did without him.
    Our plan was first to use thanhTran
  12. Like
    jsolarski got a reaction from cde in PWM with WDT+   
    not a bad idea, once i have the servo code working i will ship it over your way.
    and here is the single led code, better commented too
    //options for interval timer/* WDT is clocked by fSMCLK (assumed 1MHz)
    WDT_MDLY_32 (WDTPW+WDTTMSEL+WDTCNTCL) 32ms interval (default)
  13. Like
    jsolarski got a reaction from cde in PWM with WDT+   
    Just a different way to create PWM on 3 pins, this code is for 3 leds or an RGB led
    changing the WDT interval will change how many cycles it will go through before calling an interrupt
    the PWM period can be changed by changing the value 200 on line 22 to what ever period you will need
    changing the led_ value is the duty cycle of the leds
    This code has not been streamlined, but it does do the job, updated code and limitation are going to be experimented with later this weekend, i am going to see how many servos LEDs i can hook up to it, max pins i can use is 9 pins, but that is using all pins possible........
    my test circuit

    FYI mspgcc code

    #include #include //add for interrupt #define UP 0x00 #define DOWN 0x01 volatile int millsecs = 0; volatile int counter2 = 0; volatile int led_red = 0; volatile int led_green = 199; volatile int led_blue = 199; volatile int dir = UP; void main(void) { WDTCTL = WDT_MDLY_0_064; P1DIR |= BIT5 + BIT4 + BIT3; P1OUT |= BIT5 + BIT4 + BIT3; IE1 |= WDTIE; eint(); }//end main interrupt(WDT_VECTOR) watchdog_timer(void) { ++millsecs; if (millsecs == 200) { millsecs= 0; P1OUT |= BIT0 + BIT6; ++counter2; } if (millsecs == led_red ) { P1OUT ^= BIT3; } if (millsecs == led_green) { P1OUT ^= BIT4; } if (millsecs == led_blue ) { P1OUT ^= BIT5; } if (counter2 == 25 ) { counter2 =0; switch (dir){ case UP: ++led_red; --led_green; --led_blue; if (led_red == 199) {dir = DOWN;} break; case DOWN: --led_red; ++led_green; ++led_blue; if (led_red == 0) {dir = UP;} break; }//end switch }//end if }//end interrupt
  14. Like
    jsolarski got a reaction from rampadc in Sample code for Rob's f5510 usb dev board   
    Printf from the forums,

    Main Clock runs at 8Mhz, in the end it will go into a while loop, printing "hello world" over and over again
    Tested and works

    //****************************************************************************** //****************************************************************************** #include <msp430f5510.h> #include "cust_def.h" #include "stdarg.h" void Uart_Init1(void); //***************************************************************************** /* Printf functions */ void Clk_Init(void); void putchar(unsigned char byte); void linesUp(unsigned char lines); int prints(char *string, unsigned char width, unsigned char pad); int printi(long int i, unsigned char b, unsigned char sg, unsigned char width, unsigned char pad, unsigned char letbase); int printf(char *format, ...); //***************************************************************************** /* printf defines */ #define PAD_RIGHT 0x01 #define PAD_ZERO 0x02 #define PRINT_BUF_LEN 12 //***************************************************************************** char *s; char c; int i; unsigned u; long int l; long unsigned n; unsigned x; void main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop WDT Clk_Init(); P4SEL = BIT5+BIT4; Uart_Init1(); __bis_SR_register( GIE); // Enter LPM3 printf("%s", "\r\n*** printf() test ***\r\n"); putchar(c); s = "test"; c = 'X'; i = -12345; u = 12345; l = -1234567890; n = 1234567890; x = 0xABCD; printf("String %s\r\n", s); __delay_cycles(250000); printf("Char %c\r\n", c); __delay_cycles(250000); printf("Integer %i\r\n", i); __delay_cycles(250000); printf("Unsigned %u\r\n", u); __delay_cycles(250000); printf("Long %l\r\n", l); __delay_cycles(250000); printf("uNsigned loNg %n\r\n", n); __delay_cycles(250000); printf("heX %x\r\n", x); __delay_cycles(250000); printf("multiple args %s %c %i %u %l %n %x\r\n", s, c, i, u, l, n, x); __delay_cycles(250000); printf("\r\n*** Done ***\r\n"); __delay_cycles(250000); while(1) { printf(" hello world ","\n"); __delay_cycles(250000); } __bis_SR_register(LPM0_bits + GIE); // Enter LPM3 __no_operation(); // For debugger } //********************************************************************************* void Clk_Init(void) { UCSCTL3 = SELREF_2; // Set DCO FLL reference = REFO UCSCTL4 |= SELA_2; // Set ACLK = REFO UCSCTL0 = 0x0000; // Set lowest possible DCOx, MODx // Loop until XT1,XT2 & DCO stabilizes - In this case only DCO has to stabilize do { UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG); // Clear XT2,XT1,DCO fault flags SFRIFG1 &= ~OFIFG; // Clear fault flags }while (SFRIFG1&OFIFG); // Test oscillator fault flag __bis_SR_register(SCG0); // Disable the FLL control loop UCSCTL1 = DCORSEL_5; // Select DCO range 16MHz operation UCSCTL2 |= 249; // Set DCO Multiplier for 8MHz // (N + 1) * FLLRef = Fdco // (249 + 1) * 32768 = 8MHz __bic_SR_register(SCG0); // Enable the FLL control loop // Worst-case settling time for the DCO when the DCO range bits have been // changed is n x 32 x 32 x f_MCLK / f_FLL_reference. See UCS chapter in 5xx // UG for optimization. // 32 x 32 x 8 MHz / 32,768 Hz = 250000 = MCLK cycles for DCO to settle __delay_cycles(250000); } //********************************************************************************* //init uart 1 void Uart_Init1(void) { UCA1CTL1 |= UCSWRST; // **Put state machine in reset** UCA1CTL1 |= UCSSEL_2; // SMCLK UCA1BR0 = 65; // 8MHz 9600 (see User's Guide) UCA1BR1 = 3; // 8MHz 9600 UCA1MCTL = UCBRS_2 + UCBRF_0; // Modln UCBRSx=0, UCBRFx=0, + UCOS16 // over sampling UCA1CTL1 &= ~UCSWRST; // **Initialize USCI state machine** //UCA1IE |= UCRXIE; // Enable USCI_A0 RX interrupt } //********************************************************************************* //printf source from http://forum.43oh.com/topic/396-getting-printf-working/page__hl__printf /*------------------------------------------------------------------- DESCRIPTION: Send one char in TX buffer, if it is not busy. Wait until not busy. INPUTS: One char. OUTPUTS: Send all the char in TX buffer. RETURNS: None. ---------------------------------------------------------------------*/ // Modify this routine so that it points to YOUR UART (zeke) void putchar(unsigned char byte) { while (!(UCA1IFG&UCTXIFG)); //while (!(IFG2 & UCA0TXIFG)); // USCI_A0 TX buffer ready? UCA1TXBUF = byte; // Load Tx register that clear UCA0TXIFG } /*------------------------------------------------------------------- DESCRIPTION: Move numbers of lines up in the HyperTerminal. INPUTS: None. OUTPUTS: Line up to TX buffer. RETURNS: None. ---------------------------------------------------------------------*/ void linesUp(unsigned char lines) { unsigned char i; for (i = 0; i < lines; ++i) { putchar(0x1b); putchar(0x5b); putchar(0x41); } } /*------------------------------------------------------------------- DESCRIPTION: Send out charater strings with defined width, justification and padding. Width = 0 or width < string length means unlimited width. Normal padding is space and left justification, but it can pad '0' or pad to the right side, depending on pad value. pad justification padding char bxxxxxx00 left ' ' bxxxxxx1x right ' ' or '0' bxxxxxxx1 left or right '0' INPUTS: Valid string and special charater in form of "\n" for example refered by pointer *string. Output field width. Justification and padding flag pad. OUTPUTS: Sent formated string to com port output. RETURNS: Total of chars sent. ---------------------------------------------------------------------*/ int prints(char *string, unsigned char width, unsigned char pad) { int pc = 0; unsigned char padchar = ' '; // The pading char is space normally if (width > 0) // If output width is defined { unsigned char len = 0; char *ptr; for (ptr = string; *ptr; ++ptr) ++len; // Calculate string length and put it in len if (len >= width) width = 0; // If string is longer than width, then width is not applicable define as zero else width -= len; // Else redefine width as padding spaces if (pad & PAD_ZERO) padchar = '0'; // If padding char is zero, then get padchar as zero ready instead of original space } if (!(pad & PAD_RIGHT)) // If not right padding - left justification { for (; width > 0; --width) // If ther is padding width. Output padding char as '0' or ' '. { putchar (padchar); ++pc; } } for (; *string ; ++string) // Output the full string { putchar (*string); ++pc; } for (; width > 0; --width) { // Write padding char to the right if normal left justification putchar (padchar); ++pc; } return pc; // Return the output char number } /*------------------------------------------------------------------- * DESCRIPTION: Print 32 bit signed interger in dec or hex. In specific * width, padding and justification using prints(). Use 12 byte buffer * which is enough for 32 bit int. * INPUTS: Up to 32 byte signed interger i. Counting base: 10 or 16. * Sign flag sg. Output string width. padding and justification flag. * Leter base for number conversion. * OUTPUTS: Sent formated interger as string to com port output. * RETURNS: Total of chars sent. ---------------------------------------------------------------------*/ int printi(long int i, unsigned char b, unsigned char sg, unsigned char width, unsigned char pad, unsigned char letbase) { char print_buf[PRINT_BUF_LEN]; // Interger as string array char *s; char neg = 0; unsigned long int t; unsigned long int u = i; int pc = 0; if (i == 0) // If output char is 0, then just output it with padding and width. { print_buf[0] = '0'; print_buf[1] = '\0'; // Always remenber to put string end return prints(print_buf, width, pad); //Print out zero and done. } if (sg && (b == 10) && (i < 0)) // If it is a negative int, then record the '-' and number as positive { neg = 1; u = -i; } s = print_buf + PRINT_BUF_LEN-1; // Point s to the end of the output buffer and put a null there. *s = '\0'; while (u) // Convert the positive int to string with whatever counting base, dec, or hex. { t = u % b; if( t >= 10 ) t += letbase - '0' - 10; *--s = t + '0'; u /= b; } if (neg) { // If it is a negative number if( width && (pad & PAD_ZERO) ) { // If there is width, right justified and pad with zero, output negative sign. putchar ('-'); ++pc; --width; } else *--s = '-'; // Otherwise put the '-' to string buffer. } return pc + prints (s, width, pad); // Output the string buffer and return the output counter. } /*------------------------------------------------------------------- * DESCRIPTION: short form of printf. Print argument strings with mixed * varables (string or interger)inside formated. * INPUTS: Argument string pointer. * OUTPUTS: print out the argument with style using prints() and printi(). * RETURNS: Total of chars sent. * Warning!!! varables and constant numbers even 0, must casted with * (long int)in printf(), if it is going to print out using * format "u", "d", "X" and "x"! Or the complier will assigned * 16-bit for data smaller than 16 bit and the argument pointer * will fetch a wrong 32-bit data and the argument point * increament will be in wrong size. * Limitations: 1) It treats all interger as 32 bit data only. * 2) No floating point data presentation. * 3) Has left/right alignment with 0 padding. * 4) Has format code "s", "d", "X", "x", "u" and "c" only. ---------------------------------------------------------------------*/ int printf(char *format, ...) { int width, pad; int pc = 0; char scr[2]; va_list args; va_start(args, format); for (; *format != 0; ++format) { if (*format == '%') { ++format; width = pad = 0; if (*format == '\0') break; if (*format == '%') goto out; if (*format == '-') { ++format; pad = PAD_RIGHT; } while (*format == '0') { ++format; pad |= PAD_ZERO; } for ( ; *format >= '0' && *format <= '9'; ++format) { width *= 10; width += *format - '0'; } if( *format == 's' ) { char *s = (char *)va_arg( args, int ); pc += prints (s?s:"(null)", width, pad); continue; } if( *format == 'd' ) { pc += printi (va_arg( args, long int ), 10, 1, width, pad, 'a'); continue; } if( *format == 'x' ) { pc += printi (va_arg( args, long int ), 16, 0, width, pad, 'a'); continue; } if( *format == 'X' ) { pc += printi (va_arg( args, long int ), 16, 0, width, pad, 'A'); continue; } if( *format == 'u' ) { pc += printi (va_arg( args, long int ), 10, 0, width, pad, 'a'); continue; } if( *format == 'c' ) { // char are converted to int then pushed on the stack scr[0] = (char)va_arg( args, int ); scr[1] = '\0'; pc += prints (scr, width, pad); continue; } } else { out: putchar(*format); ++pc; } } va_end( args ); return pc; } //#pragma vector=USCI_A1_VECTOR //__interrupt void USCI_A1_ISR(void) //{ //nop(); //}
  15. Like
    jsolarski reacted to yyrkoon in Code::Blocks + mspgcc how-to.   
    This how-to is primarily for Windows users. However, paths aside most of this information should be applicable for Linux users as well. Technically, this should also work with OSX.

    You will need Energia, and Code::Blocks. Plus a bit of time.

    In this how-to I will walk through setting up a toolchain for use with Code::Blocks, and when done showing how we can use the created project as a user defined template for future projects.

    Added Videos to youtube to help clarify some things I found confusing myself in this how to.


    First things first, we need to setup a directory where Code::Blocks expect to find the MSP430 toolchain. This is optional, but highly recommended as it will be less hassle to set everything up. So . . .

    1) Create directory C:\hightec

    2) Navigate to \hardware\tools and copy the msp430 directory to C:\hightec\

    3) Install code::blocks if not already installed. First time it is run the MSP430 toolchain
    should be detected.

    4) create a new project. -> select empty project. -> Click the go button.

    5) Name the project. the name is unimportant, but needed. First time code::blocks is run, you will have to
    tell it which directory projects are created in. click the next button.

    6) On this page, select "GNU GCC compiler for MSP430" from the compiler dropdown box, then select the finish button. code::blocks will complain, giving ~3 message boxes saying it does not how to setup various settings for the compiler.

    7) From the menu bar Select settings -> compiler.

    8) At the top again we need to select the compiler from the dropdown box. select "GNU GCC compiler for MSP430"

    9) Click the toolchain tab. below this should be yet another tab "Program files". Here the toolchain should already be autodetected. However. . .

    Compiler: -> msp430-gcc.exe
    C++ compiler: -> msp430-g++.exe
    linker for dynamic libs: -> msp430-gcc.exe
    linker for static libs: -> msp430-gcc.exe
    Make program: -> make.exe ( keep in mind Energia uses it's own build system, and has no make)

    10) Change to the Addtional paths tab. add -> C:hightec\msp430\msp430\include

    11) Change to the Compiler settings main tab -> other options tab -> add
    -c -g -Os -Wall -ffunction-sections -fdata-sections -mmcu=msp430g2553

    12) Switch to the linker settings tab -> in the other linker options text box add ->
    -Os -Wl,-gc-sections,-u,main -mmcu=msp430g2553

    13) Click the ok button on the bottom.

    14) From the menubar select project -> properties -> build targets. Uncheck the auto-generate filename extension. In the Output filename field change the output file name extension to elf.

    15) Click ok to save and exit the dialog.

    16) From the menubar select file -> new -> file C/C++ file -> go -> next -> Filename with full path: click the ... button, name the file -> click ok -> Select the All button -> and finally the finish button.

    Add . . .
    #include int main(){ return 0;}

    to main.c/cpp and save.

    17) From the menubar select build -> build. Output should be similar to . . .
    -------------- Build: Debug in msp430 (compiler: GNU GCC Compiler for MSP430)---------------msp430-g++.exe -c -g -Os -Wall -ffunction-sections -fdata-sections -mmcu=msp430g2553 -IC:\HighTec\Msp430\msp430\include -c main.cpp -o obj\Debug\main.omsp430-gcc.exe -LC:\HighTec\Msp430\msp430\lib\ldscripts\msp430g2553 -o bin\Debug\msp430.elf obj\Debug\main.o -Os -Wl,-gc-sections,-u,main -mmcu=msp430g2553 Output size is 6.44 KBProcess terminated with status 0 (0 minutes, 0 seconds)0 errors, 0 warnings (0 minutes, 0 seconds)

    18) From the menubar select file -> save project as template name the template and click ok.

    Now, when you create a new project...

    File -> New -> Project -> On the left select user templates. Violoa !

    Pretty sure mspdebug can be used in conjunction with this as well. However I am done with this for today, and will leave that for the next time.
  16. Like
    jsolarski reacted to mechg in PowerScope   
    43oh Store link   I found myself wanting a dedicated power monitor to use while developing battery-powered application circuits, so I built one using the MSP430G2402.    http://code.google.com/p/powerscope/   This device has already helped me identify and eliminate about 40% of the power usage of a project in-progress.   Right now, I just have the code as a zip file on the download tab, but if anyone wants to develop additional features, I can check the code into Subversion and create some branches.    The board can be ordered for about $12 (for 3 boards) by uploading the Eagle .brd file to http://www.oshpark.com I don't make any money from oshpark.   Greg Glenn
  17. Like
    jsolarski reacted to oPossum in 2^N for real numbers using integer math   
    When working with electronic music (MIDI synth and such) it is sometimes necessary to adjust pitch by units of octaves, semitones, or cents.
    An octave is a 2:1 ratio. So the ratio between any number of octaves is 2^N. This is a simple bit shift. Easy.
    A semitone is 1/12 of an octave (typically), so the ratio for that is 2^(N/12). A cent is 1/1200 of an octave, so the ratio for that is 2^(N/1200). Can't use bit shifting for that!
    The C stdlib provides the pow() function that can be used for these calculations, but it uses rather slow floating point math.
    This code will do it with relatively fast fixed point integer math. This code could easily be adapted to almost any base and exponent by changing the look-up tables. It uses the property of exponents that 2 ^ (1 + 2 + 4 + 8) == (2 ^ 1) * (2 ^ 2) * (2 ^ 4) * (2 ^ 8)
    // // 2 ^ (n / (1200 * 8192)) // // n = 1 / 8,192 cent //   = 1 / 819,200 semitone //   = 1 / 9,830,400 octave // // range of n: -134,217,727 to +78,643,199 //            = -13.65 to +7.99 octaves // // returned value is 8.24 fixed point // // + exponents in 8.24 format static const uint32_t etp[27] = {     0x01000001,                     // 00000001  1.0000000705     0x01000002,                     // 00000002  1.0000001410     0x01000005,                     // 00000004  1.0000002820     0x01000009,                     // 00000008  1.0000005641     0x01000013,                     // 00000010  1.0000011282     0x01000026,                     // 00000020  1.0000022563     0x0100004C,                     // 00000040  1.0000045127     0x01000097,                     // 00000080  1.0000090254     0x0100012F,                     // 00000100  1.0000180509     0x0100025E,                     // 00000200  1.0000361021     0x010004BB,                     // 00000400  1.0000722054     0x01000977,                     // 00000800  1.0001444161     0x010012EE,                     // 00001000  1.0002888530     0x010025DE,                     // 00002000  1.0005777895     0x01004BC1,                     // 00004000  1.0011559129     0x01009798,                     // 00008000  1.0023131618     0x01012F8B,                     // 00010000  1.0046316744     0x0102607D,                     // 00020000  1.0092848012     0x0104C6A1,                     // 00040000  1.0186558100     0x0109A410,                     // 00080000  1.0376596592     0x0113A513,                     // 00100000  1.0767375682     0x0128CC11,                     // 00200000  1.1593637909     0x01581889,                     // 00400000  1.3441243996     0x01CE81F4,                     // 00800000  1.8066704016     0x0343994D,                     // 01000000  3.2640579400     0x0AA77169,                     // 02000000  10.6540742354     0x71826157                      // 04000000  113.5092978129 }; // - exponents in 8.24 format static const uint32_t etn[27] = {     0x00FFFFFF,                     // 00000001  0.9999999295     0x00FFFFFE,                     // 00000002  0.9999998590     0x00FFFFFB,                     // 00000004  0.9999997180     0x00FFFFF7,                     // 00000008  0.9999994359     0x00FFFFED,                     // 00000010  0.9999988718     0x00FFFFDA,                     // 00000020  0.9999977437     0x00FFFFB4,                     // 00000040  0.9999954873     0x00FFFF69,                     // 00000080  0.9999909747     0x00FFFED1,                     // 00000100  0.9999819495     0x00FFFDA2,                     // 00000200  0.9999638992     0x00FFFB45,                     // 00000400  0.9999277998     0x00FFF689,                     // 00000800  0.9998556048     0x00FFED13,                     // 00001000  0.9997112304     0x00FFDA28,                     // 00002000  0.9994225441     0x00FFB455,                     // 00004000  0.9988454217     0x00FF68C1,                     // 00008000  0.9976921765     0x00FED1DC,                     // 00010000  0.9953896791     0x00FDA51C,                     // 00020000  0.9908006133     0x00FB4FC4,                     // 00040000  0.9816858552     0x00F6B582,                     // 00080000  0.9637071184     0x00EDC157,                     // 00100000  0.9287314100     0x00DCCF8E,                     // 00200000  0.8625420320     0x00BE7564,                     // 00400000  0.7439787570     0x008DB277,                     // 00800000  0.5535043908     0x004E6E13,                     // 01000000  0.3063671106     0x00180743,                     // 02000000  0.0938608065     0x0002415D                      // 04000000  0.0088098510 }; uint32_t tpow(int32_t n) {     const uint32_t *et = etp;           // Assume + exponent     if(n < 0) n = -n, et = etn;         // Adjust for - exponent                                         //     uint32_t r = 1L << 24;              // Init result to 1.0 in 8.24 format                                         //     do {                                //         if(n & 1) r = mul824(r, *et);   // Multiply by exponent if lsb of n is 1         ++et;                           // Next exponent     } while(n >>= 1);                   // Next bit, loop until no more 1 bits                                         //     return r;                           // Return result }
  18. Like
    jsolarski got a reaction from nmayo in Hi from the Fair Haven, NY   
    Welcome to the forums.
  19. Like
    jsolarski reacted to Rickta59 in msp430-gcc 4.6.3 signed overflow questions   
    I was looking for a quick test for a print format routine and came up with that. I see now that it is undefined behavior and can't be relied on. However, with that said, I'm going to provide code to other people who will surely abuse it. At least, I have an answer to their future questions.
  20. Like
    jsolarski reacted to H3rv3 in TLS3008 RGB Leds on Launchpad   
    I bought some addressable RGB Leds from Dealextreme and instead of the expected WS2801 chip, they came with TLS3008 drivers (8bit control for each colour, single wire, different protocol from WS2811 too).
    It took some time with the osciloscope to get the timing right but this now works perfect. This is in C rahter than assembly but I can get a decent update rate. I do not work with the full 50 Leds as there is not enough RAM in the chip I use (2231) but I tried looping the code to work with the full length, that worked ok except on one set of Leds which was sometimes lagging, I think that this is due to the extra time used by the loop when returning. If all the RGB data is in a table there should be no issue. I will check this when I have a better chip.
    I am making a kind of light organ - vu meter mix with a short string of 6  Leds and the update on the audio is faster than I need.
    This is compiled with IAR.
    Any comments and improvements welcome!
    // TLS3008 based 6 RGB LEDs string test application for MSP430 // Based on DonJuanito99 for arduino //THIS IS THE WORKING CODE // includes #include "msp430g2231.h" #include "intrinsics.h" // defines #define PULSEUS1 33 // Manchester half period in clock cycles (2.5us) to 1 #define PULSEUS0 22 // Manchester half period in clock cycles (2.5us) to 0 #define PULSEUS2 9 // used for end of command last 0 delay #define EOSYNCDELAYMS 50750 // Pause duration at end of SYNC frame (3.5ms) #define EORESETMS 29000 // Pause duration at end of RESET frame (2ms) #define EOFDELAYMS 5000 // Pause duration at end of each frame (of 50 LEDs RGB data) (0.35ms) #define UP 0x00 #define DOWN 0x01 #define HOLD 0x02 // variables //all reds //unsigned char RGBTable [18]={0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00}; //one color each //unsigned char RGBTable [18]={0xFF,0x00,0x00,0x0F,0x00,0x0F,0x00,0x00,0xFF,0x00,0x0F,0x0F,0x00,0xff,0x00,0x0f,0x0F,0x00}; //all off unsigned char RGBTable [18]; int i; int bc; char led_red = 1; char led_green = 255; char led_blue = 1; char red = UP; char blue = HOLD; char green = DOWN; // routines void reset(void); // sends reset frame void sync(void); // sends sync frame void frame_start(void); // sends emty data frame (last bit, out of procedure delay) void updateRGB (void); // sends the data to the leds void bitc(char); // bit sending procedure to send commands void bitd(char); // bit sending procedure to send data void main(void) { //pin setup output and 0 P1DIR |= BIT0; P1OUT &= ~BIT0; //Stop watchdog timer WDTCTL = WDTPW + WDTHOLD; //Set clock at 16MHz DCOCTL = DCO0 + DCO1; BCSCTL1 = RSEL0 + RSEL1 + RSEL2 + RSEL3; //Disable interupts __disable_interrupt(); // initialising strings reset(); sync(); reset(); sync(); reset(); sync(); while(1) { // reset(); // not required in this loop, consider regular reset // sync(); // not required in this loop, consider regular re-sync // send the data to the string updateRGB(); // the code below is just for the show while (P1IN & BIT3) {} //fade logic switch (red){ case UP: ++led_red; if (led_red == 255) {red = DOWN; green = HOLD; blue = UP; led_green=0;} break; case DOWN: --led_red; if (led_red == 0) {red = HOLD;} break; case HOLD: break; }//end switch switch (blue){ case UP: ++led_blue; if (led_blue == 255) {blue = DOWN; green = UP; red = HOLD;led_red=0;} break; case DOWN: --led_blue; if (led_blue == 0) {blue = HOLD;} break; case HOLD: break; }//end switch switch (green){ case UP: ++led_green; if (led_green == 255) {green = DOWN; red = UP; blue = HOLD;led_blue=0;} break; case DOWN: --led_green; if (led_green == 0) {green = HOLD;} break; case HOLD: break; }//end switch RGBTable [0]=led_red; RGBTable [1]=led_green; RGBTable [2]=led_blue; RGBTable [3]=led_blue; RGBTable [4]=led_green; RGBTable [5]=led_red; RGBTable [6]=led_red; RGBTable [7]=led_blue; RGBTable [8]=led_green; RGBTable [9]=led_blue; RGBTable [10]=led_red; RGBTable [11]=led_green; RGBTable [12]=led_green; RGBTable [13]=led_blue; RGBTable [14]=led_red; RGBTable [15]=led_green; RGBTable [16]=led_red; RGBTable [17]=led_blue; } //end while } // end main() void updateRGB(void) // send the RGBTable data to the string { frame_start(); // prepare to send data __delay_cycles (PULSEUS0-4); for(i=0;i<18;i++) // Repeat for 6 leds * 3 data blocks { // Start tag (= 0 bit) P1OUT &= ~BIT0; // set to 0 __delay_cycles(PULSEUS1); P1OUT |= BIT0; //set to 1 __delay_cycles(4); for (bc=0x80;bc!=0;bc>>=1) bitd( RGBTable[i] & bc ); // send the 8 data bits __delay_cycles (6); } P1OUT &= ~BIT0; __delay_cycles (EOFDELAYMS); //pass value from chip to LED (=send a complete frame start) frame_start(); __delay_cycles (PULSEUS1-3); P1OUT &= ~BIT0; // write a low __delay_cycles (EOFDELAYMS); } void bitd(char { if (b==0){ P1OUT &= ~BIT0; // set to 0 __delay_cycles(PULSEUS1); P1OUT |= BIT0; //set to 1 __delay_cycles (4); } else{ P1OUT |= BIT0; // set to 1 __delay_cycles(PULSEUS1); P1OUT &= ~BIT0; //set to 0 __delay_cycles (4); } } void bitc(char { if (b==0){ P1OUT &= ~BIT0; // set to 0 __delay_cycles(PULSEUS1); P1OUT |= BIT0; //set to 1 __delay_cycles (PULSEUS0); } else{ P1OUT |= BIT0; // set to 1 __delay_cycles(PULSEUS1); P1OUT &= ~BIT0; //set to 0 __delay_cycles (PULSEUS0); } } void sync() { bitc(1); bitc(1); bitc(1); bitc(1); bitc(1); bitc(1); bitc(1); bitc(1); bitc(1); bitc(1); bitc(1); bitc(1); bitc(1); bitc(1); bitc(1); bitc(0); bitc(0); bitc(0); bitc(1); bitc(0); bitc(0); bitc(0); bitc(0); bitc(0); bitc(0); bitc(0); bitc(0); bitc(0); bitc(0); bitc(0); __delay_cycles (PULSEUS2); // additional delay on last 0 P1OUT &= ~BIT0; // now set to 0 __delay_cycles (EOSYNCDELAYMS); // end of sync frame delay } void reset() { bitc(1); bitc(1); bitc(1); bitc(1); bitc(1); bitc(1); bitc(1); bitc(1); bitc(1); bitc(1); bitc(1); bitc(1); bitc(1); bitc(1); bitc(1); bitc(0); bitc(1); bitc(0); bitc(0); __delay_cycles (PULSEUS2); // additional delay on last 0 P1OUT &= ~BIT0; // now set to 0 __delay_cycles (EORESETMS); // end of reset frame delay } void frame_start() { bitc(1); bitc(1); bitc(1); bitc(1); bitc(1); bitc(1); bitc(1); bitc(1); bitc(1); bitc(1); bitc(1); bitc(1); bitc(1); bitc(1); bitc(1); bitc(0); bitc(0); bitc(1); P1OUT &= ~BIT0; __delay_cycles(PULSEUS1+9); P1OUT |= BIT0; //set to 1 // last 0 bit has no delay (delay will be set outside due to procedure return delays) }  
  21. Like
    jsolarski reacted to tripwire in Embedding breakpoints in C code   
    Since I started programming for MSP430 I've been looking for the MSP equivalent of "__asm int 3" (aka DebugBreak). I've come up with this fragment, tested on CCS 5.3.0:
    #ifndef NDEBUG // If debugger is attached and software breakpoints are enabled, DEBUG_BREAK will pause execution #define DEBUG_BREAK _op_code(0x4343) #else // Strip out DEBUG_BREAKs in final/release builds #define DEBUG_BREAK #endif  
    Put this in a header file and you can then embed breakpoints in your code with a DEBUG_BREAK; statement. To reiterate what it says in the comment above: DEBUG_BREAK only halts if the debugger is attached and software breakpoints are enabled!
    For an example of where it's useful, consider the DCO calibration constants check used in a lot of example programs:
    if(CALBC1_1MHZ == 0xFF || CALDCO_1MHZ == 0xFF) // Check calibration constants weren't erased { DEBUG_BREAK; // Halt program (if debugger is connected) while(1); // Loop forever (as a backup) to prevent use of erased calibration data }  
    As it normally appears (without the DEBUG_BREAK) the CPU just enters an infinite loop if the calibration data is missing. You have to notice that the program isn't progressing and manually pause to see what the problem is. With the addition of a DEBUG_BREAK the program pauses immediately so you can see what went wrong!
    They're handy for use in trap ISRs, to pause when an unexpected interrupt fires so you can find out what caused it. In that case you may want to leave out the infinite loop so the program can be resumed afterwards. They're useful for general debugging too, since embedding breakpoints like this has some advantages over breakpoints set in the debugger. More on that later...
    To understand how it works you need to know some details about how hardware and software breakpoints work. Time for a crash-course in breakpoints
    Placing a hardware breakpoint tells the MSP's Embedded Emulation Module (EEM) to halt the CPU whenever an instruction is fetched from the breakpoint's address. The EEM contains trigger modules that spy on the address and data buses inside the chip, and fire when they see a specified value. Once the trigger is set up the MSP runs code as normal until the trigger fires, which makes the EEM halt the CPU and stop all the clocks. This is great because it means hardware breakpoints don't mess up the internal state of the MSP. Unfortunately the EEM has a limited number of triggers (just 2 on the value-line chips), so you can only have two breakpoints!
    Software breakpoints work around that limitation by using one of the EEM triggers in a different way. Instead of halting when an instruction is fetched from a specific address, it halts when a specific instruction is fetched from any address. That means you can have as many breakpoints as you like, as long as they're all on the same instruction opcode. The debugger uses 0x4343 (a type of NOP) as its breakpoint opcode. When you place a software breakpoint the debugger first makes a record of the original opcode at that address. Then it overwrites it with 0x4343 in the MSP's flash memory. As before, the MSP runs code as normal until the trigger module detects an instruction fetch of the 0x4343 opcode. The EEM halts the CPU and stops the clocks. Now the debugger has to restore the opcode that it overwrote earlier and make sure it's the next instruction to execute. After you step or resume it needs to put the breakpoint opcode back again, assuming you didn't disable it in the meantime.
    All this writing to flash has an overhead, and the bad news is that the clocks need to be restarted during the process. That means that setting and hitting software breakpoints can make the on-chip timer peripherals go haywire.
    DEBUG_BREAK makes use of the debugger's trigger setup for software breakpoints, but it doesn't require any runtime flash memory overwrites. The breakpoint is entirely handled by the MSP's EEM like a hardware breakpoint, but you can have as many as you like. The only disadvantage is that you need to rebuild to move them ;-)
  22. Like
    jsolarski reacted to RobG in DMX code examples   
    Time for the receiver.
    Again, very simple code, receives 3 consecutive channels and stores the values in the array. 
    Received values can then be used as PWM values to drive RGB LED.
    #include "msp430g2553.h" typedef unsigned char u_char; typedef unsigned int u_int; #define DMX_IN_PIN BIT1 void configMSP(); u_char data[3] = { 0, }; // u_char dataCounter = 0; u_char ucaStatus = 0; u_char rxData = 0; #define DMX_IDLE 0 #define DMX_BREAK 1 #define DMX_START 2 #define DMX_READY 3 #define DMX_RECEIVE 4 u_char dmxStatus = 0; u_char dmxDataReady = 0; u_int dmxChannel = 1; u_int dmxLength = 3; u_int dmxCounter = 0; void main(void) {     WDTCTL = WDTPW + WDTHOLD;     configMSP();     while (1) {     } } void configMSP() {     // DCO     BCSCTL1 = CALBC1_16MHZ;     DCOCTL = CALDCO_16MHZ;     P1SEL |= DMX_IN_PIN;     P1SEL2 |= DMX_IN_PIN;     UCA0CTL0 |= UCSPB; // 2 stop bits     UCA0CTL1 |= UCSSEL_2 + UCRXEIE + UCBRKIE;     UCA0BR0 = 0x40; // 16MHz/64 = 250k     UCA0BR1 = 0;     UCA0MCTL = 0;     UCA0CTL1 &= ~UCSWRST;     IE2 |= UCA0RXIE;     _bis_SR_register(GIE); } #pragma vector=USCIAB0RX_VECTOR __interrupt void USCI0RX_ISR(void) {     ucaStatus = UCA0STAT;     rxData = UCA0RXBUF;     if (ucaStatus & UCBRK) {         dmxStatus = DMX_BREAK;         ucaStatus = 0;         dmxCounter = 0;         dataCounter = 0;     } else {         switch (dmxStatus) {         case DMX_IDLE:             break;         case DMX_BREAK:             if (rxData == 0) {                 dmxStatus = DMX_START;             } else {                 dmxStatus = DMX_IDLE;             }             dmxCounter++;             break;         case DMX_START:             if (dmxCounter == dmxChannel) {                 dmxStatus = DMX_RECEIVE;             } else {                 dmxCounter++;                 break;             }         case DMX_RECEIVE:             data[dataCounter] = rxData;             dataCounter++;             if (dataCounter == dmxLength) {                 dmxStatus = DMX_IDLE;                 dmxDataReady = 1;                 break;             }             dmxCounter++;             break;         }     } }
  23. Like
    jsolarski got a reaction from Advane Harshal in Hello World from india   
    Are you a zombie? lol Cause I am sort of partial to my brain.
    Welcome to the forums!!
  24. Like
    jsolarski reacted to GG430 in Sundial - Kids Clock with LEDs   
    In the past few month our older daughter woke up in the middle of the night once in a while. She didn't know whether it was late enough to get up and ready for Kindergarten. So she woke my wife and myself up and asked. Bad idea...
    I needed a solution for her without the need to read the clock. So I decided to build the "Sundial" clock for her 4th birthday. Well this idea came up maybe 2 month before her birthday. This brought me under pressure to complete it, but I had a good plan and it was ready the day before her birthday.

      It's driven by a MSP430G2553. It has one LED for the moon and one for the sun. The twelve LEDs for the clock are charlieplexed to four pins. The plexiglass is called endlighten and has some particles in it to enlight the entire area of the glass and not only the edges.
    The clock is off all the time. From 7am to 8am the sun and clock are on. From 6 to 7pm the moon and clock are on.
    Beside the moon is a capacitive sensing area behind the wood. It's just one button and turns on the clock and depending on the time 7am - 6pm the sun and 6pm - 7am the moon for 30 seconds.
    The video shows a bit of the details.

  25. Like
    jsolarski reacted to yyrkoon in Simple Serial ( minimal ? ) debugging.   
    Yes, I was looking at your post, and oPossum's for same related material. It bothers me to hard code things like this, *but* this keeps it simple, and short.
    However, what does your ASM debugger have to do with being simple ?   oPossum already wrote assembly source for printf() to use uart output mentioned on the Tiny printf() page.
    What I have here, is meant more as beginner learning code, that just so happens to provide some useful functionality.
  • Create New...