Jump to content
43oh

Alan

Members
  • Content Count

    56
  • Joined

  • Last visited

Reputation Activity

  1. Like
    Alan reacted to jpnorair in STM32L vs. MSP430F5: What's left for MSP430?   
    Recently I've been doing a lot of work with STM32L.  The asynchronous RTOS that I had previous built for MSP430F5/F6 is now working nicely on STM32L.  I'm doing some benchmarking and profiling of STM32L vs. MSP430 -- it is a long process, but the signs aren't looking good for MSP430.  Here are some of the preliminary, qualitative results.
     
    Lowest-Power Sleep:
    I've used LPM3 for MSP430F5 and STOP-mode for STM32L.  These are the lowest-power modes that allow SRAM retention (and register retention) and a means for the MCU to schedule its own wakeup with a timer.  Both of the devices use roughly 2uA in this mode.  Both devices also come out of lowest power sleep in roughly 10us, however the MSP430 needs more like 100us if you have the supply voltage monitor enabled.  STM32L does not need the extra time, so it wins.
     
    Runtime Performance per mA
    STM32L is using the Cortex M3, not the M0, so it has a brutish ALU with 32x32 multiplier in addition to single-instruction multiply-accumulate, single-instruction logical comparsion with shift, and a bunch of other neat ALU instruction that make it run very fast.  Additionally, it has a DMA that is independent of the CPU.  I'm using it a 4.2 MHz to achieve 1mA runtime, and my MSP430F5 is running at 5.2 MHz to achieve 1mA.  For doing DSP or software crypto (like RSA), it isn't even close.  The ARM just humiliates the MSP.  For doing protocol processing, RTOS scheduling, and more logical operations, the ARM still is beating the MSP by about 2x, even though the MSP is clocked a bit higher.  So, my verdict is that STM32L uses less than half the runtime power of MSP430F5.  STM32L also has a fast-settling 16MHz clock that outperforms MSP430 at 25MHz, and if you're crazy you can push it to 32 MHz.  It absolute performance, it just dominates.
     
    Features and cost
    I'm comparing a low-end STM32L (STM32L151C8: 64KB Flash, 4KB EEPROM, 10KB SRAM) and a mid-range MSP430 (MSP430F5510: 32KB Flash, 0.5KB storage Flash, 6KB SRAM).  Otherwise, they have a comparable set of peripherals and they cost about the same.  The difference is that almost every peripheral in the STM32L is just a little bit better than its equivalent on the MSP430.  Plus, having the 4KB EEPROM is really nice.  The storage Flash is still NAND-type Flash and it still needs wear-leveling, which is hardly worth the effort for such a small piece of memory.
     
    The sole redeeming factor of MSP430
    A major deficiency of STM32L is that there isn't a low-power clock source other than the RTC, so building a low-power asynchronous RTOS is difficult.  But, it is obviously possible.  Moreover, chips like EFM32 are nearly identical to STM32L, except even lower power, and EFM32 has an array of low-power timers.  MSP430 has a much better clocking system for implementing low-power apps, and overall it is a lot easier to work-with than STM32L.  But now that my RTOS is ported, that hurdle is cleared, so the ease-of-use argument is really not a huge deal, in my opinion.
     
    What's left for MSP430?
    Frankly, I'm not bullish on MSP430 anymore.  I've used it for years, I think the architecture is very elegant, and I love the clocking system.  The competition from Cortex-M is just getting to tough for any mid-range "proprietary" MCU architecture to face.  It's not just TI: everyone making competitors to Cortex-M is getting squeezed.  The Wolverine core is a nice move by TI, but it's too little too late.  For the same price as a Wolverine core MSP430, I can get an EFM32 with superior MCU features apart from the FRAM, and similar or even superior low-power features.  These EFM32s have 16KB of SRAM and a really good supply monitor, so all you are really getting with FRAM is a speed-limiter on your CPU (8 MHz).
     
    My conclusion is simple: TI needs to find a way to drop the price on MSP430 so they can compete in the low-end market against AVR8 and PIC, where the MSP430 is faster and lower-power.  Today's mid and high-end MSP430's simply cannot compete against Cortex-M.  TI has always been about beating competition on marketing and fabrication, so I know they can do it, and I'm surprised they haven't.  Clearly, the G-series is a step in that direction, but in my opinion it is really it is the 5-series that they need to cost-optimize.
  2. Like
    Alan reacted to jpnorair in Which MCU?   
    If you are looking at 8/16 bit MCUs, then you are looking at the lower-end MSP430 devices, and these are more power efficient than EFM32 for those sorts of apps.  If you are looking at MSP430F5, EFM32 will trounce it at everything, up and down.  STM32L is often more energy efficient than MSP430F5 is, and EFM32 is more efficient than STM32L.  The one caveat of EFM32 is that it is quite expensive, but MSP430F5 devices aren't usually very cheap, either.
  3. Like
    Alan reacted to jpnorair in Which MCU?   
    Yes, precisely.
     
    WiFi is expensive.  It is power hungry, it forces heavy infrastructure costs because it doesn't scale very well, and the CC3000 is itself an expensive product.  Generally, it is best to avoid for wireless sensor networking unless you're just goofing around, or unless you are making some type of niche-y home automation/networking (HAN) device.
     
    Pretty much any MCU you use is going to be a "drop in the bucket" to the CC3000 in terms of cost and energy requirement.  Rhetorically, I would use a value-line STM32F or some MSP430, depending on which of these two I am more familiar with.  No reason to use a silly, 5V AVR or PIC.  Going STM32L vs. F will save you only ~3uA, which is negligible compared to the WiFi network processor core duty cycle energy.  MSP430, basically the same argument.
  4. Like
    Alan reacted to spirilis in Which MCU?   
    I don't have any experience with STM32 stuff, but others here do so hopefully they'll chime in.  The F5529 LaunchPad sounds like an excellent fit based on the limited description you have so far.  I have the CC3000 boosterpack but haven't exactly got it working yet... seems the existing energia lib et al is a bit half-baked (the base C library sounds like the way to go, I just haven't spent the time to grok it yet).  There's a lot of buzz around it, including Adafruit who sells generic breakout boards for it too.
     
    I guess if you're just reporting sensor data and maybe turning a few things on/off, the MSP430 should be perfect assuming you have a chip with enough resources to drive the wifi stuff.  F5529 should be OK for that imo.  WiFi isn't exactly a power-miserly application though, so a big consideration will be how often it actually has to use the wifi... does it periodically wake up on its own, collect data & transmit?  Or should it be active all the time and waiting for inbound requests?  The latter is substantially more power-hungry due to the need to keep the RF pieces active all the time.  I bet it'd make the MCU choice a smaller piece of the puzzle in that instance.
  5. Like
    Alan got a reaction from Keepcool in Problems to compile my very first msp code   
    When I copied the makefile source from the page it left a single space at the start of every line. Makefiles use tabs to distinguish a block of code under a target so its complaining about this. You'll have to remove all them spaces to get it going.
     
    (The link is here is anyone is curious http://sourceforge.net/apps/mediawiki/mspgcc/index.php?title=Example:Makefile)
     
    If you are new to makefiles that example might be a bit too convoluted to start with.
     
    Here is a simpler example if you prefer. Its not as universal as the example provided but hopefully shows just enough to give you a basic overview.
    https://github.com/alanbarr/msp430-launchpad/blob/master/examples/switchLeds/makefile
    https://github.com/alanbarr/msp430-launchpad/blob/master/examples/switchLeds/main.c
  6. Like
    Alan got a reaction from Keepcool in Problems to compile my very first msp code   
    Sounds like your linker is having some issues.
    If you look for "msp430" in the ubuntu software centre, or in the link you previous posted and make sure you install all the packages. The linker is in binutils which can be installed with a
    sudo apt-get install binutils-msp430
    you should also install
    sudo apt-get install msp430-libc
    sudo apt-get install gcc-msp430
    sudo apt-get install msp430mcu
    sudo apt-get install gdb-msp430
    sudo apt get install mspdebug
     
    However I have some issues with gdb - haven't successfully got it working with the launchpad. GDB isn't too necessary but if you have used it before it allows debugging through C code. mspdebug allows for flashing and debugging but its in assembly.
  7. Like
    Alan got a reaction from Keepcool in Problems to compile my very first msp code   
    Sorry I have never went through the debian site before, I'm happy apt-get'ing from the command line. Did you install all the packages on the debian page? including http://packages.debian.org/sid/zlib1g for example?. The only thing I can think of is you missed a dependency which ubunutu bundled into the install for me.
     
    Also I am not too sure what msp430mcu-config is as I don't seem to have a binary for it - at least in my PATH.
  8. Like
    Alan got a reaction from aalani in MSP430G2553 I2C   
    Hmm I actually just noticed a potential issue with my code. I still have the clock freq hardcoded:
    UCB0BR0 = 12; // fSCL = SMCLK/12 = ~100kHz
     
    So as long as your clock is 1MHz this will be ok and give you ~100 kHz.
     
    So my I2C code doesn't actually use time430.h. - just my example. Its something I'll change in the future.
    The point of this header file is to globally define the clock speed in a macro which can be used in some calibration and delay macros which are defined in this header file.
     
    If you are looking at my example and you have used TIME430_CALIBRATE_CLOCK() you can switch this for the standard DCO macros to calibrate 1Mhz. If you have used TIME430_DELAY_MS() you will have to replace it with an appropriate _delay_cycles call.
     
    If you use my header you need to #define TIME430_CLOCK_FREQ to 1 before you #include the header - either in your makefile OR right before you include it e.g.

    #define TIME430_CLOCK_FREQ 1 #include "time430.h"
     
    If you look at the file
    https://github.com/alanbarr/msp430-launchpad/blob/master/common/inc/time430.h
    you can see whats going on
  9. Like
    Alan got a reaction from aalani in MSP430G2553 I2C   
    I've modified TIs code and split it into functions. Its been a while since I have looked at it admittedly but hopefully the following files might be useful to you. I wrote it for mspgcc there might be some issues with using it with CSS / IAR mainly the interrupts will need changed. The register setups will be the same though.
     
    I2C:
    https://github.com/alanbarr/msp430-launchpad/blob/master/common/src/i2c.c
    https://github.com/alanbarr/msp430-launchpad/blob/master/common/inc/i2c.h
     
    Example:
    https://github.com/alanbarr/msp430-launchpad/blob/master/examples/i2cBitExp4Leds/main.c
  10. Like
    Alan got a reaction from turd in MSP430G2553 I2C   
    I've modified TIs code and split it into functions. Its been a while since I have looked at it admittedly but hopefully the following files might be useful to you. I wrote it for mspgcc there might be some issues with using it with CSS / IAR mainly the interrupts will need changed. The register setups will be the same though.
     
    I2C:
    https://github.com/alanbarr/msp430-launchpad/blob/master/common/src/i2c.c
    https://github.com/alanbarr/msp430-launchpad/blob/master/common/inc/i2c.h
     
    Example:
    https://github.com/alanbarr/msp430-launchpad/blob/master/examples/i2cBitExp4Leds/main.c
  11. Like
    Alan got a reaction from bluehash in MSP430G2553 I2C   
    I've modified TIs code and split it into functions. Its been a while since I have looked at it admittedly but hopefully the following files might be useful to you. I wrote it for mspgcc there might be some issues with using it with CSS / IAR mainly the interrupts will need changed. The register setups will be the same though.
     
    I2C:
    https://github.com/alanbarr/msp430-launchpad/blob/master/common/src/i2c.c
    https://github.com/alanbarr/msp430-launchpad/blob/master/common/inc/i2c.h
     
    Example:
    https://github.com/alanbarr/msp430-launchpad/blob/master/examples/i2cBitExp4Leds/main.c
  12. Like
    Alan reacted to gordon in Updated compile of mspgcc and mspdebug on Linux   
    You can use my build script (attached to this post) (as a starting point) on two conditions:
     
    - I do not wish to provide any kind of support whatsoever regarding this script. It works and works well, has been for quite a long time now, and I am pretty tired of listening to statements to the contrary.
     
    - I do not wish to be associated with this script in any way, shape or form (otherwise #1 is bound to happen)
     
    I am also completely uninterested in any enhancements, bug fixes, colored output, error handling, and whatever else you can think of. Basically, you grab it, do whatever you want with it, and I never want to hear of it again.
     
    If you can live with this, by all means be my guest to re-use it. If you can't, consider the offer void. ("You" means anyone and everyone who wants this piece of code.)
    build-mspgcc.gz
  13. Like
    Alan reacted to RobG in Saving data to flash on power down   
    Here is a simple solution to the problem I had, saving data when power goes down.
    There are two parts needed, a diode (1N4148) and a capacitor (~47uF.)
    The way it works, you isolate main power from MCU and connect capacitor on the MCU's side.
    One of the pins is connected to the main power and will trigger an interrupt.
    In the interrupt routine, we will be saving data to flash.
    This is a simple proof of concept, the final code should include low voltage detection for situations like dying battery.
     

     


     

    #include "msp430g2231.h" unsigned int data = 0; unsigned int * const savedDataPtr = (unsigned int *)(0x1000); void main(void) { WDTCTL = WDTPW + WDTHOLD; P1DIR &= ~BIT1; P1IE |= BIT1; P1IES |= BIT1; P1IFG &= ~BIT1; P1REN |= BIT1; P1OUT &= ~BIT1; P1DIR |= BIT0; P1OUT |= BIT0; data = *savedDataPtr; if(data == 0xFFFF) data = 100; unsigned int counter = data; _bis_SR_register(GIE); while(1) { counter = data; while(counter > 0) { _delay_cycles(1000); counter--; } P1OUT ^= BIT0; } } // Port 1 interrupt service routine #pragma vector=PORT1_VECTOR __interrupt void Port_1(void) { P1OUT &= ~BIT0; data += 100; // Save value FCTL2 = FWKEY + FSSEL0 + FN1; FCTL1 = FWKEY + ERASE; FCTL3 = FWKEY; *savedDataPtr = 0; FCTL1 = FWKEY + WRT; *savedDataPtr = data; FCTL1 = FWKEY; FCTL3 = FWKEY + LOCK; P1IFG &= ~BIT1; }
  14. Like
    Alan reacted to RobG in Font collection   
    Let's start one.
    Here are some fonts I have:
     
    font_5x7.h
    font_8x12.h
    font_9x16.h
    font_11x16.h
  15. Like
    Alan got a reaction from SugarAddict in $4.30 LCD Booster - Sold Out   
    I got my two in the post there.
    Haven't had much time with them, just soldered on some headers and ran RobG's example code on it.
    Have to say I am very impressed with display.
     
    Just wanted to say thanks to SugarAddict and Bluehash
     
    Hopefully I'll get some time with it next week.
     
    Oh and if anyone's keeping count, to my surprise there was a $1 bill tucked away inside Thanks again!
  16. Like
    Alan reacted to RobG in Nokia 7110 Library   
    Here's my version of Nokia 7110 library.
    Just text for now, but graphics will be included later on.
    Enjoy!
     


     
    main.cfont_5x7.h
    sed1565.c
    sed1565.h
  17. Like
    Alan reacted to oPossum in Time & Temperature on Nokia 7110   
    This uses code from Software RTC, Using the internal temperature sensor and Nokia 5110 template class. The code has been modified and refined a bit for this project.
     



     
    main.cpp

    #include #include #include #include #include "nokia7110tl.h" using namespace nokia7110; static const unsigned char ti[] = { 48, 48 / 8, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC, 0xFC,0xFC,0xFC,0xFC,0x00,0x00,0x00,0x00,0x00,0xF0, 0xF0,0xF0,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFC,0xFC,0x3C,0x80,0xFC,0xFD, 0xFD,0xFD,0x3D,0x81,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC, 0xFC,0xFC,0xFC,0xFC,0x00,0x00,0x00,0x00, 0x00,0x1C,0x7C,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC, 0xFC,0xFC,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xF7,0xF0,0xF0,0x00,0xF0,0xFF,0xFF,0xFF, 0xFF,0x0F,0xF0,0xF0,0xF0,0xF0,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xF8,0xF0,0x00,0x00, 0x00,0x00,0x00,0x00,0x01,0x03,0x07,0x3F,0x7F,0xFF, 0xFF,0xFF,0xFF,0xFF,0x7F,0x3F,0x3F,0x7F,0xFF,0xFF, 0xFF,0xFF,0xFF,0x1F,0x00,0x1E,0x1F,0x1F,0x1F,0x1F, 0x01,0x1E,0x1F,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0x7F,0x7F,0x3F,0x3F,0x3F,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x03, 0x0F,0x3F,0xFF,0xFE,0xFE,0xFE,0xFC,0xFC,0xFC,0xFC, 0xFC,0xFC,0xFC,0x7F,0x1F,0x07,0x03,0x03,0x01,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x01,0x07,0x0F,0x0F,0x1F,0x1F,0x3F, 0x3F,0x3F,0x3F,0x1C,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; /* P1.0 Reset P1.3 Temp Sensor (Not used) P2.0 Serial Data P2.1 Backlight P2.2 Chip Select P2.3 Data/Command P2.4 Serial Clock P2.5 Pushbutton */ // P1 static const unsigned LCD_RESET = BIT0; static const unsigned RXD = BIT2; static const unsigned SWITCH = BIT3; // P2 static const unsigned LCD_DATA = BIT0; static const unsigned LCD_BACKLIGHT = BIT1; static const unsigned LCD_CE = BIT2; static const unsigned LCD_DC = BIT3; static const unsigned LCD_CLK = BIT4; static const unsigned LCD_BTN = BIT5; Nokia7110 lcd; void show_time(const struct tm *t) // Show time on LCD { static const char *dow[7] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; int x, w; const char *s; div_t d; if(t->tm_hour < 10) { x = -2; lcd.fill(0, 0, 9, 2, 0); d.rem = t->tm_hour; } else { x = 3; lcd.fill(0, 0, 3, 2, 0); d = div(t->tm_hour, 10); lcd.pd12(d.quot, x, 0); } lcd.pd12(d.rem, x + 11, 0); lcd.pd12(11, x + 22, 0); d = div(t->tm_min, 10); lcd.pd12(d.quot, x + 27, 0); lcd.pd12(d.rem, x + 38, 0); lcd.pd12(11, x + 49, 0); d = div(t->tm_sec, 10); lcd.pd12(d.quot, x + 54, 0); lcd.pd12(d.rem, x + 65, 0); lcd.fill(x + 76, 0, 7 - x, 2, 0); if(t->tm_mon < 9) { x = -5; lcd.fill(0, 2, 6, 2, 0); d.rem = t->tm_mon + 1; } else { x = 0; d = div(t->tm_mon + 1, 10); lcd.pd12(d.quot, x, 2); } lcd.pd12(d.rem, x + 11, 2); lcd.pd12(13, x + 22, 2); d = div(t->tm_mday, 10); lcd.pd12(d.quot, x + 30, 2); lcd.pd12(d.rem, x + 41, 2); lcd.pd12(13, x + 52, 2); d = div(t->tm_year % 100, 10); lcd.pd12(d.quot, x + 60, 2); lcd.pd12(d.rem, x + 71, 2); if(x) lcd.fill(x + 82, 2, 1 - x, 2, 0); s = dow[t->tm_wday]; w = strlen(s) * 6; x = (83 - w) >> 1; lcd.fill(0, 4, x, 1, 0); lcd.print((unsigned char)x, (unsigned char)4, s); x += w; lcd.fill(x, 4, 83 - x, 1, 0); } // Print integer from -999 to 9999 using 12 x 16 font void print_int(int i, const unsigned y) { if(i < -999 || i > 9999) return; const unsigned neg = i < 0; if(neg) i = -i; div_t d; d.quot = i; unsigned x = 48; do { d = div(d.quot, 10); lcd.pd12(d.rem, x -= 12, y); } while(d.quot); if(neg) lcd.pd12(14, x -= 12, y); while(x) lcd.pd12(10, x -= 12, y); } // Print integer from -999 to 9999 using 6 x 8 font void print_int(int i, unsigned x, const unsigned y) { if(i < -999 || i > 9999) return; const unsigned e = x; x += 24; const unsigned neg = i < 0; if(neg) i = -i; div_t d; d.quot = i; do { d = div(d.quot, 10); lcd.print(x -= 6, y, '0' + d.rem); } while(d.quot); if(neg) lcd.print(x -= 6, y, '-'); while(x > e) lcd.print(x -= 6, y, ' '); } void draw_bargraph(int f) { int x, y, bg; char c; unsigned char bgc[9] = { 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF, 0 }; char *bgl[8] = { "90", "80", "70", "60", "50", "40", "30", "20" }; x = 20; // bg = (f - (x - 5)) * 4 / 5; // for(y = 7; y >= 0; --y) { // lcd.pos(83, y); // if(bg < 0) { c = bgc[8]; } else if (bg > 7) { c = bgc[7]; } else { c = bgc[bg]; } lcd.write((unsigned char *)&c, 1, lcd_data); lcd.print(bgl[y], c); bg -= 8; } // } time_t tt; // Time in seconds since epoch unsigned adc; // ADC value #pragma vector = WDT_VECTOR // - Watchdog timer interrupt vector __interrupt void wdt_isr(void) // This interrupt will occur once per second { // ++tt; // Increment time_t __bic_SR_register_on_exit(LPM0_bits); // Wakeup main code } // // #pragma vector = ADC10_VECTOR // ADC conversion complete interrupt __interrupt void ADC10_ISR(void) // { // adc = ADC10MEM; // Read ADC __bic_SR_register_on_exit(LPM0_bits); // Wakeup main code } // int main(void) { int x, y; char c; struct tm ts; int dc, dk, df; // Temperature in degrees C, K, and F WDTCTL = WDTPW | WDTHOLD; P1REN = RXD | SWITCH; P1DIR = LCD_RESET; P1OUT = RXD | SWITCH | LCD_RESET; P2DIR = LCD_DC | LCD_CE | LCD_CLK | LCD_BACKLIGHT | LCD_DATA; P2REN = LCD_BTN; P2OUT = LCD_CLK | LCD_DC | LCD_CE | LCD_BACKLIGHT | LCD_BTN; ADC10CTL0 = 0; // Configure ADC ADC10CTL1 = INCH_10 | ADC10DIV_3; // ADC10CTL0 = SREF_1 | ADC10SHT_3 | REFON | ADC10ON | ADC10IE; ADC10CTL0 |= ADC10IE; // Enable ADC conversion complete interrupt // // 32 kHz xtal loading //BCSCTL3 = XCAP_1; // 6 pF (default) BCSCTL3 = XCAP_2; // 10 pF //BCSCTL3 = XCAP_3; // 12.5 pF // WDTCTL = WDTPW | WDTTMSEL | WDTCNTCL | WDTSSEL; // Use WDT as interval timer IE1 |= WDTIE; // Enable WDT interrupt _EINT(); // Enable interrupts // // Set initial time - there is no UI for this ts.tm_hour = 13; // Hour ts.tm_min = 37; // Minute ts.tm_sec = 42; // Second ts.tm_mon = 3; // Month (0 based!) ts.tm_mday = 20; // Day of Month ts.tm_year = 2012 - 1900; // Year ts.tm_wday = 5; // Day of Week - Not used by mktime() ts.tm_yday = 0; // Not used by mktime() ts.tm_isdst = 0; // DST flag - Not used by rtc_tick() // tt = mktime(&ts); // Convert tm struct to time_t // lcd.reset(); lcd.init(); lcd.clear(); lcd.print(30, 6, "MSP430"); lcd.print(18, 7, "Nokia 7110"); for(x = -47; x < 24; ++x) { lcd.bitmap(ti, x, 0); __delay_cycles(20000); } __delay_cycles(2000000); for(; x < 96; ++x) { lcd.bitmap(ti, x, 0); __delay_cycles(20000); } lcd.clear(); lcd.print(9, 7, "Character Set"); x = y = 0; lcd.pos(x, y); for(c = 32; c < 128; ++c) { lcd.print(c); if(++x >= 16) x = 0, lcd.pos(x, ++y); } __delay_cycles(3000000); lcd.clear(); ts.tm_hour = ts.tm_min = ts.tm_sec = 88; ts.tm_mon = 87; ts.tm_mday = ts.tm_year = 88; ts.tm_wday = 5; show_time(&ts); lcd.pd12(15, 48, 5); lcd.pd12(17, 59, 5); lcd.print(24, 7, "\x7F""C"); lcd.print(66, 7, "\x7F""K"); print_int(8888, 5); print_int(8888, 0, 7); print_int(8888, 42, 7); for(x = 15; x < 96; ++x) draw_bargraph(x); __delay_cycles(3000000); lcd.clear(); // lcd.pd12(15, 48, 5); // Degrees lcd.pd12(17, 59, 5); // F lcd.print(24, 7, "\x7F""C"); // C lcd.print(66, 7, "\x7F""K"); // K // for(; { // for-ever show_time(localtime(&tt)); // Convert time_t to tm struct and show on LCD __bis_SR_register(LPM0_bits + GIE); // Sleep until WDT interrupt ADC10CTL0 |= (ENC | ADC10SC); // Begin ADC conversion __bis_SR_register(LPM0_bits + GIE); // Sleep until conversion complete // // Convert to temperature dc = ((27069L * adc) - 18169625L) >> 16; // Vref = 1.5V dk = ((27069L * adc) - 268467L) >> 16; // Vref = 1.5V df = ((48724L * adc) - 30634388L) >> 16; // Vref = 1.5V // // Display on LCD print_int(df, 5); // Degrees F print_int(dc, 0, 7); // Degrees C print_int(dk, 42, 7); // Degrees K draw_bargraph(df); // Deg F Bargraph } // return 0; }
     
    nokia7110tl.h - C++ template class for Nokia 7110 (SED1565)

    namespace nokia7110 { unsigned char PNONE; typedef enum { lcd_command = 0, // Array of one or more commands lcd_data = 1, // Array of one or more bytes of data lcd_data_repeat = 2 // One byte of data repeated } lcd_cmd_type; template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> struct Nokia7110 { void write(const unsigned char *cmd, unsigned len, const lcd_cmd_type type = lcd_data); void reset(void); void init(void); void home(void); void pos(unsigned char x, unsigned char y); void clear(unsigned char x = 0); void fill(unsigned x, unsigned y, unsigned w, unsigned h, unsigned char z); void bitmap(const unsigned char *bmp, signed char x, signed char y, unsigned char w, unsigned char h); inline void bitmap(const unsigned char *bmp, signed char x, signed char y) { bitmap(bmp + 2, x, y, bmp[0], bmp[1]); }; void print(char c); inline void print(unsigned char x, unsigned char y, char c) { pos(x, y); print(c); }; void print(const char *s); inline void print(unsigned char x, unsigned char y, const char *s) { pos(x, y); print(s); }; void print(const char *s, unsigned char m); void printv(unsigned char x, unsigned char y, char *s); void pd12(unsigned n, unsigned x, unsigned y); }; template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::write(const unsigned char *cmd, unsigned len, const lcd_cmd_type type) { register unsigned mask; if(&_EP != &PNONE) _EP &= ~_CE; do { mask = 0x0080; do { if(*cmd & mask) { _SP |= _DATA; _SP &= ~_CLK; } else { _SP &= ~(_CLK | _DATA); } _SP |= _CLK; mask >>= 1; } while(!(mask & 1)); if(&_CP == &PNONE) { __delay_cycles(_DC); } else { if(!type) _CP &= ~_DC; } if(*cmd & mask) { _SP |= _DATA; _SP &= ~_CLK; } else { _SP &= ~(_CLK | _DATA); } _SP |= _CLK; if(&_CP != &PNONE) _CP |= _DC; if(!(type & 2)) ++cmd; } while(--len); if(&_EP != &PNONE) _EP |= _CE; } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::reset(void) { if(&_RP == &PNONE) { // --- Set initial state of CLK, DC and CE as needed // * = output used for reset if(&_CP == &PNONE) { if(&_EP != &PNONE) { // CLK*, DATA, CE _EP |= _CE; } // else // CLK*, DATA } else { if(&_EP != &PNONE) { // CLK, DATA, DC*, CE if(&_SP == &_EP) { _SP |= (_CLK | _CE); } else { _SP |= _CLK; _EP |= _CE; } } else { // CLK, DATA, DC* _SP |= _CLK; } } // --- Reset pulse on CLK or DC as needed if(&_CP == &PNONE) { // No DC port, use CLK to reset _SP &= ~_CLK; __delay_cycles(_RD); _SP |= _CLK; } else { // Use DC to reset _CP &= ~_DC; __delay_cycles(_RD); _CP |= _DC; } } else { _RP &= ~_RST; if(&_EP != &PNONE) { if(&_SP == &_EP) { _SP |= (_CLK | _CE); } else { _SP |= _CLK; _EP |= _CE; } } else { _SP |= _CLK; } __delay_cycles(_RD); _RP |= _RST; } __delay_cycles(_RD); } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::init(void) { static const unsigned char init[] = { 0xA6, //Display: Normal 0xA3, //LCD Bias Settings: 1/7 0xA1, //ADC Selection: Reverse 0xC0, //Common Output: Normal Direction //0xC8, //Common Output: Upside Down 0x22, //Set the V5 output Voltage 0x81, //Set Electronic Volume Register 0x2E, //Power Controller Set // Booster circuit: ON // Voltage regulator circuit: ON // Voltage follower circuit: OFF 0x2F, //Power Controller Set // Voltage follower circuit: ON 0xE3, //Non-OPeration Command 0x40, //Set the start line 0xAF, //LCD On //0xA5, //Display All Points: ON 0xA4, //Display All Points: NORMAL }; write(init, sizeof(init), lcd_command); } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::home(void) { static const unsigned char home[] = { 0xB0, 0x11, 0x02 }; write(home, sizeof(home), lcd_command); } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::pos(unsigned char x, unsigned char y) { unsigned char c[3]; x += 18; c[0] = 0xB0 | y; c[1] = 0x10 | (x >> 4); c[2] = x & 0x0F; write(c, sizeof(c), lcd_command); } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::clear(unsigned char x) { for(unsigned y = 0; y < 9; ++y) { pos(0, y); write(&x, 96, lcd_data_repeat); } } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::fill(unsigned x, unsigned y, unsigned w, unsigned h, unsigned char z) { unsigned yy = y + h; unsigned char c[3]; x += 18; c[1] = 0x10 | (x >> 4); c[2] = (x & 0x0F); for(;y < yy; ++y) { c[0] = 0xB0 | y; write(c, sizeof(c), lcd_command); write(&z, w, lcd_data_repeat); } } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::bitmap(const unsigned char *bmp, signed char x, signed char y, unsigned char w, unsigned char h) { unsigned char c[3]; unsigned char ww; if(x < 0) { ww = w + x; bmp -= x; x = 0; } else if(x + w >= 96) { ww = (96 - x); } else { ww = w; } x += 18; c[0] = 0xB0 | y; c[1] = 0x10 | (x >> 4); c[2] = x & 0x0F; while(h--) { write(c, sizeof(c), lcd_command); write(bmp, ww); bmp += w; ++c[0]; } } static const unsigned char font[96][5] = { 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00, 0x00, 0x5F, 0x00, 0x00, // ! 0x00, 0x07, 0x00, 0x07, 0x00, // " 0x14, 0x7F, 0x14, 0x7F, 0x14, // # 0x24, 0x2A, 0x7F, 0x2A, 0x12, // $ 0x23, 0x13, 0x08, 0x64, 0x62, // % 0x36, 0x49, 0x56, 0x20, 0x50, // & 0x00, 0x08, 0x07, 0x03, 0x00, // ' 0x00, 0x1C, 0x22, 0x41, 0x00, // ( 0x00, 0x41, 0x22, 0x1C, 0x00, // ) 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, // * 0x08, 0x08, 0x3E, 0x08, 0x08, // + 0x00, 0x40, 0x38, 0x18, 0x00, // , 0x08, 0x08, 0x08, 0x08, 0x08, // - 0x00, 0x00, 0x60, 0x60, 0x00, // . 0x20, 0x10, 0x08, 0x04, 0x02, // / 0x3E, 0x51, 0x49, 0x45, 0x3E, // 0 0x00, 0x42, 0x7F, 0x40, 0x00, // 1 0x42, 0x61, 0x51, 0x49, 0x46, // 2 0x21, 0x41, 0x49, 0x4D, 0x33, // 3 0x18, 0x14, 0x12, 0x7F, 0x10, // 4 0x27, 0x45, 0x45, 0x45, 0x39, // 5 0x3C, 0x4A, 0x49, 0x49, 0x30, // 6 0x41, 0x21, 0x11, 0x09, 0x07, // 7 0x36, 0x49, 0x49, 0x49, 0x36, // 8 0x06, 0x49, 0x49, 0x29, 0x1E, // 9 0x00, 0x00, 0x14, 0x00, 0x00, // : 0x00, 0x00, 0x40, 0x34, 0x00, // ; 0x00, 0x08, 0x14, 0x22, 0x41, // < 0x14, 0x14, 0x14, 0x14, 0x14, // = 0x00, 0x41, 0x22, 0x14, 0x08, // > 0x02, 0x01, 0x51, 0x09, 0x06, // ? 0x3E, 0x41, 0x5D, 0x59, 0x4E, // @ 0x7C, 0x12, 0x11, 0x12, 0x7C, // A 0x7F, 0x49, 0x49, 0x49, 0x36, // B 0x3E, 0x41, 0x41, 0x41, 0x22, // C 0x7F, 0x41, 0x41, 0x41, 0x3E, // D 0x7F, 0x49, 0x49, 0x49, 0x41, // E 0x7F, 0x09, 0x09, 0x09, 0x01, // F 0x3E, 0x41, 0x49, 0x49, 0x7A, // G 0x7F, 0x08, 0x08, 0x08, 0x7F, // H 0x00, 0x41, 0x7F, 0x41, 0x00, // I 0x20, 0x40, 0x41, 0x3F, 0x01, // J 0x7F, 0x08, 0x14, 0x22, 0x41, // K 0x7F, 0x40, 0x40, 0x40, 0x40, // L 0x7F, 0x02, 0x1C, 0x02, 0x7F, // M 0x7F, 0x04, 0x08, 0x10, 0x7F, // N 0x3E, 0x41, 0x41, 0x41, 0x3E, // O 0x7F, 0x09, 0x09, 0x09, 0x06, // P 0x3E, 0x41, 0x51, 0x21, 0x5E, // Q 0x7F, 0x09, 0x19, 0x29, 0x46, // R 0x26, 0x49, 0x49, 0x49, 0x32, // S 0x01, 0x01, 0x7F, 0x01, 0x01, // T 0x3F, 0x40, 0x40, 0x40, 0x3F, // U 0x1F, 0x20, 0x40, 0x20, 0x1F, // V 0x3F, 0x40, 0x38, 0x40, 0x3F, // W 0x63, 0x14, 0x08, 0x14, 0x63, // X 0x03, 0x04, 0x78, 0x04, 0x03, // Y 0x61, 0x51, 0x49, 0x45, 0x43, // Z 0x00, 0x7F, 0x41, 0x41, 0x41, // [ 0x02, 0x04, 0x08, 0x10, 0x20, // '\' 0x00, 0x41, 0x41, 0x41, 0x7F, // ] 0x04, 0x02, 0x01, 0x02, 0x04, // ^ 0x80, 0x80, 0x80, 0x80, 0x80, // _ 0x00, 0x03, 0x07, 0x08, 0x00, // ' 0x20, 0x54, 0x54, 0x54, 0x78, // a 0x7F, 0x28, 0x44, 0x44, 0x38, // b 0x38, 0x44, 0x44, 0x44, 0x28, // c 0x38, 0x44, 0x44, 0x28, 0x7F, // d 0x38, 0x54, 0x54, 0x54, 0x18, // e 0x00, 0x08, 0x7E, 0x09, 0x02, // f 0x18, 0xA4, 0xA4, 0xA4, 0x7C, // g 0x7F, 0x08, 0x04, 0x04, 0x78, // h 0x00, 0x44, 0x7D, 0x40, 0x00, // i 0x00, 0x20, 0x40, 0x40, 0x3D, // j 0x00, 0x7F, 0x10, 0x28, 0x44, // k 0x00, 0x41, 0x7F, 0x40, 0x00, // l 0x7C, 0x04, 0x78, 0x04, 0x78, // m 0x7C, 0x08, 0x04, 0x04, 0x78, // n 0x38, 0x44, 0x44, 0x44, 0x38, // o 0xFC, 0x18, 0x24, 0x24, 0x18, // p 0x18, 0x24, 0x24, 0x18, 0xFC, // q 0x7C, 0x08, 0x04, 0x04, 0x08, // r 0x48, 0x54, 0x54, 0x54, 0x24, // s 0x04, 0x04, 0x3F, 0x44, 0x24, // t 0x3C, 0x40, 0x40, 0x20, 0x7C, // u 0x1C, 0x20, 0x40, 0x20, 0x1C, // v 0x3C, 0x40, 0x30, 0x40, 0x3C, // w 0x44, 0x28, 0x10, 0x28, 0x44, // x 0x4C, 0x90, 0x90, 0x90, 0x7C, // y 0x44, 0x64, 0x54, 0x4C, 0x44, // z 0x00, 0x08, 0x36, 0x41, 0x00, // { 0x00, 0x00, 0x77, 0x00, 0x00, // | 0x00, 0x41, 0x36, 0x08, 0x00, // } 0x02, 0x01, 0x02, 0x04, 0x02, // ~ 0x00, 0x06, 0x09, 0x09, 0x06, // degrees }; template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::print(char c) { write(&font[c - 32][0], 5); write(&font[0][0], 1); } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::print(const char *s) { while(*s) { write(&font[*s - 32][0], 5); write(&font[0][0], 1); ++s; } } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::print(const char *s, unsigned char m) { unsigned char c; while(*s) { c = font[*s - 32][0] ^ m; write(&c, 1); c = font[*s - 32][1] ^ m; write(&c, 1); c = font[*s - 32][2] ^ m; write(&c, 1); c = font[*s - 32][3] ^ m; write(&c, 1); c = font[*s - 32][4] ^ m; write(&c, 1); write(&m, 1); ++s; } } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::printv(unsigned char x, unsigned char y, char *s) { while(*s) { pos(x, y); ++y; write(&font[*s - 32][0], 5); write(&font[0][0], 1); ++s; } } static const unsigned char num11x16[19][11 * 2] = { 0x00,0xF0,0xFC,0xFE,0x06,0x02,0x06,0xFE,0xFC,0xF0,0x00, // 0 0x00,0x07,0x1F,0x3F,0x30,0x20,0x30,0x3F,0x1F,0x07,0x00, 0x00,0x00,0x08,0x0C,0xFC,0xFE,0xFE,0x00,0x00,0x00,0x00, // 1 0x00,0x20,0x20,0x20,0x3F,0x3F,0x3F,0x20,0x20,0x20,0x00, 0x00,0x0C,0x0E,0x06,0x02,0x02,0x86,0xFE,0x7C,0x38,0x00, // 2 0x00,0x30,0x38,0x3C,0x36,0x33,0x31,0x30,0x30,0x38,0x00, 0x00,0x0C,0x0E,0x86,0x82,0x82,0xC6,0xFE,0x7C,0x38,0x00, // 3 0x00,0x18,0x38,0x30,0x20,0x20,0x31,0x3F,0x1F,0x0E,0x00, 0x00,0x00,0xC0,0x20,0x18,0x04,0xFE,0xFE,0xFE,0x00,0x00, // 4 0x00,0x03,0x02,0x02,0x02,0x22,0x3F,0x3F,0x3F,0x22,0x02, 0x00,0x00,0x7E,0x7E,0x46,0x46,0xC6,0xC6,0x86,0x00,0x00, // 5 0x00,0x18,0x38,0x30,0x20,0x20,0x30,0x3F,0x1F,0x0F,0x00, 0x00,0xC0,0xF0,0xF8,0xFC,0x4C,0xC6,0xC2,0x82,0x00,0x00, // 6 0x00,0x0F,0x1F,0x3F,0x30,0x20,0x30,0x3F,0x1F,0x0F,0x00, 0x00,0x06,0x06,0x06,0x06,0x06,0xC6,0xF6,0x3E,0x0E,0x00, // 7 0x00,0x00,0x00,0x30,0x3C,0x0F,0x03,0x00,0x00,0x00,0x00, 0x00,0x38,0x7C,0xFE,0xC6,0x82,0xC6,0xFE,0x7C,0x38,0x00, // 8 0x00,0x0E,0x1F,0x3F,0x31,0x20,0x31,0x3F,0x1F,0x0E,0x00, 0x00,0x78,0xFC,0xFE,0x86,0x02,0x86,0xFE,0xFC,0xF8,0x00, // 9 0x00,0x00,0x00,0x21,0x21,0x31,0x1D,0x1F,0x0F,0x03,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x70,0x70,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // : 0x00,0x0E,0x0E,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // . 0x00,0x38,0x38,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0xC0,0x30,0x0C,0x00,0x00,0x00,0x00, // / 0x00,0x30,0x0C,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, // - 0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x00,0x18,0x3C,0x66,0x66,0x3C,0x18,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xF0,0xF8,0x0C,0x06,0x02,0x02,0x02,0x02,0x0E,0x0C,0x00, // C 0x03,0x07,0x0C,0x18,0x10,0x10,0x10,0x10,0x1C,0x0C,0x00, 0xFE,0xFE,0x42,0x42,0x42,0x42,0x42,0x42,0x00,0x00,0x00, // F 0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xFE,0xFE,0x40,0xE0,0xB0,0x18,0x0C,0x06,0x02,0x00,0x00, // K 0x1F,0x1F,0x00,0x00,0x01,0x03,0x06,0x0C,0x18,0x10,0x00 }; template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::pd12(unsigned n, unsigned x, unsigned y) { pos(x, y); write(num11x16[n], 11, lcd_data); pos(x, ++y); write(num11x16[n] + 11, 11, lcd_data); } } // namespace
  18. Like
    Alan reacted to SugarAddict in $4.30 LCD Booster - Sold Out   
    Store Link : The $4.30 LCD BoosterPack - Limited Edition
     
    So I've been working on this for a little while now... I'll get a prototype of the mounting spacer from the CNC shop around the 9th... I have some boards already that were made purely for testing the footprint, lcd, and code. I've already got a batch of the production PCB's on order that are to make sure everything is good before I order a crapload of them... I'm looking at doing 100 of these.
     



    Rob-LCDBack.pdf <-- This is the mounting spacer's general idea in 2d, working with the CNC to get it all perfect.
     
    I will be using the Nokia 7110 LCD... dipmicro still has a fair stock of them, I'm going to order 100 of them when I get my next paycheck.
     
    Thoughts?
     
    I will be taking a minor loss to make this happen at $4.30 each, it's still cheaper than a day at the slopes!
  19. Like
    Alan reacted to turd in Nokia 5110 lcd with mspgcc   
    Just a simple test of the Nokia 5110 lcd with mspgcc
     

     
    nokiatest.c

    #include #include //Include font file const int sclk = BIT0; //LCD clock line (clocked on falling edge) const int sda = BIT1; //LCD data line (MSB first) const int dc = BIT2; //LCD mode select (low for instruction and high for data) const int cs = BIT3; //LCD chip select (low for select) const int rst = BIT4; //LCD reset (low for reset) const int draw = 1; //Used to select data mode const int inst = 0; //Used to select instruction mode void init_lcd(void); //Initialise LCD void shift_out(unsigned int, unsigned char);//SPI void delay(unsigned int); void main(void) { WDTCTL = WDTPW + WDTHOLD; //Put watchdog timer on hold BCSCTL1 = CALBC1_1MHZ; //Set frequency to 16MHZ DCOCTL = CALDCO_1MHZ; P1DIR = sclk | sda | dc | cs | rst; //Initialise output pins init_lcd(); //Initialise LCD shift_out(inst, 128); //Move cursor to start shift_out(inst, 64); //of first line unsigned int i; for(i = 0; i < 455; ++i) //Shift out all characters { shift_out(draw, font[i]); } while(1) //Do nothing in a loop { } } void init_lcd(void) { P1OUT &= ~(sclk | sda | dc | cs | rst); //Set all outputs low delay(50000); //Wait for LCD to reset P1OUT |= rst; //Deactivate reset P1OUT &= ~cs; //Set chip select low to select LCD shift_out(inst, 0b00100000); //function set: chip is active, horizontal addressing, use basic instruction set shift_out(inst, 0b00001100); //Display control: normal mode unsigned int i; for(i = 0; i < 504; ++i) //Shift out zeros to whole screen to clear { shift_out(draw, 0x00); } P1OUT |= cs; //Set chip select high to deselect LCD } void shift_out(unsigned int ints_draw, unsigned char data_byte) { if(ints_draw == inst) //Set dc (mode) line low if inst is used { P1OUT &= ~dc; } else if(ints_draw == draw) //Set dc (mode) line high if draw is used { P1OUT |= dc; } P1OUT &= ~cs; //Set chip select low to select LCD unsigned char i; for(i = 0; i <= 7; i++) { P1OUT &= ~sclk; //Set clock line low if(data_byte > 127) //If most significant bit is 1 set data line high { P1OUT |= sda; } else if(data_byte < 128) //If most significant bit is 0 set data line low { P1OUT &= ~sda; } P1OUT |= sclk; //Bring clock line high to shift out bit data_byte = data_byte << 1; //shift bits in data_byte left } P1OUT |= cs; //Set chip select high to deselect LCD } void delay(unsigned int time) { unsigned int i; for(i = 0; i < time; i++) //Waste time { } }
     
    lcdfont.h

    const unsigned char font[] = { 0x00, 0x00, 0x00, 0x00, 0x00, // sp 0x00, 0x00, 0x2f, 0x00, 0x00, // ! 0x00, 0x07, 0x00, 0x07, 0x00, // " 0x14, 0x7f, 0x14, 0x7f, 0x14, // # 0x24, 0x2a, 0x7f, 0x2a, 0x12, // $ 0xc4, 0xc8, 0x10, 0x26, 0x46, // % 0x36, 0x49, 0x55, 0x22, 0x50, // & 0x00, 0x05, 0x03, 0x00, 0x00, // ' 0x00, 0x1c, 0x22, 0x41, 0x00, // ( 0x00, 0x41, 0x22, 0x1c, 0x00, // ) 0x14, 0x08, 0x3E, 0x08, 0x14, // * 0x08, 0x08, 0x3E, 0x08, 0x08, // + 0x00, 0x00, 0x50, 0x30, 0x00, // , 0x10, 0x10, 0x10, 0x10, 0x10, // - 0x00, 0x60, 0x60, 0x00, 0x00, // . 0x20, 0x10, 0x08, 0x04, 0x02, // / 0x3E, 0x51, 0x49, 0x45, 0x3E, // 0 0x00, 0x42, 0x7F, 0x40, 0x00, // 1 0x42, 0x61, 0x51, 0x49, 0x46, // 2 0x21, 0x41, 0x45, 0x4B, 0x31, // 3 0x18, 0x14, 0x12, 0x7F, 0x10, // 4 0x27, 0x45, 0x45, 0x45, 0x39, // 5 0x3C, 0x4A, 0x49, 0x49, 0x30, // 6 0x01, 0x71, 0x09, 0x05, 0x03, // 7 0x36, 0x49, 0x49, 0x49, 0x36, // 8 0x06, 0x49, 0x49, 0x29, 0x1E, // 9 0x00, 0x36, 0x36, 0x00, 0x00, // : 0x00, 0x56, 0x36, 0x00, 0x00, // ; 0x08, 0x14, 0x22, 0x41, 0x00, // < 0x14, 0x14, 0x14, 0x14, 0x14, // = 0x00, 0x41, 0x22, 0x14, 0x08, // > 0x02, 0x01, 0x51, 0x09, 0x06, // ? 0x32, 0x49, 0x59, 0x51, 0x3E, // @ 0x7E, 0x11, 0x11, 0x11, 0x7E, // A 0x7F, 0x49, 0x49, 0x49, 0x36, // B 0x3E, 0x41, 0x41, 0x41, 0x22, // C 0x7F, 0x41, 0x41, 0x22, 0x1C, // D 0x7F, 0x49, 0x49, 0x49, 0x41, // E 0x7F, 0x09, 0x09, 0x09, 0x01, // F 0x3E, 0x41, 0x49, 0x49, 0x7A, // G 0x7F, 0x08, 0x08, 0x08, 0x7F, // H 0x00, 0x41, 0x7F, 0x41, 0x00, // I 0x20, 0x40, 0x41, 0x3F, 0x01, // J 0x7F, 0x08, 0x14, 0x22, 0x41, // K 0x7F, 0x40, 0x40, 0x40, 0x40, // L 0x7F, 0x02, 0x0C, 0x02, 0x7F, // M 0x7F, 0x04, 0x08, 0x10, 0x7F, // N 0x3E, 0x41, 0x41, 0x41, 0x3E, // O 0x7F, 0x09, 0x09, 0x09, 0x06, // P 0x3E, 0x41, 0x51, 0x21, 0x5E, // Q 0x7F, 0x09, 0x19, 0x29, 0x46, // R 0x46, 0x49, 0x49, 0x49, 0x31, // S 0x01, 0x01, 0x7F, 0x01, 0x01, // T 0x3F, 0x40, 0x40, 0x40, 0x3F, // U 0x1F, 0x20, 0x40, 0x20, 0x1F, // V 0x3F, 0x40, 0x38, 0x40, 0x3F, // W 0x63, 0x14, 0x08, 0x14, 0x63, // X 0x07, 0x08, 0x70, 0x08, 0x07, // Y 0x61, 0x51, 0x49, 0x45, 0x43, // Z 0x00, 0x7F, 0x41, 0x41, 0x00, // [ 0x55, 0x2A, 0x55, 0x2A, 0x55, // 55 0x00, 0x41, 0x41, 0x7F, 0x00, // ] 0x04, 0x02, 0x01, 0x02, 0x04, // ^ 0x40, 0x40, 0x40, 0x40, 0x40, // _ 0x00, 0x01, 0x02, 0x04, 0x00, // ' 0x20, 0x54, 0x54, 0x54, 0x78, // a 0x7F, 0x48, 0x44, 0x44, 0x38, // b 0x38, 0x44, 0x44, 0x44, 0x20, // c 0x38, 0x44, 0x44, 0x48, 0x7F, // d 0x38, 0x54, 0x54, 0x54, 0x18, // e 0x08, 0x7E, 0x09, 0x01, 0x02, // f 0x0C, 0x52, 0x52, 0x52, 0x3E, // g 0x7F, 0x08, 0x04, 0x04, 0x78, // h 0x00, 0x44, 0x7D, 0x40, 0x00, // i 0x20, 0x40, 0x44, 0x3D, 0x00, // j 0x7F, 0x10, 0x28, 0x44, 0x00, // k 0x00, 0x41, 0x7F, 0x40, 0x00, // l 0x7C, 0x04, 0x18, 0x04, 0x78, // m 0x7C, 0x08, 0x04, 0x04, 0x78, // n 0x38, 0x44, 0x44, 0x44, 0x38, // o 0x7C, 0x14, 0x14, 0x14, 0x08, // p 0x08, 0x14, 0x14, 0x18, 0x7C, // q 0x7C, 0x08, 0x04, 0x04, 0x08, // r 0x48, 0x54, 0x54, 0x54, 0x20, // s 0x04, 0x3F, 0x44, 0x40, 0x20, // t 0x3C, 0x40, 0x40, 0x20, 0x7C, // u 0x1C, 0x20, 0x40, 0x20, 0x1C, // v 0x3C, 0x40, 0x30, 0x40, 0x3C, // w 0x44, 0x28, 0x10, 0x28, 0x44, // x 0x0C, 0x50, 0x50, 0x50, 0x3C, // y 0x44, 0x64, 0x54, 0x4C, 0x44 }; // z
    The Font was found here: http://homepage.ntlworld.com/c.lewis19/nokia.htm
     
    The Make file:

    CC=msp430-gcc CFLAGS= -Wall -g -mmcu=msp430x2012 OBJS=nokiatest.o all: $(OBJS) $(CC) $(CFLAGS) -o nokiatest.elf $(OBJS) %.o: %.c $(CC) $(CFLAGS) -c $< clean: rm -fr nokiatest.elf $(OBJS)
     
    (Change lcdfont.c to lcdfont.h)
    nokiatest.c
    lcdfont.c
  20. Like
    Alan reacted to nuetron in Using the reset pin to power up/down/reset   
    Hi all,
    This is a small program to toggle the launchpad LEDs with the RESET pin on your favorite micro.
    It can also be used to put your system into sleep mode, while retaining the ability to reset the msp.
     
    If you hold the reset button down for five seconds or more, the micro will reset.
    If you hold it for under five seconds, the green LED will toggle once.
     

    #include "msp430g2211.h" #define LED1_TOGGLE P1OUT ^= BIT0 #define LED1_ON P1OUT |= BIT0 #define LED1_OFF P1OUT &= ~BIT0 #define LED2_TOGGLE P1OUT ^= BIT6 #define LED2_ON P1OUT |= BIT6 #define LED2_OFF P1OUT &= ~BIT6 void main(void) { WDTCTL = WDT_MDLY_32 | WDTNMI | WDTNMIES; IE1 |= WDTIE+NMIIE; // Enable the NMI and WDT interrupts P1OUT = 0xFF; P1DIR = 0x77; P1REN = 0x88; P2DIR = 0; P2SEL = 0; _EINT(); } #pragma vector = WDT_VECTOR __interrupt void NMI_enable(void){ IE1 |= NMIIE; // enable the non-maskable reset pin interrupt, } // seems it is turned off after each use #pragma vector = NMI_VECTOR __interrupt void powermode(void){ //>>>>switch BIT7 from what ever it is usually used for, connect it to RESET<<<< char time; for(time=0; time<50 && !(P1IN & BIT7); time++){ // poll BIT7 during the loop __delay_cycles(100000); LED1_TOGGLE; // toggle the red launchpad LED } if(time>48){ // if held down for five seconds WDTCTL = time; // restart system } else LED2_TOGGLE; // toggle the green launchpad LED LED1_OFF; IFG1 &= ~WDTIFG+NMIIFG; // clear the NMI and WDT interrupt flags }
  21. Like
    Alan got a reaction from GeekDoc in About the MSP430 clocks.   
    There aren't as many clocks as that per-say. The DCO, VLO and LFX (ext. crystal) are the actual hardware clock sources.
    ACLK, MCLK and SMCLK are clock signals which are sourced from the DCO, VLO and LFX.
    You generally setup which signal uses which clock source at the start of the program, and from then on identify the clocks via the signals.
    The user guide goes into more detail on this, and http://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=2&ved=0CCoQFjAB&url=http%3A%2F%2Fwww.ccs.neu.edu%2Fhome%2Fnoubir%2FCourses%2FCSU610%2FS07%2FMSP430-Clock-Timers.pdf&ei=PhdIT4GUFoaf8gPnzKixDg&usg=AFQjCNG3qbaODjBAmoYOfGMcgWblWWB_Qg&sig2=-FIaptUpqsviofiIrBKZgQ provides a brief overview and some code examples.
  22. Like
    Alan got a reaction from OppaErich in [solved] delay loop doesn't get called   
    Try the above or try declaring tick as a volatile variable.
  23. Like
    Alan reacted to bluehash in MSPGCC and C++?   
    Today I learned that ThisIsKnownAsCamelCase. :!!!:
  24. Like
    Alan reacted to pabigot in Efficient Code   
    Implement it in different ways, build it with a variety of compiler options, examine the generated code, and pick the one you like best. Be prepared to redo this next time you update your compiler.
     
    For me, "best" is whichever one is easiest to understand, because maintainability is more important than minor speed improvements and the compiler pretty much always does something sensible,. (And if it doesn't, I fix the compiler, but then that's me....)
     
    Seriously. Compilers these days do so much analysis that unless whole function is trivial there's really no point trying to guess what's going to turn out to be best, and whatever you pick today may change tomorrow.
  25. Like
    Alan reacted to Rickta59 in Efficient Code   
    You didn't mention which compiler you are using. If you are using msp430-gcc you should look at the
    'msp430-objdump -S' command to view the compiler generated code. On CCS, there are check boxes that will
    output the mixed C + asm code. Make sure you are using compiler optimization before you bother to look.
     
    naken430util will give you cycle counts to help you decide which code is better.
     
    -rick
×
×
  • Create New...