Jump to content
43oh

Rickta59

Members
  • Content Count

    1,135
  • Joined

  • Last visited

  • Days Won

    71

Reputation Activity

  1. Like
    Rickta59 reacted to ike in Serial Fun   
    Q. What is that?
    A. It's "Serial Fun", a serial LCD using msp430g2211, HD44780 and one resistor.
     
    Q. Why are you doing this, there are many serial LCD on the market?
    A. I don't like them. Using PIC16F88 or ATmega for display and using cheap and low power msp430G2xxx for main CPU is just plain stupid.
     
    Q. SparkFun's serial LCD looks better!
    A. Yes, you are right. But it cost $24.95 and have to wait for shipping. You may have cheap 16x2 LCD module form ebay for $3.20 and extra MCU msp430g2211, that comes with LaunchPad, so you can have serial LCD right now and is more cheap.
     
    Q. $3.20 for serial LCD? OK, where is the catch?
    A. There is no catch. You just need piece of perfboard, 12 pin male header, 1800 Ohm resistor, little bit of wire and LCD module itself.
     
    Q. Schemes in source code and on the picture are different.
    A. Yes. Scheme in the source code is how to connect stand alone msp430g2211 to LCD and on the picture is how to connect LaunchPad to LCD.
     
    Q. Your pictures are crap.
    A. Yes. I like to work at night and my camera is not so great at artificial lighting. I'll make better pictures and will post it here, but I suggest anyone who has spare LCD module and LaunchPad to assemble this easy project and post picture of it.
     
    Q. Why are you using 1800 Ohm resistor instead of 10k pot?
    A. Because when you adjust the pot it's resistance will be 1800 Ohm. I know it's value depends of supply volgate, temperature and manufacturer, but most cheap negative LCD modules needs 1800 Ohm resistor.
     
    Q. How do you power 5.0V LCD module?
    A. From Test Point 1, tag as TP1 near USB connector.
     
    Q. What if I have 3.3V LCD module?
    A. Power it form pin 1 VCC on the LaunchPad.
     
    Q. You connected BackLight without resistor, it will burn in flames.
    A. On cheap LCD modules there is internal 100 Ohm resistor on module connected in series with LED, so it will not burn.
     
    Q. You did not turn-off BackLight because Pin 3 (P1.1) goes to 3.6V not 5.0V, so there is 1.4V voltage when it should be 0V
    A. White LED will not turn-on 1.4V.
     
    Q. You are torturing Pin 3 (P1.1) forcing it to sink so much current.
    A. It will be OK.
     
    Q. It is time for code review. I don't like your code.
    A. You have the source and you are free to improve it. I think that is great project, that will be useful for most of 43ohers and if
    you can make it better is good for all of us.
     
    Q. I don't like 9600 Baud connection speed.
    A. If you could set DCOCLK to 16MHz and use BCSCTL1, DIVAx Bits 5-4 (Divider for ACLK) to run it at 19200, 38400, 76800 and 153600 bps.(not tested but should be OK)
     
    Q. No I wish slower speed.
    A. OK. Change this 2 lines
    104 and 208 will give you 4800bps.
    208 and 416 will give you 2400bps.
    416 and 832 will give you 1200bps and so on...
     
    Q. How can I control it?
    A. Just use terminal emulator on your computer, you can use another LaunchPad or stand alone MCU to send serial data to Pin 4 (P1.2). Tiny printf() - C version is a good example how to send data to serial LCD.
     
    Q. You don't use delay after each LCD write.
    A. You are right. 9600 bps is so slow and modern LCD are more faster than ones manufactured by Hitachi 30-40 years ago. If you wish you could add some delays here and there.
     
    Q. What about if I have different LCD module like 4x20, not default one 2x16?
    A. All standard character LCD modules are supported including 1x8, 2x8, 1x16, 2x16, 2x20, 2x24, 4x16, 4x20.
     
    Q. How?
    A. One character which look like space is sacrificed as escape code, just like SparkFun's serial LCD. 0xFE or 254 is interpreted as magical symbol, next symbol is send to LCD as a command, except for 0b 001x xxxx which will change operation mode of LCD module and it will stop working.
    To send 0xFE or 254 character in Windows OS, turn on NumLock, hold Alt key and type on the NumPad 254 and then release Alt key.
    254 and 0 does nothing.
    254 and 1 Clears Display and set DDRAM address to 0.
    254 and 2 or 3 Sets DDRAM address 0 in address counter. Also returns display from being shifted to original position. DDRAM
    contents remain unchanged.
    254 and 4 to 7 Sets cursor move direction and specifies display shift.
    254 and 8 to 15 Sets entire display (D) on/off, cursor on/off ©, and blinking of cursor position character (.
    254 and 16 to 31 Moves cursor and shifts display without changing DDRAM contents.
    254 and 32 to 43 is where fun begins.
    Look at this table
    For example
    254 and 32 is BackLight on, 2 lines, Address (0-15,64-79,16-31,80-95), Rows 16.
    254 and 48 is BackLight off, 2 lines, Address (0-15,64-79,16-31,80-95), Rows 16.
    254 and 46 is BackLight on, 4 lines, Address (0-19,64-83,20-39,84-103), Rows 20.
    254 and 62 is BackLight off, 4 lines, Address (0-19,64-83,20-39,84-103), Rows 20.
     
    Some of the values are invalid like 4 lines, 24 rows is not valid combination, there is no such display. Most common LCD modules 1x16 are actuality 2 lines, 8 rows.
     
    254 and 64 to 127 Sets CGRAM address. CGRAM data is sent and received after this setting. Address 0 of CGRAM for custom graphics.
    254 and 128 or bigger is equivalent to 254 and 1 Clears Display and set DDRAM address to 0.
     
    Q. Custom characters?
    A. 1.hold Alt key and type on the NumPad 8 and then release Alt or ctrl+@.
    2.hold Alt key and type on the NumPad 1 or 9 and then release Alt or ctrl+a.
    3.hold Alt key and type on the NumPad 2 and then release Alt or ctrl+b.
    4.hold Alt key and type on the NumPad 3 or 11 and then release Alt or ctrl+c.
    5.hold Alt key and type on the NumPad 4 or 12 and then release Alt or ctrl+d.
    6.hold Alt key and type on the NumPad 5 and then release Alt or ctrl+e.
    7.hold Alt key and type on the NumPad 6 or 14 and then release Alt or ctrl+f.
    8.hold Alt key and type on the NumPad 7 or 15 and then release Alt or ctrl+g.
     
    Q. OK, but how can I edit them?
    A. Best way is to send Alt+254 and then Alt+64. Now send 8x8 bytes and your CGRAM will be programed. Now send Alt+254 and then Alt+1 to switch back to text mode.
     
    Q. I want to edit individual custom characters(CC).
    A.
    Alt+254,Alt+64, 8 bytes,Alt+254, Alt+1 for CC#1
    Alt+254,Alt+72, 8 bytes,Alt+254, Alt+1 for CC#2
    Alt+254,Alt+80, 8 bytes,Alt+254, Alt+1 for CC#3
    Alt+254,Alt+88, 8 bytes,Alt+254, Alt+1 for CC#4
    Alt+254,Alt+96, 8 bytes,Alt+254, Alt+1 for CC#5
    Alt+254,Alt+104, 8 bytes,Alt+254, Alt+1 for CC#6
    Alt+254,Alt+112, 8 bytes,Alt+254, Alt+1 for CC#7
    Alt+254,Alt+120, 8 bytes,Alt+254, Alt+1 for CC#8
     
     
    New version ver 0.03, now with less bugs, but with more butterflys!
     

    // msp430g2211 LCD HD44780 White BL // +-----------------+ +------------------+ // | VCC |-+-- 3.6V TP1 5.0V-+---|2. VDD/VCC | // | RST |-+ +---|15. A------>|--+ | // | | | | | // | TEST |-----X +-|5. R/W | | // | GND |---- GND-+------------+-|1. VSS/GND | | // | | +-[~~1.8K~~]---|3. VO | | // | | | | | // | P1.0 |----------------------->|4. RS | | // | P1.1 |----------------------->|16. K-[~100~]- + | // | RXD/P1.2 |<-------- 9600 8N1 | | // | P1.3 |----------------------->|6. Enable | // | P1.4 |----------------------->|11. DB4 | // | P1.5 |----------------------->|12. DB5 | // | P1.6 |----------------------->|13. DB6 | // | P1.7 |----------------------->|14. DB7 | // | | | | // | | X----|7. DB0 | // | | X----|8. DB1 | // | | X----|9. DB2 | // | | X----|10. DB3 | // | | | | // | | | | // +-----------------+ +------------------+ // // // // // // // //ver 0.03 //****************************************************************************** #include "msp430g2211.h" #include "stdint.h" //The one true int //------------------------------------------------------------------------------ // Hardware-related definitions //------------------------------------------------------------------------------ #define LCDDataMode BIT0 // LCD RS DataMode #define LCDBackLight BIT1 // LCD BackLight #define UART_RXD BIT2 // RXD on P1.2 (Timer0_A.CCI1A) #define LCDEnable BIT3 // LCD Enable //------------------------------------------------------------------------------ #define toggle P1OUT|= LCDEnable;__no_operation();P1OUT&= ~LCDEnable; // toggle,toggle on the wall #define MAGIC 0xFE //do you belive in magic? //------------------------------------------------------------------------------ // Conditions for 9600 Baud SW UART, SMCLK = 1MHz //------------------------------------------------------------------------------ #define UART_TBIT_DIV_2 52 //(1000000 / (9600 * 2)) #define UART_TBIT 104 //(1000000 / 9600) //------------------------------------------------------------------------------ // Global variables used for UART RX //------------------------------------------------------------------------------ uint8_t rxBuffer; // Received UART character //------------------------------------------------------------------------------ // main() //------------------------------------------------------------------------------ void main(void) { //1. Stop watchdog WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer //2. Set DCOCLK to 1MHz if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF){ _bis_SR_register(LPM4_bits); // If calibration constant is erased, TRAP! } //Set DCOCLK to 1MHz BCSCTL1 = CALBC1_1MHZ; // Set range DCOCTL = CALDCO_1MHZ; // Set DCO step + modulation //3. Initialize all GPIO P1OUT = 0x00; // Initialize all GPIO P1SEL = UART_RXD; // Timer function for RXD pins P1DIR = 0xFF & ~UART_RXD; // Set all pins but RXD to output P2OUT = 0x00; P2SEL = 0x00; P2DIR = 0xFF; //4. LCD Init //wait 0.5 seconds for LCD VCC+ to rise __delay_cycles(500000); // 0.5 seconds //4-bit Interface Mode Samsung 6a0069 // 4-bit mode, 5x8, 1/16 duty, 2 lines, display off P1OUT= 0x20; //4-bit mode toggle toggle P1OUT= 0x80; //operational mode: 5x8, 1/16 duty, 2 lines, display off toggle __delay_cycles( 50 ); //////////////////////////////////////////////// //display on P1OUT= 0x00; // toggle P1OUT= 0xC0; // toggle __delay_cycles( 1600 ); /////////////////////////////////////////////////// //display clear P1OUT= 0x00; // toggle P1OUT= 0x10; // toggle __delay_cycles( 1600 ); ///////////////////////////////////////////////// //Entry Mode Set: Increment mode, Entire shift off P1OUT= 0x00; // toggle P1OUT= 0x60; // toggle ////////////////////////////////////////////////// //5. TimerA_UART_init TACCTL1 = SCS + CM1 + CAP + CCIE; // Sync, Neg Edge, Capture, Int TACTL = TASSEL_2 + MC_2; // SMCLK, start in continuous mode uint8_t x=0; //current x uint8_t y=0; //current y uint8_t lines=2; //most common LCD 16x2 uint8_t rows=16; uint8_t CGRAMmode=0; //on boot write to DDRAM uint8_t address=16; //Address of third line uint8_t CommandFlag=0; //CommandFlag uint8_t BackLight=0; //0 means BackLight ON, 2 means BackLight OFF __enable_interrupt(); // Main loop for (; { // Wait for incoming character __bis_SR_register(LPM0_bits);// Go to bed. if(CommandFlag==1){ CommandFlag=0; if((rxBuffer|0x1F)==0x3F){ //0b 001x xxxx is really funny command, outlaw it! //setup //BIT4 - BackLight: 1 = off, 0 = on //BIT3 - Lines: 1 = 4 lines, 0 = 2 lines //BIT2 - Address: 1 = (0-19,64-83,20-39,84-103), 0=(0-15,64-79,16-31,80-95) //BIT1&BIT0 - Rows 00=16, 01=8, 10=20, 11=24 if((rxBuffer&BIT4)==BIT4) {BackLight=LCDBackLight;P1OUT|=LCDBackLight;} //BackLight OFF else {BackLight=0;P1OUT&=~LCDBackLight;} //BackLight ON if((rxBuffer&BIT2)==BIT2) address=20; //20x2, 20x4, 24x2 else address=16; //16x2, 16x4 if((rxBuffer&BIT3)==BIT3) lines=4; //lines=4 else lines=2; //lines=2 switch(rxBuffer & 0x03){ //rows case 0x00: rows=16; break; case 0x01: rows=8; break; case 0x02: rows=20; break; case 0x03: rows=24; break; } } else{ if(rxBuffer>=0x40){ if(rxBuffer>=0x80){rxBuffer=0x01;goto happydragons;}else{CGRAMmode=1;goto saddragons;} } else{ switch (rxBuffer){ case 0x00:break;//This is invalid command, there is nothing wrong to send it to LCD, //but it's better to use it for something else case 0x01:; case 0x02:; case 0x03: happydragons: CGRAMmode=0;x=0;y=0; default: //send command to LCD saddragons: P1OUT= (rxBuffer& 0xF0)|BackLight; toggle P1OUT= (rxBuffer<< 4)|BackLight; toggle }//switch }//else rxBuffer>=0x40 }//else }//if CommandFlag else if (rxBuffer==MAGIC){CommandFlag=1;}//strange things happens here else{ if(CGRAMmode==0){ switch (rxBuffer){ //filter non interestig characters here case 0x0A: break; //break Line feed case 0x0D: goto dragons; //new line http://xkcd.com/292/ default: //print character P1OUT= (rxBuffer& 0xF0) | LCDDataMode|BackLight; toggle P1OUT= (rxBuffer<< 4) | LCDDataMode|BackLight; toggle x++; if (x==rows){ dragons: x=0; y++; if (y==lines)y=0; //I hope that rxBuffer is free and unused switch(y){ case 0: rxBuffer=0x80; break; //0x80 is address of line 1 case 1: rxBuffer=0xC0; break; //0x80+0x40 is address of line 2 case 2: rxBuffer=0x80+address; break; //line 1 + address case 3: rxBuffer=0xC0+address; break; //line 2 + address } //goto new line P1OUT= (rxBuffer& 0xF0)|BackLight; toggle P1OUT= (rxBuffer<< 4)|BackLight; toggle } }//switch }// CGRAMmode if else{ //data in CGRAMmode P1OUT= (rxBuffer& 0xF0) | LCDDataMode|BackLight; toggle P1OUT= (rxBuffer<< 4) | LCDDataMode|BackLight; toggle }//CGRAMmode else }// no MAGIC }//main loop }//main #pragma vector = TIMERA1_VECTOR __interrupt void Timer_A1_ISR(void) { static uint8_t rxBitCnt = 8; static uint8_t rxData = 0; switch (__even_in_range(TAIV, TAIV_TAIFG)) { // Use calculated branching case TAIV_TACCR1: // TACCR1 CCIFG - UART RX TACCR1 += UART_TBIT; // Add Offset to CCRx if (TACCTL1 & CAP) { // Capture mode = start bit edge TACCTL1 &= ~CAP; // Switch capture to compare mode TACCR1 += UART_TBIT_DIV_2; // Point CCRx to middle of D0 } else { rxData >>= 1; if (TACCTL1 & SCCI) { // Get bit waiting in receive latch rxData |= 0x80; } rxBitCnt--; if (rxBitCnt == 0) { // All bits RXed? rxBuffer = rxData; // Store in global variable rxBitCnt = 8; // Re-load bit counter TACCTL1 |= CAP; // Switch compare to capture mode __bic_SR_register_on_exit(LPM0_bits); // Clear LPM0 bits from 0(SR) } } break; } } //------------------------------------------------------------------------------ //END
     



  2. Like
    Rickta59 reacted to bluehash in [ ENDED ] Nov-Dec 2011 - 43oh Project of the Month Contest   
    After a brief break, entry to the Nov-Dec 2011 contest is open. We are hoping that this be a mega contest with alot of entries. There is a ton of useful resources shared on the Forums. Be ambitious. At the same time, submit your project, even if it is a simple one. We are still adding prizes. You may win even if you do not expect it.
     
    Last date of Submission : December 26th, 2011
     
    We have exciting and awesome prizes this time. Lets start:
    [1] X-Tronic 2 in 1 Digital Hot Air Rework Soldering Iron Station graciously donated by SugarAddict.
    (3 HOT AIR TIPS - 10 SOLDERING TIPS - 1 EXTRA HEATING ELEMENT - 1 5X MAGNIFYING LAMP)
     
    [2] PanaVise 201 by our sponsor All-Spec.
     
    [3] One Serial LCD Backpack donated by Rob. This is an assembled PCB. An LCD costs around $3.50 on ebay.
    Rob makes awesome little Booster Packs and other stuff for the MSP430, aptly named "430Things"
     
    [3] The Terminal - 128x64 OLED Booster Pack by 43oh
     
    [4] Paladin PA1118 GripP 20 Wire Cutter/Stripper by our sponsor All-Spec.
     
    [5] A "BOARD" prize (idea by Robg), where you get to choose any one of the following boards
    - 595 Expander PCB
    - Three Wire LCD Breakout
    - One Soundpad PCB
     
    [6] 2xLS Research Proflex01 Zigbee radios donated by oPossum.
    If you have any kits or breakout boards to donate/lying unused, send us a mail and we'll put it up here. This time the number of entries needed for a valid POTM is ten.
     
    Members who have donated can also participate. It will be unfortunate not to have them. Thanks to All-Spec and Saleig for being our Sponsors for the next three months.
     
    To submit your entry, make an entry into this thread with the following:
    1 - A small description of your project.
    2 - A picture or video of your setup
    3 - Code.
    4 - Schematic(rough/hand drawn is fine as long its legible)
     
    About judging the winner :
    - A week before the contest ends, a poll will be created with all the project entries. Only members of the forum will be allowed to vote.
    - The contest will roll over to the next month if there are fewer than 10 projects(ten or less).
     
    A few simple rules to follow:
    - You must be a member of the 43oh forum at least a week before your submission.
    - One entry from each member will be permitted.
    - Your project can be anything based around the MSP430. You may interface the MSP430 to another controller.
    - You may reuse code from anywhere as long as you give credit to the original author.
    - You must submit code and schematics of your project with a proper description.
    - You can submit your MSP430 project, even if it was created before the annoucement of the contest.
    - You must have at least 10 posts in the forums, for your entry to be considered when the voting begins.
    - A member is free to modify his/her code to perfection, till the closing date, as long as the original entry is not changed.
    For eg: If a member submits "Launchpad controlled Space Shuttle", he/she can modify code, schematics and hardware and improve upon it till the closing date. But a change in project to "Launchpad controlled Robot" will not be allowed. Hopefully this will encourage members to post their projects early and not play the waiting game.
     
    Previous Contests:
    November 2010 --[Announce] [ Winner]
    December 2010 --[Announce / Winner]
    April 2011 --------[Announce / Winner]
    May/June 2011---[Announce / Winner]
    July-Sep 2011-----[Announce / Winner]
     
    Winner Announcement
  3. Like
    Rickta59 got a reaction from OppaErich in [solved] (PEBCAK) mspgcc - blinky.c fails to compile   
    Are you using a launchpad? If so, that should be:

    mspdebug rf2500
     
    -rick
  4. Like
    Rickta59 reacted to oPossum in CNC-milling: create 3 different frequencies with MSP430G2553   
    Here is some code that uses NCOs to generate three frequencies with 100 uHz (0.0001 Hz) resolution for a specified duration.
     
    There will be some jitter when 100000 / Frequency is not an integer. This may or may not be a problem. There are ways to reduce the jitter, but more hardware is required.
     
    Be very careful with the ISR code - it must be able to run in under 120 cycles.
     

    #include "msp430g2553.h" static long int timer = 0; // Duration of motion static long int pix = 0; // Phase increment static long int piy = 0; static long int piz = 0; static long int px = 0; // Position static long int py = 0; static long int pz = 0; static long int dx = 1; // Direction static long int dy = 1; static long int dz = 1; // Sample rate * (1 / resolution in Hz) static const long int pl = 1000000000; void set_fx(long int f) { pix = f - pl; } void set_fy(long int f) { piy = f - pl; } void set_fz(long int f) { piz = f - pl; } void main(void) { WDTCTL = WDTPW | WDTHOLD; // Disable watchdog DCOCTL = 0; BCSCTL1 = CALBC1_16MHZ; // Set DCO to 16 MHz DCOCTL = CALDCO_16MHZ; // P1DIR = 0x13; // I/O assignment P1REN = 0x00; // P1OUT = 0x02; // P1SEL = 0x10; // Enable SMCLK output P2DIR = 0x07; // P2REN = 0x00; // P2OUT = 0x00; // P2SEL = 0xC0; // TA0CTL = TASSEL_2 | MC_1; // Timer A config: SMCLK, count up TA0CCR0 = 160 - 1; // Setup Timer A CCR0 period for 100,000 Hz TA0CCTL0 |= CCIE; // Enable PWM interrupt _EINT(); // Enable interrupts set_fx(10000000); // 1000.0000 Hz set_fy(20000000); // 2000.0000 Hz set_fz(25000000); // 2500.0000 Hz timer = -1; // Run for a long time for(;; } #pragma vector = TIMER0_A0_VECTOR __interrupt void timer_a_isr(void) { static long int pax = 0; // Phase accumulator static long int pay = 0; static long int paz = 0; if(timer) { --timer; pax += pix; if(pax < 0) pax += pl; else { P2OUT |= 1; px += dx; P2OUT &= ~1; } pay += piy; if(pay < 0) pay += pl; else { P2OUT |= 2; py += dy; P2OUT &= ~2; } paz += piz; if(paz < 0) paz += pl; else { P2OUT |= 4; pz += dz; P2OUT &= ~4; } } }
  5. Like
    Rickta59 reacted to RobG in 4ch Volt Meter using Nokia 5110   
    This is just to show what can be done with 5110.
    FYI, inputs are floating, top bar is P1.3, which is pulled-up by default, values are raw, not calibrated.




    #include "msp430g2553.h" #include "PCD8544.h" #define LCD5110_SCLK_PIN BIT5 #define LCD5110_DN_PIN BIT7 #define LCD5110_SCE_PIN BIT4 #define LCD5110_DC_PIN BIT6 #define LCD5110_SELECT P1OUT &= ~LCD5110_SCE_PIN #define LCD5110_DESELECT P1OUT |= LCD5110_SCE_PIN #define LCD5110_SET_COMMAND P1OUT &= ~LCD5110_DC_PIN #define LCD5110_SET_DATA P1OUT |= LCD5110_DC_PIN #define LCD5110_COMMAND 0 #define LCD5110_DATA 1 void writeStringToLCD(const char *string); void writeCharToLCD(char c); void writeToLCD(unsigned char dataCommand, unsigned char data); void clearLCD(); void setAddr(unsigned char xAddr, unsigned char yAddr); void initLCD(); void binaryToUnpackedBCD(unsigned int n, unsigned char * digits); unsigned char bcd[4] = {0,0,0,0}; int adc[4] = {0,0,0,0}; unsigned char last[4] = {0,0,0,0}; static const char tick[64] = { 0x07, 0x04, 0x06, 0x04, 0x06, 0x04, 0x06, 0x04, 0x06, 0x04, 0x07, 0x04, 0x06, 0x04, 0x06, 0x04, 0x06, 0x04, 0x06, 0x04, 0x07, 0x04, 0x06, 0x04, 0x06, 0x04, 0x06, 0x04, 0x06, 0x04, 0x07, 0x04, 0x06, 0x04, 0x06, 0x04, 0x06, 0x04, 0x06, 0x04, 0x07, 0x04, 0x06, 0x04, 0x06, 0x04, 0x06, 0x04, 0x06, 0x04, 0x07, 0x04, 0x06, 0x04, 0x06, 0x04, 0x06, 0x04, 0x06, 0x04, 0x07, 0x04, 0x06, 0x04 }; void main(void) { WDTCTL = WDTPW + WDTHOLD; // disable WDT BCSCTL1 = CALBC1_1MHZ; // 1MHz clock DCOCTL = CALDCO_1MHZ; P1OUT |= LCD5110_SCE_PIN + LCD5110_DC_PIN; P1DIR |= LCD5110_SCE_PIN + LCD5110_DC_PIN; // setup USIB P1SEL |= LCD5110_SCLK_PIN + LCD5110_DN_PIN; P1SEL2 |= LCD5110_SCLK_PIN + LCD5110_DN_PIN; UCB0CTL0 |= UCCKPH + UCMSB + UCMST + UCSYNC; // 3-pin, 8-bit SPI master UCB0CTL1 |= UCSSEL_2; // SMCLK UCB0BR0 |= 0x01; // 1:1 UCB0BR1 = 0; UCB0CTL1 &= ~UCSWRST; // clear SW ADC10CTL1 = INCH_3 + CONSEQ_1; ADC10CTL0 = ADC10SHT_2 + MSC + ADC10ON + ADC10IE; ADC10DTC1 = 0x04; ADC10AE0 |= 0x0F; _delay_cycles(500000); initLCD(); clearLCD(); // LCD test writeStringToLCD("4ch Volt Meter"); setAddr(0,5); writeStringToLCD("by RobG @ 43oh"); char c = 0; // setup tickmarks char d = 0; while(d < 4) { d++; c = 0; setAddr(0,d); while(c < 64) { writeToLCD(LCD5110_DATA, tick[c]); c++; } } _bis_SR_register(GIE); while(1) { ADC10SA = (unsigned int)&adc[0]; ADC10CTL0 |= ENC + ADC10SC; _delay_cycles(100000); } } // ADC10 interrupt service routine #pragma vector=ADC10_VECTOR __interrupt void ADC10_ISR(void) { ADC10CTL0 &= ~ENC; char c = 0; while(c < 4) { unsigned char curr = adc[c] >> 4; unsigned char prev = last[c]; unsigned char b = 0; unsigned char t = 0; binaryToUnpackedBCD(curr, bcd); if(curr < prev) { setAddr(curr, c + 1); b = prev - curr + 1; t = curr; while(b > 0) { writeToLCD(LCD5110_DATA, tick[t++]); b--; } } else if(curr > prev) { setAddr(prev, c + 1); b = curr - prev; t = prev; while(b > 0) { writeToLCD(LCD5110_DATA, 0x70 | tick[t++]); b--; } } setAddr(70 ,c + 1); writeCharToLCD(bcd[2] + 0x30); writeToLCD(LCD5110_DATA, 0x40); writeToLCD(LCD5110_DATA, 0x0); writeCharToLCD(bcd[3] + 0x30); last[c] = curr; c++; } } void writeStringToLCD(const char *string) { while(*string) { writeCharToLCD(*string++); } } void writeCharToLCD(char c) { unsigned char i; for(i = 0; i < 5; i++) { writeToLCD(LCD5110_DATA, font[c - 0x20][i]); } writeToLCD(LCD5110_DATA, 0); } void writeToLCD(unsigned char dataCommand, unsigned char data) { LCD5110_SELECT; if(dataCommand) { LCD5110_SET_DATA; } else { LCD5110_SET_COMMAND; } UCB0TXBUF = data; while(!(IFG2 & UCB0TXIFG)) ; LCD5110_DESELECT; } void clearLCD() { setAddr(0, 0); int c = 0; while(c < PCD8544_MAXBYTES) { writeToLCD(LCD5110_DATA, 0); c++; } setAddr(0, 0); } void setAddr(unsigned char xAddr, unsigned char yAddr) { writeToLCD(LCD5110_COMMAND, PCD8544_SETXADDR | xAddr); writeToLCD(LCD5110_COMMAND, PCD8544_SETYADDR | yAddr); } void initLCD() { writeToLCD(LCD5110_COMMAND, PCD8544_FUNCTIONSET | PCD8544_EXTENDEDINSTRUCTION); writeToLCD(LCD5110_COMMAND, PCD8544_SETVOP | 0x3F); writeToLCD(LCD5110_COMMAND, PCD8544_SETTEMP | 0x02); writeToLCD(LCD5110_COMMAND, PCD8544_SETBIAS | 0x03); writeToLCD(LCD5110_COMMAND, PCD8544_FUNCTIONSET); writeToLCD(LCD5110_COMMAND, PCD8544_DISPLAYCONTROL | PCD8544_DISPLAYNORMAL); } void binaryToUnpackedBCD(unsigned int n, unsigned char * digits) { __asm(" clr R14"); __asm(" rla R12"); __asm(" rla R12"); __asm(" rla R12"); __asm(" rla R12"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" mov.b R14, 3(R13)"); __asm(" swpb R14"); __asm(" mov.b R14, 1(R13)"); __asm(" rra R14"); __asm(" rra R14"); __asm(" rra R14"); __asm(" rra R14"); __asm(" mov.b R14, 0(R13)"); __asm(" swpb R14"); __asm(" mov.b R14, 2(R13)"); __asm(" and #0x0F0F, 0(R13)"); __asm(" and #0x0F0F, 2(R13)"); return; }
    #ifndef PCD8544_H_#define PCD8544_H_#define PCD8544_POWERDOWN 0x04#define PCD8544_ENTRYMODE 0x02#define PCD8544_EXTENDEDINSTRUCTION 0x01#define PCD8544_DISPLAYBLANK 0x0#define PCD8544_DISPLAYNORMAL 0x4#define PCD8544_DISPLAYALLON 0x1#define PCD8544_DISPLAYINVERTED 0x5// H = 0#define PCD8544_FUNCTIONSET 0x20#define PCD8544_DISPLAYCONTROL 0x08#define PCD8544_SETYADDR 0x40#define PCD8544_SETXADDR 0x80#define PCD8544_HPIXELS 84#define PCD8544_VBANKS 6#define PCD8544_MAXBYTES 504 // PCD8544_HPIXELS * PCD8544_VBANKS// H = 1#define PCD8544_SETTEMP 0x04#define PCD8544_SETBIAS 0x10#define PCD8544_SETVOP 0x80//transform#define NONE 0x00#define FLIP_H 0x01#define FLIP_V 0x02#define ROTATE 0x04 // 90 deg CW#define ROTATE_90_CW ROTATE#define ROTATE_90_CCW (FLIP_H | FLIP_V | ROTATE)#define ROTATE_180 (FLIP_H | FLIP_V)static const char font[][5] = { // basic font{0x00, 0x00, 0x00, 0x00, 0x00} // 20,{0x00, 0x00, 0x5f, 0x00, 0x00} // 21 !,{0x00, 0x07, 0x00, 0x07, 0x00} // 22 ",{0x14, 0x7f, 0x14, 0x7f, 0x14} // 23 #,{0x24, 0x2a, 0x7f, 0x2a, 0x12} // 24 $,{0x23, 0x13, 0x08, 0x64, 0x62} // 25 %,{0x36, 0x49, 0x55, 0x22, 0x50} // 26 &,{0x00, 0x05, 0x03, 0x00, 0x00} // 27 ',{0x00, 0x1c, 0x22, 0x41, 0x00} // 28 (,{0x00, 0x41, 0x22, 0x1c, 0x00} // 29 ),{0x14, 0x08, 0x3e, 0x08, 0x14} // 2a *,{0x08, 0x08, 0x3e, 0x08, 0x08} // 2b +,{0x00, 0x50, 0x30, 0x00, 0x00} // 2c ,,{0x08, 0x08, 0x08, 0x08, 0x08} // 2d -,{0x00, 0x60, 0x60, 0x00, 0x00} // 2e .,{0x20, 0x10, 0x08, 0x04, 0x02} // 2f /,{0x3e, 0x51, 0x49, 0x45, 0x3e} // 30 0,{0x00, 0x42, 0x7f, 0x40, 0x00} // 31 1,{0x42, 0x61, 0x51, 0x49, 0x46} // 32 2,{0x21, 0x41, 0x45, 0x4b, 0x31} // 33 3,{0x18, 0x14, 0x12, 0x7f, 0x10} // 34 4,{0x27, 0x45, 0x45, 0x45, 0x39} // 35 5,{0x3c, 0x4a, 0x49, 0x49, 0x30} // 36 6,{0x01, 0x71, 0x09, 0x05, 0x03} // 37 7,{0x36, 0x49, 0x49, 0x49, 0x36} // 38 8,{0x06, 0x49, 0x49, 0x29, 0x1e} // 39 9,{0x00, 0x36, 0x36, 0x00, 0x00} // 3a :,{0x00, 0x56, 0x36, 0x00, 0x00} // 3b ;,{0x08, 0x14, 0x22, 0x41, 0x00} // 3c <,{0x14, 0x14, 0x14, 0x14, 0x14} // 3d =,{0x00, 0x41, 0x22, 0x14, 0x08} // 3e >,{0x02, 0x01, 0x51, 0x09, 0x06} // 3f ?,{0x32, 0x49, 0x79, 0x41, 0x3e} // 40 @,{0x7e, 0x11, 0x11, 0x11, 0x7e} // 41 A,{0x7f, 0x49, 0x49, 0x49, 0x36} // 42 B,{0x3e, 0x41, 0x41, 0x41, 0x22} // 43 C,{0x7f, 0x41, 0x41, 0x22, 0x1c} // 44 D,{0x7f, 0x49, 0x49, 0x49, 0x41} // 45 E,{0x7f, 0x09, 0x09, 0x09, 0x01} // 46 F,{0x3e, 0x41, 0x49, 0x49, 0x7a} // 47 G,{0x7f, 0x08, 0x08, 0x08, 0x7f} // 48 H,{0x00, 0x41, 0x7f, 0x41, 0x00} // 49 I,{0x20, 0x40, 0x41, 0x3f, 0x01} // 4a J,{0x7f, 0x08, 0x14, 0x22, 0x41} // 4b K,{0x7f, 0x40, 0x40, 0x40, 0x40} // 4c L,{0x7f, 0x02, 0x0c, 0x02, 0x7f} // 4d M,{0x7f, 0x04, 0x08, 0x10, 0x7f} // 4e N,{0x3e, 0x41, 0x41, 0x41, 0x3e} // 4f O,{0x7f, 0x09, 0x09, 0x09, 0x06} // 50 P,{0x3e, 0x41, 0x51, 0x21, 0x5e} // 51 Q,{0x7f, 0x09, 0x19, 0x29, 0x46} // 52 R,{0x46, 0x49, 0x49, 0x49, 0x31} // 53 S,{0x01, 0x01, 0x7f, 0x01, 0x01} // 54 T,{0x3f, 0x40, 0x40, 0x40, 0x3f} // 55 U,{0x1f, 0x20, 0x40, 0x20, 0x1f} // 56 V,{0x3f, 0x40, 0x38, 0x40, 0x3f} // 57 W,{0x63, 0x14, 0x08, 0x14, 0x63} // 58 X,{0x07, 0x08, 0x70, 0x08, 0x07} // 59 Y,{0x61, 0x51, 0x49, 0x45, 0x43} // 5a Z,{0x00, 0x7f, 0x41, 0x41, 0x00} // 5b [,{0x02, 0x04, 0x08, 0x10, 0x20} // 5c
  6. Like
    Rickta59 reacted to SugarAddict in F5529 Breakout Dev Board (Now with pics!)   
    Got the boards today from Seeed... couldn't help but solder at least one up... and I'm sad... the USB is failing (Unknown device / malfunctioning device) but programming it via a LP with SBW works fine and runs...
     




  7. Like
    Rickta59 got a reaction from kenemon in Free STM32F4 discovery kit in US/Canada   
    I'm not sure what size SD/MMC card you are trying to support, however the FatFs Generic FAT File System Module might work on one of the msp430s that have > than 1k of RAM. You might look at the generic version of the code to get started. You can find more info here: http://elm-chan.org/fsw/ff/00index_e.html
     
    -rick
  8. Like
    Rickta59 reacted to TopHatHacker in Zombie in a Can!   
    Hey, just poking my head in here quick to show off the first prototype of my Zombie in a Can!
     
    Check out the VID

     
    I used a launchpad with the 2231, a bluesmirf board, a window motor and a custom android app, this thing is awesome! I'm pretty proud that I made this in a night with 2 or 3 broken projects I had sitting around.
     
    Let me know what you think! and i'll be posting some scare videos soon
     


     
    First Motor Test


  9. Like
    Rickta59 reacted to DanAndDusty in Halloween Motion Triggered Sound and Light Thingamajig   
    OK.. Here is the code.. There is a separate header/code file for each section/device.. So we have
     
    EEPROM_USCI.c/h - Contains the main flow of the project
    25AA1024.c/h - Contains the routines for talking to the EEPROM (25AA1024)
    MAX5159.c/h - Contains the routines for talking to the DAC (MAX5159)
    USCI_UART.c/h - Contains routines for sending stuff through the serial port (Uses USCI on the 2553)
    xmodem.c.h - The "Fun" part of the project for me.. Routines for receiving a file using xmodem.
     
     
  10. Like
    Rickta59 got a reaction from YanuarPrijadi in Interface 23K256 SPI RAM with USI SPI   
    I came across the Microchip 23K256 Serial RAM device a while back. It seems to fit the bill
    when you need more RAM but don't want to spend a lot of money to get it. These chips are
    inexpensive, (about $1,50 at time of this post 06/05/2011) and hold 32K worth of data. You access
    the memory using SPI. You can even put multiple 23K256 devices on your SPI bus and get
    even more buffer space.
     
    The arduino world already has a couple of libraries to access these devices. I adapted
    one of these to work with both CCS and the uniarch compiler.
     
    I used GRACE to help me configure the msp430g2452 USI in SPI Mode 1. This code might be
    also be useful as a starting point for any SPI Mode 1 device. This code is written for the USI
    device. It would be nice to have a USCI version that would work with the g2553 chip.
     
    Typical use for this device might be to buffer UART received data that is larger than the 128 bytes
    of SRAM available on the smaller G series chips.
     
    You might want to verify the pin setup, I think I have it correct, however you should always verify.
    One interesting item of note is my use of one of the GPIO pins to power the device. You may or
    may not want to use that in your setup. According to the datasheet the 23K256 uses somewhere
    between 2-10mA of power based on how fast you interface with it. I think the G series should
    handle that but I'm not 100% sure. Please comment if you know.
     
    https://gist.github.com/1009412
     

    /** * testspi23K256.c - Interface Microchip 23K256 Serial RAM chip with MSP430G2452 USI SPI * * This code snippet show you how to configure the USI SPI in SPI Mode 1 to communicate with * the 23K256 chip at 4MHz. It takes about 98uSecs to write a single byte and 32K takes * about 100ms. * * msp430g2452 - http://focus.ti.com/docs/prod/folders/print/msp430g2452.html * 23K256 - http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en539039 * * Pin Connections: * * MSP430 SCLK P1.5 -> PIN 6(SCK) 23K256 * MSP430 MISO P1.7 -> PIN 2(SO) 23K256 * MSP430 MOSI P1.6 -> PIN 5(SI) 23K256 * MSP430 GPIO P1.1 -> PIN 1(CS) 23K256 * MSP430 GPIO P1.4 -> PIN 8(VCC) 23K256 * * 23K256 PIN 7 Pullup resistor * 23K256 PIN 8 Pulldown resistor * * Linux build: * * $ msp430-gcc -mmcu=msp430g2452 -O3 -g -Wall -I. -c testspi23K256.c * $ msp430-gcc -mmcu=msp430g2452 -O3 -g -Wall -I. -o ./testspi23K256.elf ./testspi23K256.o -Wl,-Map,./testspi23K256.map * $ msp430-objdump -Sww ./testspi23K256.elf >./testspi23K256.lss * $ msp430-size ./testspi23K256.elf * $ mspdebug -q --force-reset rf2500 "erase" "prog ./testspi23K256.elf" * * This code was inspired from this code: * * http://sourceforge.net/projects/mysudoku/files/ * http://hackaday.com/2009/03/02/parts-32kb-spi-sram-memory-23k256/ * */ #include #include enum { POWER_PIN = BIT4, // we power the 23K256 chip from one of our GPIO pins SS_PIN = BIT1, // CS , active low DEBUG_PIN = BIT0, // toggle on and off marking time to write DUMMY_BYTE = 0xFF // byte we send when we just want to read slave data }; static inline uint8_t RWData(volatile uint8_t value); void loop(); #define powerOn P1OUT |= POWER_PIN #define powerOff P1OUT &= ~POWER_PIN #define ssSelect P1OUT &= ~SS_PIN #define ssDeselect P1OUT |= SS_PIN #define delay_1ms __delay_cycles(16000) #define SR_WRITE_STATUS 0x01 #define SR_WRITE 0x02 #define SR_READ 0x03 #define SR_READ_STATUS 0x05 // 23K256 Serial Ram functions uint8_t SR_getMode(void) { ssSelect; RWData(SR_READ_STATUS); // 0x05 uint8_t mode = RWData(DUMMY_BYTE); ssDeselect; return mode; } void SR_setMode(uint8_t mode) { ssSelect; RWData(SR_WRITE_STATUS); // 0x01 RWData(mode); ssDeselect; } static inline void SR_writestream(uint16_t addr) { ssDeselect; // deselect if we are active ssSelect; RWData(0x02); RWData(addr >> 8); RWData(addr); } static inline void SR_readstream(uint16_t addr) { ssDeselect; ssSelect; RWData(0x03); RWData(addr >> 8); RWData(addr); } static inline uint8_t RWData(volatile uint8_t value) { USISRL = value; USICNT = 8; // initialize bit count, start transfer/read __delay_cycles(0); while (!(USIIFG & USICTL1)) ; // wait for SPI flag to trip return USISRL; } /** * main */ int main() { // kill the watchdog timer WDTCTL = WDTPW + WDTHOLD; // configure DCO clock to 16MHz BCSCTL2 = SELM_0 + DIVM_0 + DIVS_0; if (CALBC1_16MHZ != 0xFF) { DCOCTL = 0x00; BCSCTL1 = CALBC1_16MHZ; DCOCTL = CALDCO_16MHZ; } BCSCTL1 |= XT2OFF + DIVA_0; BCSCTL3 = XT2S_0 + LFXT1S_2 + XCAP_1; // configure GPIO P1OUT = POWER_PIN; P1DIR = SS_PIN + POWER_PIN + DEBUG_PIN; // configure USI - SPI Mode 1 @ 4MHz, clocked off SMCLK USICTL0 |= USISWRST; USICTL0 = USIPE7 + USIPE6 + USIPE5 + USIMST + USIOE + USISWRST; USICTL1 |= USICKPH; USICKCTL = USIDIV_1 + USISSEL_2; /* Enable USI */ USICTL0 &= ~USISWRST; __enable_interrupt(); // Set global interrupt enable // toggle the power for the 23K256 powerOff; delay_1ms; powerOn; ssDeselect; delay_1ms; while (1) { uint8_t chipMode; // make sure there is a 23K256 chip and that // is wired properly and in sequential mode chipMode = SR_getMode(); if (chipMode != 0x41) { SR_setMode(0x41); } else { while (1) { loop(); } } } } #define BYTES_TO_STREAM 32768 // should be less <= 32768 #define PATTERN_BYTE_VALUE 0x55 /** * loop - write a test pattern and read it back */ void loop() { volatile uint16_t i; volatile uint8_t storedValue = 0; P1OUT |= DEBUG_PIN; // mark start of write for measurement with oscope SR_writestream(0); // start writing at address 0 for (i = 0; i < BYTES_TO_STREAM; ++i) { RWData(PATTERN_BYTE_VALUE); } P1OUT &= ~DEBUG_PIN; // mark end of write for measurement with oscope // verify the bytes we wrote were stored and retreived properly SR_readstream(0); // start reading at address 0 for (i = 0; i < BYTES_TO_STREAM; ++i) { storedValue = RWData(DUMMY_BYTE); // verify our test pattern if (storedValue != PATTERN_BYTE_VALUE) { // if values aren't the same an error occurred, // turn off all leds, then sit and spin P1OUT &= ~BIT6; P1OUT &= ~DEBUG_PIN; while (1) { ; } } } }
  11. Like
    Rickta59 got a reaction from xpg in Instruction cycle counting with naken430util   
    I've been having fun experimenting with msp430 assembly code and msp430-gcc. I realized pretty quickly that the key to writing fast code in asm is knowing how many instructions cycles each asm statement takes to execute. Unfortunately, I couldn't find any mps430-gcc command line argument that would show me that. You can hand count the instructions cycles and add them up, however doing this quickly gets tedious. There is a better solution.
     
    gnomad (aka rocket4kids) showed me a small standalone msp430 assembler called naken430asm http://www.mikekohn.net/micro/naken430asm_msp430_assembler.php. With a little bending you can get cycle counts using naken430util in combination with the msp430-gcc bin utilites.
     
    First, compile your code as usual and produce an ELF file. We will assume your file is called blink.elf. Once you have an ELF file, convert it to an intel hex file using this command:
     

    msp430-objcopy -O ihex blink.elf blink.hex
    (thanks for this recommendation gordon)
     
    nake430util can then be used to get a listing of the asm instructions in the hex file along with a cycle count using the following command:
     

    naken430util -disasm blink.hex > cycle_listing.txt
     
    The cycle_listing.txt will contain something that looks like this:
     

    Addr Opcode Instruction Cycles ------- ------ ---------------------------------- ------ 0xc000: 0x4031 mov.w #0x0400, SP 2 0xc002: 0x0400 0xc004: 0x4215 mov.w &0x0120, r5 3 0xc006: 0x0120 0xc008: 0xf375 and.b #-1, r5 1 0xc00a: 0xd035 bis.w #0x5a08, r5 2 0xc00c: 0x5a08 0xc00e: 0x403f mov.w #0x0000, r15 2
     
    You can optimize your code by experimenting with the different addressing modes. If you are using variables more than once you probably want to move those things into registers. Register to register operations typically only take one cycle. If you can change your code so that a majority of your frequently run instructions use register to register addressing, you will get closer to 1 MIPS/ 1MHz execution. In my code, I focused on my interrupt routines and by paying attention to the number of cycles used I was able to shave off some significant time.
     
    I put together an msp430 assembler skeleton package you can grab from github. It has a Makefile and sample code that automates the instructions discussed above. You can find it here:
     
    https://gist.github.com/1303030
     
    [Plug for #43OH IRC]
    I've found the #43oh channel on http://webchat.freenode.net to be an incredible resource for getting my questions answered by friendly, knowledgeable people about the msp430 platform. Thanks guys!
     
     
    -rick
  12. Like
    Rickta59 got a reaction from gwdeveloper in Fraunchpad DMA Interrupt Vectors?   
    The data sheet seems to indicate 3 DMA channels.
     
    -rick
     

     
    http://www.ti.com/ds_dgm/images/fbd_slas639a.gif
  13. Like
    Rickta59 got a reaction from zborgerd in Instruction cycle counting with naken430util   
    I've been having fun experimenting with msp430 assembly code and msp430-gcc. I realized pretty quickly that the key to writing fast code in asm is knowing how many instructions cycles each asm statement takes to execute. Unfortunately, I couldn't find any mps430-gcc command line argument that would show me that. You can hand count the instructions cycles and add them up, however doing this quickly gets tedious. There is a better solution.
     
    gnomad (aka rocket4kids) showed me a small standalone msp430 assembler called naken430asm http://www.mikekohn.net/micro/naken430asm_msp430_assembler.php. With a little bending you can get cycle counts using naken430util in combination with the msp430-gcc bin utilites.
     
    First, compile your code as usual and produce an ELF file. We will assume your file is called blink.elf. Once you have an ELF file, convert it to an intel hex file using this command:
     

    msp430-objcopy -O ihex blink.elf blink.hex
    (thanks for this recommendation gordon)
     
    nake430util can then be used to get a listing of the asm instructions in the hex file along with a cycle count using the following command:
     

    naken430util -disasm blink.hex > cycle_listing.txt
     
    The cycle_listing.txt will contain something that looks like this:
     

    Addr Opcode Instruction Cycles ------- ------ ---------------------------------- ------ 0xc000: 0x4031 mov.w #0x0400, SP 2 0xc002: 0x0400 0xc004: 0x4215 mov.w &0x0120, r5 3 0xc006: 0x0120 0xc008: 0xf375 and.b #-1, r5 1 0xc00a: 0xd035 bis.w #0x5a08, r5 2 0xc00c: 0x5a08 0xc00e: 0x403f mov.w #0x0000, r15 2
     
    You can optimize your code by experimenting with the different addressing modes. If you are using variables more than once you probably want to move those things into registers. Register to register operations typically only take one cycle. If you can change your code so that a majority of your frequently run instructions use register to register addressing, you will get closer to 1 MIPS/ 1MHz execution. In my code, I focused on my interrupt routines and by paying attention to the number of cycles used I was able to shave off some significant time.
     
    I put together an msp430 assembler skeleton package you can grab from github. It has a Makefile and sample code that automates the instructions discussed above. You can find it here:
     
    https://gist.github.com/1303030
     
    [Plug for #43OH IRC]
    I've found the #43oh channel on http://webchat.freenode.net to be an incredible resource for getting my questions answered by friendly, knowledgeable people about the msp430 platform. Thanks guys!
     
     
    -rick
  14. Like
    Rickta59 got a reaction from bluehash in Instruction cycle counting with naken430util   
    I've been having fun experimenting with msp430 assembly code and msp430-gcc. I realized pretty quickly that the key to writing fast code in asm is knowing how many instructions cycles each asm statement takes to execute. Unfortunately, I couldn't find any mps430-gcc command line argument that would show me that. You can hand count the instructions cycles and add them up, however doing this quickly gets tedious. There is a better solution.
     
    gnomad (aka rocket4kids) showed me a small standalone msp430 assembler called naken430asm http://www.mikekohn.net/micro/naken430asm_msp430_assembler.php. With a little bending you can get cycle counts using naken430util in combination with the msp430-gcc bin utilites.
     
    First, compile your code as usual and produce an ELF file. We will assume your file is called blink.elf. Once you have an ELF file, convert it to an intel hex file using this command:
     

    msp430-objcopy -O ihex blink.elf blink.hex
    (thanks for this recommendation gordon)
     
    nake430util can then be used to get a listing of the asm instructions in the hex file along with a cycle count using the following command:
     

    naken430util -disasm blink.hex > cycle_listing.txt
     
    The cycle_listing.txt will contain something that looks like this:
     

    Addr Opcode Instruction Cycles ------- ------ ---------------------------------- ------ 0xc000: 0x4031 mov.w #0x0400, SP 2 0xc002: 0x0400 0xc004: 0x4215 mov.w &0x0120, r5 3 0xc006: 0x0120 0xc008: 0xf375 and.b #-1, r5 1 0xc00a: 0xd035 bis.w #0x5a08, r5 2 0xc00c: 0x5a08 0xc00e: 0x403f mov.w #0x0000, r15 2
     
    You can optimize your code by experimenting with the different addressing modes. If you are using variables more than once you probably want to move those things into registers. Register to register operations typically only take one cycle. If you can change your code so that a majority of your frequently run instructions use register to register addressing, you will get closer to 1 MIPS/ 1MHz execution. In my code, I focused on my interrupt routines and by paying attention to the number of cycles used I was able to shave off some significant time.
     
    I put together an msp430 assembler skeleton package you can grab from github. It has a Makefile and sample code that automates the instructions discussed above. You can find it here:
     
    https://gist.github.com/1303030
     
    [Plug for #43OH IRC]
    I've found the #43oh channel on http://webchat.freenode.net to be an incredible resource for getting my questions answered by friendly, knowledgeable people about the msp430 platform. Thanks guys!
     
     
    -rick
  15. Like
    Rickta59 got a reaction from oPossum in Instruction cycle counting with naken430util   
    I've been having fun experimenting with msp430 assembly code and msp430-gcc. I realized pretty quickly that the key to writing fast code in asm is knowing how many instructions cycles each asm statement takes to execute. Unfortunately, I couldn't find any mps430-gcc command line argument that would show me that. You can hand count the instructions cycles and add them up, however doing this quickly gets tedious. There is a better solution.
     
    gnomad (aka rocket4kids) showed me a small standalone msp430 assembler called naken430asm http://www.mikekohn.net/micro/naken430asm_msp430_assembler.php. With a little bending you can get cycle counts using naken430util in combination with the msp430-gcc bin utilites.
     
    First, compile your code as usual and produce an ELF file. We will assume your file is called blink.elf. Once you have an ELF file, convert it to an intel hex file using this command:
     

    msp430-objcopy -O ihex blink.elf blink.hex
    (thanks for this recommendation gordon)
     
    nake430util can then be used to get a listing of the asm instructions in the hex file along with a cycle count using the following command:
     

    naken430util -disasm blink.hex > cycle_listing.txt
     
    The cycle_listing.txt will contain something that looks like this:
     

    Addr Opcode Instruction Cycles ------- ------ ---------------------------------- ------ 0xc000: 0x4031 mov.w #0x0400, SP 2 0xc002: 0x0400 0xc004: 0x4215 mov.w &0x0120, r5 3 0xc006: 0x0120 0xc008: 0xf375 and.b #-1, r5 1 0xc00a: 0xd035 bis.w #0x5a08, r5 2 0xc00c: 0x5a08 0xc00e: 0x403f mov.w #0x0000, r15 2
     
    You can optimize your code by experimenting with the different addressing modes. If you are using variables more than once you probably want to move those things into registers. Register to register operations typically only take one cycle. If you can change your code so that a majority of your frequently run instructions use register to register addressing, you will get closer to 1 MIPS/ 1MHz execution. In my code, I focused on my interrupt routines and by paying attention to the number of cycles used I was able to shave off some significant time.
     
    I put together an msp430 assembler skeleton package you can grab from github. It has a Makefile and sample code that automates the instructions discussed above. You can find it here:
     
    https://gist.github.com/1303030
     
    [Plug for #43OH IRC]
    I've found the #43oh channel on http://webchat.freenode.net to be an incredible resource for getting my questions answered by friendly, knowledgeable people about the msp430 platform. Thanks guys!
     
     
    -rick
  16. Like
    Rickta59 got a reaction from gordon in Saving flash space, by making use of infomem   
    @Peter Thanks for the clarification from the source!
     
    I have been avoiding all the older gcc releases as I'm only using the newly added value line chips and the FRAM chips. Are there any other nice features on the table for the next release of msp430-gcc?
     
    -rick
  17. Like
    Rickta59 got a reaction from DecebaL in Software async serial tx/rx without timer   
    Here is an msp430-gcc port of serial.S. Only some minor changes required:
     
    renamed from serial.asm to serial.S
    changed header inclusion, .cdecls to #include
    added ':' to all labels
    changed .bss directives to .lcomm
    changed .def directives to .global
    fixed argument registers CCS using R12-R15 for arg1-arg4, GCC uses R15-R12 for arg1-arg4
    reworked temp registers because of argument register reorder
    changed OR asm statements to BIS statements
     

    ; serial.S - gcc port of serial.asm #include ;------------------------------------------------------------------------------- ; --- define PC,SP,SR gcc only knows about registers --- #define PC r0 #define SP r1 #define SR r2 #define ARG1 R15 #define ARG2 R14 #define ARG3 R13 #define ARG4 R12 .lcomm in_bit_mask, 2 ; Serial in pin .lcomm out_bit_mask, 2 ; Serial out pin .lcomm bit_dur, 2 ; Bit duration in cycles .lcomm half_dur, 2 ; Half bit duration in cycles ; .text ; .global serial_setup ; void serial_setup(unsigned out_mask, unsigned in_mask, unsigned bit_duration); .global putc ; void putc(unsigned c); .global puts ; void puts(char *s); .global getc ; unsigned getc(void); ; .p2align 1,0 ; align on a word boundary serial_setup: ; - Setup serial I/O bitmasks and bit duration (32 minimum) mov ARG1, &out_bit_mask ; Save serial output bitmask mov ARG2, &in_bit_mask ; Save serial input bitmask bis ARG1, &P1DIR ; Setup output pin bis ARG1, &P1OUT ; bic ARG2, &P1DIR ; Setup input pin bis ARG2, ARG1 ; bic ARG1, &P1SEL ; Setup peripheral select mov ARG3, ARG1 ; sub #16, ARG3 ; Adjust count for loop overhead rla ARG3 ; Multiply by 2 because NOP is two bytes mov ARG3, &bit_dur ; Save bit duration sub #32, ARG1 ; Adjust count for loop overhead mov ARG1, &half_dur ; Save half bit duration ret ; Return ; ; - Send a single char putc: ; Char to tx in R15 ; R12, R13, R14, R15 trashed mov &out_bit_mask, R12 ; Serial output bitmask mov &bit_dur, R14 ; Bit duration bis #0x0300, ARG1 ; Add Stop bit(s) to tx char jmp bit_low ; Send start bit... ; tx_bit: mov R14, R13 ; Get bit duration tx_delay: nop ; 4 cycle loop sub #8, R13 ; jc tx_delay ; subc R13, PC ; 0 to 3 cycle delay nop ; 3 nop ; 2 nop ; 1 ; rra ARG1 ; Get bit to tx, test for zero jc bit_high ; If high... bit_low: bic.b R12, &P1OUT ; Send zero bit jmp tx_bit ; Next bit... bit_high: bis.b R12, &P1OUT ; Send one bit jnz tx_bit ; If tx data is not zero, then there are more bits to send... ; ret ; Return when all bits sent ; ; ; - Send a NULL terminated string puts: ; Tx string using putc push R11 ; mov ARG1, R11 ; String pointer in R15, copy to R11 putsloop: ; mov.b @R11+, ARG1 ; Get a byte, inc pointer tst.b ARG1 ; Test if end of string jz putsx ; Yes, exit... call #putc ; Call putc jmp putsloop ; putsx: pop R11 ; ret ; ; getc: ; - Get a char mov &bit_dur, R14 ; Bit duration mov &in_bit_mask, R13 ; Input bitmask mov #0x01FF, ARG1 ; 9 bits - 8 data + stop ; rx_start: ; Wait for start bit mov &P1IN, R12 ; Get serial input and R13, R12 ; Mask and test bit jc rx_start ; Wait for low... ; mov &half_dur, R13 ; Wait for 1/2 bit time ; rx_delay: nop ; Bit delay sub #8, R13 ; jc rx_delay ; subc R13, PC ; 0 to 3 cycle delay nop ; 3 nop ; 2 nop ; 1 ; mov &P1IN, R12 ; Get serial input and &in_bit_mask, R12 ; rrc ARG1 ; Shift in a bit ; mov R14, R13 ; Setup bit timer jc rx_delay ; Next bit... ; rla ARG1 ; Move stop bit to carry swpb ARG1 ; Move rx byte to lower byte, start bit in msb ret ; Return with rx char and start bit in R15, stop bit in carry
     
    -rick
  18. Like
    Rickta59 reacted to greeeg in Saving flash space, by making use of infomem   
    All modern MSP chips to my knowledge feature a small area of "information memory". To my knowledge this is the equivalent to internal EEPROM on a PIC or AVR.
     
    Using mspgcc we can easily store an array of constant data into infomem. all that is required is a single attribute tag. For example in my current project I have an array of font data. by moving it to infomem I saved 192 bytes of flash. (Strictly speaking infomem is flash :think: So don't be worried about wearing it out anymore than flash ) Anyway here is the code

    /* "Compressed" font data, in form 0b ABCD EFGH IJKL MNOP {A-P} represent segment bits in each character __J_ _A__ |\ | /| | K H B | L \ | / C | \|/ | >-M--*--D-< | /|\ | N / | \ E | O I F | |/ | \| ~~P~ ~G~~ */ const unsigned int font_data[] __attribute__((section(".infomem"))) = { 0x0000,0xC101,0x0110,0x3B89,0x9BD9,0x5BDA,0x0F6D,0x4000, 0x4400,0x0022,0x55AA,0x1188,0x0002,0x1008,0x0001,0x4002, 0xEA57,0x6800,0xB24D,0xDA41,0x3818,0x8659,0x9A5D,0xA840, 0xBA5D,0xBA59,0x0041,0x0042,0x4203,0x1209,0x0621,0xB0C0, 0xAACD,0xB85C,0xBBC1,0x8255,0xABC1,0x825D,0x805C,0x9A55, 0x381C,0x83C1,0x81C5,0x441C,0x0215,0x6834,0x2C34,0xAA55, 0xB05C,0xAE55,0xB45C,0x9A59,0x81C0,0x2A15,0x4016,0x2C16, 0x4422,0x40A0,0xC243,0x0055,0x0420,0xAA00,0x0402,0x0201, 0x0020,0x028D,0x009D,0x000D,0x018D,0x000F,0x9188,0x1E01, 0x009C,0x0080,0x0081,0x1580,0x03C0,0x188C,0x008C,0x008D, 0x015C,0x03D8,0x000C,0x1081,0x1388,0x0085,0x0006,0x0A85, 0x4182,0x0E01,0x000B,0x8388,0x0180,0x11C1,0x3150,0x0000, };
     
    This one line of code is what does all the magic. This tells the linker to move this block of data into the infomem region.

    __attribute__((section(".infomem")))
     
     
    Be warned the infomem region often contains calibration data for the DCO, it would be wise to make a note of what these values are. In case you accidentally store data over them.
    This can easily be done using this command
    mspdebug rf2500 'md 0x10FE 0x2' *The address 0x10FE applicable for the the value line devices. This command will open mspdebug, connect to the device and dump 2 bytes from address 0x10FE, on the value line devices these 2 bytes are the DCO calibration values.
     
    An interesting side note about the attribute command. is that it could be used to position a function into infomem. However Some MSP430 devices are unable to execute commands from infomem. (or maybe it's just the MSP430f5438 )
  19. Like
    Rickta59 got a reaction from woodgrain in Software async serial tx/rx without timer   
    Here is an msp430-gcc port of serial.S. Only some minor changes required:
     
    renamed from serial.asm to serial.S
    changed header inclusion, .cdecls to #include
    added ':' to all labels
    changed .bss directives to .lcomm
    changed .def directives to .global
    fixed argument registers CCS using R12-R15 for arg1-arg4, GCC uses R15-R12 for arg1-arg4
    reworked temp registers because of argument register reorder
    changed OR asm statements to BIS statements
     

    ; serial.S - gcc port of serial.asm #include ;------------------------------------------------------------------------------- ; --- define PC,SP,SR gcc only knows about registers --- #define PC r0 #define SP r1 #define SR r2 #define ARG1 R15 #define ARG2 R14 #define ARG3 R13 #define ARG4 R12 .lcomm in_bit_mask, 2 ; Serial in pin .lcomm out_bit_mask, 2 ; Serial out pin .lcomm bit_dur, 2 ; Bit duration in cycles .lcomm half_dur, 2 ; Half bit duration in cycles ; .text ; .global serial_setup ; void serial_setup(unsigned out_mask, unsigned in_mask, unsigned bit_duration); .global putc ; void putc(unsigned c); .global puts ; void puts(char *s); .global getc ; unsigned getc(void); ; .p2align 1,0 ; align on a word boundary serial_setup: ; - Setup serial I/O bitmasks and bit duration (32 minimum) mov ARG1, &out_bit_mask ; Save serial output bitmask mov ARG2, &in_bit_mask ; Save serial input bitmask bis ARG1, &P1DIR ; Setup output pin bis ARG1, &P1OUT ; bic ARG2, &P1DIR ; Setup input pin bis ARG2, ARG1 ; bic ARG1, &P1SEL ; Setup peripheral select mov ARG3, ARG1 ; sub #16, ARG3 ; Adjust count for loop overhead rla ARG3 ; Multiply by 2 because NOP is two bytes mov ARG3, &bit_dur ; Save bit duration sub #32, ARG1 ; Adjust count for loop overhead mov ARG1, &half_dur ; Save half bit duration ret ; Return ; ; - Send a single char putc: ; Char to tx in R15 ; R12, R13, R14, R15 trashed mov &out_bit_mask, R12 ; Serial output bitmask mov &bit_dur, R14 ; Bit duration bis #0x0300, ARG1 ; Add Stop bit(s) to tx char jmp bit_low ; Send start bit... ; tx_bit: mov R14, R13 ; Get bit duration tx_delay: nop ; 4 cycle loop sub #8, R13 ; jc tx_delay ; subc R13, PC ; 0 to 3 cycle delay nop ; 3 nop ; 2 nop ; 1 ; rra ARG1 ; Get bit to tx, test for zero jc bit_high ; If high... bit_low: bic.b R12, &P1OUT ; Send zero bit jmp tx_bit ; Next bit... bit_high: bis.b R12, &P1OUT ; Send one bit jnz tx_bit ; If tx data is not zero, then there are more bits to send... ; ret ; Return when all bits sent ; ; ; - Send a NULL terminated string puts: ; Tx string using putc push R11 ; mov ARG1, R11 ; String pointer in R15, copy to R11 putsloop: ; mov.b @R11+, ARG1 ; Get a byte, inc pointer tst.b ARG1 ; Test if end of string jz putsx ; Yes, exit... call #putc ; Call putc jmp putsloop ; putsx: pop R11 ; ret ; ; getc: ; - Get a char mov &bit_dur, R14 ; Bit duration mov &in_bit_mask, R13 ; Input bitmask mov #0x01FF, ARG1 ; 9 bits - 8 data + stop ; rx_start: ; Wait for start bit mov &P1IN, R12 ; Get serial input and R13, R12 ; Mask and test bit jc rx_start ; Wait for low... ; mov &half_dur, R13 ; Wait for 1/2 bit time ; rx_delay: nop ; Bit delay sub #8, R13 ; jc rx_delay ; subc R13, PC ; 0 to 3 cycle delay nop ; 3 nop ; 2 nop ; 1 ; mov &P1IN, R12 ; Get serial input and &in_bit_mask, R12 ; rrc ARG1 ; Shift in a bit ; mov R14, R13 ; Setup bit timer jc rx_delay ; Next bit... ; rla ARG1 ; Move stop bit to carry swpb ARG1 ; Move rx byte to lower byte, start bit in msb ret ; Return with rx char and start bit in R15, stop bit in carry
     
    -rick
  20. Like
    Rickta59 reacted to bluehash in [ REMINDER ] Please Thank Members that help you out.   
    Hello everyone,
     
    There has been alot of good questions going on in the past few weeks - accompanied with very good discussions. One way you can show your appreciation is by using the "Thanks" or "Thumbs up " button on the top right. It may be hard to notice but a screenshot always helps:

     
    Use it if you have received something useful from a member. It takes time to write those posts and code. Consider it as karma, that's as good as it can get. :mrgreen:
     
    Thanks everyone..and wish you a happy new year.
  21. Like
    Rickta59 got a reaction from rockets4kids in Using msp430-gcc as an asm compiler   
    I spent some time and figured out how to make msp430-gcc compile and link the msp430g2xx3_ta_01.asm sample
    program from the msp430g2553 samples zip http://www.ti.com/litv/zip/slac485a. I had to modify the labels
    (added ':'s at the end ), changed some of the directives, and then passed a boatload of arguments to gcc. You can
    find the gory details in this gist:
     
    https://gist.github.com/1297504
     
    You need the latest uniarch msp430gcc with the latest patches for this to work properly and latest mspdebug.
     
    To build and install just type in the directory where the source is:
     
    $ make clean all install
     
    -rick
  22. Like
    Rickta59 got a reaction from bluehash in Using msp430-gcc as an asm compiler   
    I spent some time and figured out how to make msp430-gcc compile and link the msp430g2xx3_ta_01.asm sample
    program from the msp430g2553 samples zip http://www.ti.com/litv/zip/slac485a. I had to modify the labels
    (added ':'s at the end ), changed some of the directives, and then passed a boatload of arguments to gcc. You can
    find the gory details in this gist:
     
    https://gist.github.com/1297504
     
    You need the latest uniarch msp430gcc with the latest patches for this to work properly and latest mspdebug.
     
    To build and install just type in the directory where the source is:
     
    $ make clean all install
     
    -rick
  23. Like
    Rickta59 got a reaction from zborgerd in Using msp430-gcc as an asm compiler   
    I spent some time and figured out how to make msp430-gcc compile and link the msp430g2xx3_ta_01.asm sample
    program from the msp430g2553 samples zip http://www.ti.com/litv/zip/slac485a. I had to modify the labels
    (added ':'s at the end ), changed some of the directives, and then passed a boatload of arguments to gcc. You can
    find the gory details in this gist:
     
    https://gist.github.com/1297504
     
    You need the latest uniarch msp430gcc with the latest patches for this to work properly and latest mspdebug.
     
    To build and install just type in the directory where the source is:
     
    $ make clean all install
     
    -rick
  24. Like
    Rickta59 reacted to oPossum in Software async serial tx/rx without timer   
    Had some requests for this in IRC so here it is. This is an improved version of the serial tx previously posted and new serial rx code. Both tx and rx are blocking and interrupts should be disabled before calling.
     
    C code to show how to use the serial_setup(), putc(), puts(), and getc() functions.
    This will receive a character, increment it and echo it back. So if you type 'A', then 'B' will be echoed.

    // test.c #include "msp430g2211.h" // Functions in serial.asm (this really should be in a header file) void serial_setup(unsigned out_mask, unsigned in_mask, unsigned duration); void putc(unsigned); void puts(char *); unsigned getc(void); void main(void) { char c; // Disable watchdog WDTCTL = WDTPW + WDTHOLD; // Use 1 MHz DCO factory calibration DCOCTL = 0; BCSCTL1 = CALBC1_1MHZ; DCOCTL = CALDCO_1MHZ; // Setup the serial port // Serial out: P1.1 (BIT1) // Serial in: P1.2 (BIT2) // Bit rate: 9600 (CPU freq / bit rate) serial_setup(BIT1, BIT2, 1000000 / 9600); // Send a string puts("\r\nRunning...\r\n"); for(; { // Do forever c = getc(); // Get a char ++c; // Increment it putc(c); // Echo it back } }
     
    The serial tx/rx code. Just add this as a new source file in your CCS project and it will be callable from your C code.

    ; serial.asm .cdecls C, LIST, "msp430g2231.h" .bss in_bit_mask, 2 ; Serial in pin .bss out_bit_mask, 2 ; Serial out pin .bss bit_dur, 2 ; Bit duration in cycles .bss half_dur, 2 ; Half bit duration in cycles ; .text ; .def serial_setup ; void serial_setup(unsigned out_mask, unsigned in_mask, unsigned bit_duration); .def putc ; void putc(unsigned c); .def puts ; void puts(char *s); .def getc ; unsigned getc(void); ; ; serial_setup ; - Setup serial I/O bitmasks and bit duration (32 minimum) mov R12, &out_bit_mask ; Save serial output bitmask mov R13, &in_bit_mask ; Save serial input bitmask bis.b R12, &P1DIR ; Setup output pin bis.b R12, &P1OUT ; bic.b R13, &P1DIR ; Setup input pin or R13, R12 ; bic.b R12, &P1SEL ; Setup peripheral select mov R14, R12 ; sub #16, R14 ; Adjust count for loop overhead rla R14 ; Multiply by 2 because NOP is two bytes mov R14, &bit_dur ; Save bit duration sub #32, R12 ; Adjust count for loop overhead mov R12, &half_dur ; Save half bit duration ret ; Return ; ; - Send a single char putc ; Char to tx in R12 ; R12, R13, R14, R15 trashed mov &out_bit_mask, R15 ; Serial output bitmask mov &bit_dur, R14 ; Bit duration or #0x0300, R12 ; Stop bit(s) jmp bit_low ; Send start bit... ; tx_bit mov R14, R13 ; Get bit duration tx_delay nop ; 4 cycle loop sub #8, R13 ; jc tx_delay ; subc R13, PC ; 0 to 3 cycle delay nop ; 3 nop ; 2 nop ; 1 ; rra R12 ; Get bit to tx, test for zero jc bit_high ; If high... bit_low bic.b R15, &P1OUT ; Send zero bit jmp tx_bit ; Next bit... bit_high bis.b R15, &P1OUT ; Send one bit jnz tx_bit ; If tx data is not zero, then there are more bits to send... ; ret ; Return when all bits sent ; ; ; - Send a NULL terminated string puts ; Tx string using putc push R11 ; mov R12, R11 ; String pointer in R12, copy to R11 putsloop ; mov.b @R11+, R12 ; Get a byte, inc pointer tst.b R12 ; Test if end of string jz putsx ; Yes, exit... call #putc ; Call putc jmp putsloop ; putsx pop R11 ; ret ; ; getc ; - Get a char mov &bit_dur, R14 ; Bit duration mov &in_bit_mask, R13 ; Input bitmask mov #0x01FF, R12 ; 9 bits - 8 data + stop ; rx_start ; Wait for start bit mov.b &P1IN, R15 ; Get serial input and R13, R15 ; Mask and test bit jc rx_start ; Wait for low... ; mov &half_dur, R13 ; Wait for 1/2 bit time ; rx_delay nop ; Bit delay sub #8, R13 ; jc rx_delay ; subc R13, PC ; 0 to 3 cycle delay nop ; 3 nop ; 2 nop ; 1 ; mov.b &P1IN, R15 ; Get serial input and &in_bit_mask, R15 ; rrc R12 ; Shift in a bit ; mov R14, R13 ; Setup bit timer jc rx_delay ; Next bit... ; rla R12 ; Move stop bit to carry swpb R12 ; Move rx byte to lower byte, start bit in msb ret ; Return with rx char and start bit in R12, stop bit in carry ; .end ;
  25. Like
    Rickta59 reacted to zborgerd in Free STM32F4 discovery kit in US/Canada   
    Here's a start. I'm using Ubuntu 11.10 (just released) and it appears that the Universe repository already has an ARM package available for GCC 4.6.
     

    sudo apt-get install gcc-arm-linux-gnueabi
     
    I had looked at GCC 4.6 a week or two ago and it looked like the core was supported. The cortex-m4 appears to be a valid target with -mcpu. I'll post more details as I progress (compiling a project and actually getting it to load).
×
×
  • Create New...