Jump to content

nuetron

Members
  • Content Count

    382
  • Joined

  • Last visited

  • Days Won

    4

Reputation Activity

  1. Like
    nuetron got a reaction from GeekDoc in Anyone notice the 8-pin MSP430 yet?   
    Since those pins in the registers aren't used, we could use the register bits as spare bools:

    if(5 > some_condition < 10) P1OUT |= BIT0; else P1OUT &= ~BIT0; ... ... (P1OUT & BIT0) ? (turn_motor_left()) : (turn_motor_right());
  2. Like
    nuetron got a reaction from GeekDoc in HD44780 LCD Library (16x2 and other models)   
    Ah, I missed a line. Here is the corrected version of that command in context with this program:
    rs ? (P1OUT |= RS) : (P1OUT &= ~RS); Thanks for catching that. I'll fix it so other people don't stumble on it.
     
    There had been several programs I was working with at the time, jumping from program to program that used almost the same functions. In one of those programs, I used a char variable as an 8-bit compact set of bool variables. A char and a bool use the same amount of ram (8 bits), but a bool is used for the least significant bit, and the rest are truncated. I had several global bools, but little ram. So I used a char to hold 8 bools, and I toggled the bit I needed, and read that bit when required, then determined whether it was true or false.
     
    I could even use that 8 bits as 4 bools and a 4-bit counter. There are all kinds of ways to compress things.
  3. Like
    nuetron reacted to mochouinard in HD44780 LCD Library (16x2 and other models)   
    Actually, I wanted it to be that way. And wont be changing it
     
    All MSP430 program are REALLY small anyway, there is really no need to shorten the name of functions and variable. I do work on million of line of code software... And in those shorter name for some stuff that come few thousand time are useful. But in this case, it doesn't. You will can run out of flash within a few minute at typing even with those long name anyway...
     
    It actually welcome to have longer descriptive information for function name. The goal was not just to make it work, but also provide details information for all the configuration option. Even option that had was set by default, I created define name for it so it clear what information is used. It not needed to use them, but it make it clearer for people starting with it to understand what going on.
     
    And by that, the code I made can read alot like the datasheet of HD44780. I used the same time range specified, the same name for the different function you can call... I've actually decided to write it this way because other people lcd lib were not written this way and not functional, and what they did didn't fully match the datasheet... So it was hard to understand what they did wrong.
     
    My goal was also to keep the footprint small. So compiled with mspgcc, the size is 420byte. Lot of optimization is left to be done, but I'm ok for the moment.
     
    It not perfect, but does the job for me and is a much better design to actually compare with the datasheet.
     
    But what great, is everyone can provide their own flavor here I did this for me and to help my dad (who had issue with current people code especially because they just seem to do something but with no flexibility / details of what they are actually doing).
     
    There is things I don't like in my code rightnow, and the primary one is the fact you need to edit the .h to change the pin / port usage. I need to find a memory efficient way to make it configurable from the main C file, maybe by using a structure... Anyway not sure yet on how to do that part.
  4. Like
    nuetron reacted to bluehash in Members will now be warned for incorrect post content format.   
    Hello Everyone,
     
    Since the community is growing to larger numbers, it becomes difficult for moderators to keep editing posts that don't follow correct post etiquette.
     
    So far, there are only two major rules to follow about post content.
    1. Do NOT use dropbox, imgur or any other thirdparty links, if you care about this community. These links die off after a few years/months. Look around the major forums. Images dating back to 2010 are dead and the posts are useless. So please upload to 43oh.
     
    2. Please use the code tag to display code. It is much easier to read and you will most probably get an answer as members will at least try to browse through code. It is the "<>" button in your edit bar.
     
    The warning points makes it easier for us to let you know instead of spending alot of time everyday downloading and re-uploading images and editing posts. Warning points hold no value, they will not harm you. It is just to let you know. You must acknowledge the warning to continue posting.
     
    Thanks! Any concerns, please list them below.
  5. Like
    nuetron reacted to bluehash in Members will now be warned for incorrect post content format.   
    @@pjkim Thanks for your view. 
    Although downloaders have nothing to contribute, they are still using the service for free. Registering takes under 30 seconds. It is true only 2000 of the 20,000 members are active. Is it that bad to have a large user base? 
     
    This community runs on servers. Servers need money to run. Having a larger userbase allows me to get in advertisers. Also, this is not always cash. These advertisers either pay or give products for giveaways, which in turn attracts more people who can contribute and post content.  Plus there is cost of domains, licenses, design content, shipping giveaway prizes, sponsoring bossterpacks etc.
     
    Having them to register benefits the whole community.
  6. Like
    nuetron reacted to RobG in Serial SPI memory functions   
    Here is the set of functions needed to read and write serial SPI memory, SRAM & EEPROM.
     
    EEPROM: Microchip 25AAxxx series
    SRAM: Microchip 23Kxxx series
     
    Included are byte and sequence read and write functions (page boundaries must be handled by user.)
    Test functions are also included. Additional functions will be added later on.
     
    Those functions can be used with some of my booster packs, like CC2500, Universal Color LCD, and few other.
     
    Test example

    // setup SPI pins, which can be shared with other devices // setup memory specific pins P1OUT |= SRAM_CS_PIN + SRAM_HOLD_PIN; P1DIR |= SRAM_CS_PIN + SRAM_HOLD_PIN; P2OUT |= EEPROM_CS_PIN; P2DIR |= EEPROM_CS_PIN; // setup display // run tests drawString(0,0,"Test SRAM:"); drawString(64, 0, (testSRAM() == 'O' ? "Pass" : "Fail")); drawString(0,10,"Test EEPROM:"); drawString(76, 10, (testEEPROM() == 'O' ? "Pass" : "Fail"));
     

     
    memory.h
    memory.c
  7. Like
    nuetron got a reaction from izdane in The Task   
    My dad handed me a sheet of paper this morning:
     
    ---------------------------------------------------------------- The Task ----------------------------------------------------------------
     
     
    The young man stopped his steed on a slight knoll. Twisting in the saddle he wistfully looked back over the terrain he had traversed, thinking of the battles fought, the lessons learned, the order brought, and the wisdom earned. Sighing he then looked forward into the chaos and danger of what lay ahead: The Werkaria. He had been here many times before, but though many battles had been fought here, many remained. His hand went reflexively to the hilt of his weapon, firmly ensconced in the scabbard at his hip. The handle of the soldering iron felt familiar and reassuring. Nathan knew it was time to dismount the steed that had brought him thus far and proceed alone, as the friendly constant companion could not follow him into the chaos ahead. He closed Laptop5's lid and, leaving its smooth muzzle behind, strode into the wilds that few dared enter that existed between the cliffs of West Wall and East Wall. Mumbling bits of The Code, which had strengthened him and his friends and which had guided him on his quest, he remembered the things he had learned from Master BlueHash and those who had gone before him. Ahead, in the jumble of the wild waited the thing that must be tamed - the MSP430.
     
    Nathan had fought with this beast on other occasions, and knew that harder battles lay ahead before this particular animal would be subdued. Struggling through the wires of the badlands, which tore at his legs like vines, he thought of his friends and family, which, not understanding the need for his quest, refused to enter here. Here, where components needed to survive were hard to find - and many times had to be harvested with great difficulty - Nathan felt truly alive. He was in his element. Though it seemed insane, he actually looked forward to the battles because of the rewards gained when The Code worked! The MSP430 was not the only beast out here, either. His confidants had warned him about its sister, The Ardweeno Beast, which was just as dangerous.
     
    Suddenly, he found himself at the Board. The beast was waiting for him! Drawing his soldering iron from its scabbard Nathan engaged in The Task. With a wisp of flux smoke and amid the flash of LEDs he was instantly focused only on the Battle, as all else around him faded away. He became unaware of West Wall, East Wall, and the chaos of Werkaria. Only the Board mattered, and only his skill with The Code could save him!
     
    -----------------------------------------------------------------------------------------------------------------------------------------------------
  8. Like
    nuetron got a reaction from roadrunner84 in iPhone/iPod touch/iPad/Android bluetooth C++ compiler/debugger   
    I was wondering, does anybody know of a good msp430 compiler like IAR for mobile devices?
     
    If not, I have some ideas if anybody is up for making one.
    Physically connecting to the phone is out of the question, so it would have to be bluetooth. An msp (preprogrammed) with a bluetooth transceiver may just be all that's needed to program another msp via spi-bi-wire, and possibly throw in an rx/tx port to transfer data back through the Bluetooth, just like the launchpad does with USB.
     
    Just tossing ideas out.
  9. Like
    nuetron reacted to oPossum in Frequency Counter using Launchpad & Nokia 5110 LCD   
    That is where the product name and mfg name are. We are close to having kits available - hopefully about 2 months from now. I can't really say much about it or make design files available until then. Currently working on several projects that use that board.
  10. Like
    nuetron reacted to GeekDoc in Random ad...   
    Not near as bad, but really, Google?
     

    What could I have been searching/viewing to prompt this (other than all the obvious jokes)?
     
    It's not a problem, blue. I just thought it was funny.
     
    EDIT:
    Went back to main page; THIS is more like it!
     

  11. Like
    nuetron reacted to kylej1050 in Lightning detector/counter   
    I'm fascinated by weather. New Mexico doesn't have much to offer in this particular area but I try to capture the moments whenever I can.
     
    This is one of two lightning projects I'm currently working on. The second is an IR detector for triggering my Kodak Retina 2 with B&W film.
     

     
    The detector captures pulses from an external lightning detector circuit, counts how many strikes there have been since the last reset(powered off) and takes the average Strikes Per Minute based on the last 10 seconds worth of data. I'll get around to a better averaging scheme later but I wanted this thing up and running faster because we are getting into storm season here in NM. Pin 1.6 is for accessories but can be used for an LED to indicate when a strike is occurring for minimal parts. I'm using an LED and a speaker from the detector add-on circuits so I can hear and see the strikes outside the MSP.
     
    I sample Vcc so I know when the lithium battery is in need of recharging(runs 1MHz so without audio should last a long time with the 1200mAH capacity). The code is based on the 4.2-3.6V working range of a lithium-ion battery being dropped through a diode to not exceed the MSP max. I intended to incorporate a charger circuit so there is an input for the indicator but thermal limitations of a plastic chassis has made this a no go for now.
     
    The code for the LCD is based off the 5110 code that is on here, the lightning detector circuit is from http://www.techlib.com/electronics/lightning.html#Egor but I used the newer antenna tank circuit , and the lithium charger circuit is from here http://www.shdesigns.org/lionchg.html modified for a single cell.
     
    I had a little mishap making the chassis yesterday so I now have to go get another cover but I should have a finished product to show soon.
     

    // main.c #include "msp430g2553.h" #include "PCD8544.h" #define LCD5110_SCLK_PIN BIT5 #define LCD5110_DN_PIN BIT7 #define LCD5110_SCE_PIN BIT0 #define LCD5110_DC_PIN BIT1 #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 // Pin 1.4 for lightning trigger (hi->low) // Pin 1.3 for charge indicator (high == charging) // Pin 1.6 for pulsed output (high pulse) #define SPI_MSB_FIRST UCB0CTL0 |= UCMSB #define SPI_LSB_FIRST UCB0CTL0 &= ~UCMSB void writeStringToLCD(const char *string); void writeCharToLCD(char c); void writeIntToLCD(int input); void writeBlockToLCD(char *byte, unsigned char length); void writeGraphicToLCD(char *byte, unsigned char transform); void writeToLCD(unsigned char dataCommand, unsigned char data); void clearLCD(); void clearBank(unsigned char bank); void setAddr(unsigned char xAddr, unsigned char yAddr); void initLCD(); // Variables for lightning counter volatile unsigned int SPMTime = 0, displayUpdate = '4', totalStrikes = 0, SPMCount = 0; volatile long unsigned int timeSinceReset = 0; long unsigned int TSRCalc; unsigned int totalStrikesDisp, TSDCheck, SPMCheck; short int TSD5, TSD4, TSD3, TSD2, TSD1, SPM3, SPM2, SPM1, TSRHour, TSRMinute, TSRSecond; int SPMAverage = 0; // Variables for battery circuit short int batteryTime = 0, batteryLevel = 0, batteryStatus = '0'; int main() { WDTCTL = WDTPW + WDTHOLD; // disable WDT BCSCTL1 = CALBC1_1MHZ; // 1MHz clock DCOCTL = CALDCO_1MHZ; BCSCTL3 = XCAP_3; // 12.5pF capacitance for 32KHz crystal. P1IE |= 0x10; // P1.4 interrupt enabled P1IES |= 0x10; // P1.4 Hi/lo edge P1IFG &= ~0x10; // P1.4 IFG cleared P1OUT |= LCD5110_SCE_PIN + LCD5110_DC_PIN + BIT3; P1OUT &= ~BIT6; P1DIR |= LCD5110_SCE_PIN + LCD5110_DC_PIN + BIT6; P1REN |= BIT3; // 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_11; // AVcc/2 ADC10CTL0 = SREF_1 + ADC10SHT_3 + REF2_5V + REFON + ADC10ON; // Begin active code WDTCTL = WDT_ADLY_1000; IE1 |= WDTIE; initLCD(); clearLCD(); setAddr(0,0); writeStringToLCD("Lightning"); setAddr(0,1); writeStringToLCD(" Detector"); clearBank(3); writeStringToLCD("Avg SPM: 0"); // setAddr spacing 54 clearBank(4); writeStringToLCD("Total: 0"); // setAddr spacing 42 clearBank(5); writeStringToLCD("TSR: 00:00:00"); // setAddr spacing 30 while(1) { switch(displayUpdate) { case '1': // Calculate time TSRCalc = timeSinceReset; TSRHour = TSRCalc / 3600; TSRCalc %= 3600; TSRMinute = TSRCalc / 60; TSRSecond = TSRCalc % 60; // Display time setAddr(30,5); writeIntToLCD(TSRHour/10); writeIntToLCD(TSRHour%10); writeCharToLCD(0x3a); writeIntToLCD(TSRMinute/10); writeIntToLCD(TSRMinute%10); writeCharToLCD(0x3a); writeIntToLCD(TSRSecond/10); writeIntToLCD(TSRSecond%10); break; case '2': P1OUT ^= BIT6; // Update total strikes from interrupt TSDCheck = totalStrikesDisp = totalStrikes; TSD5 = totalStrikesDisp / 100000; totalStrikesDisp%=100000; TSD4 = totalStrikesDisp / 10000; totalStrikesDisp%=10000; TSD3 = totalStrikesDisp / 1000; totalStrikesDisp%=1000; TSD2 = totalStrikesDisp / 100; totalStrikesDisp%=100; TSD1 = totalStrikesDisp / 10; // Display total strikes setAddr(42,4); if (TSD5 == 0 && TSDCheck < 100000) writeCharToLCD(0x20); else writeIntToLCD(TSD5); if (TSD4 == 0 && TSDCheck < 10000) writeCharToLCD(0x20); else writeIntToLCD(TSD4); if (TSD3 == 0 && TSDCheck < 1000) writeCharToLCD(0x20); else writeIntToLCD(TSD3); if (TSD2 == 0 && TSDCheck < 100) writeCharToLCD(0x20); else writeIntToLCD(TSD2); if (TSD1 == 0 && TSDCheck < 10) writeCharToLCD(0x20); else writeIntToLCD(TSD1); writeIntToLCD(totalStrikesDisp%10); P1OUT ^= BIT6; break; case '3': // Update average strikes per minute SPMCheck = SPMAverage = SPMCount * 6; SPM3 = SPMAverage / 1000; SPMAverage %= 1000; SPM2 = SPMAverage / 100; SPMAverage %= 100; SPM1 = SPMAverage / 10; // Display SPM setAddr(54, 3); if (SPM3 == 0 && SPMCheck < 1000) writeCharToLCD(0x20); else writeIntToLCD(SPM3); if (SPM2 == 0 && SPMCheck < 100) writeCharToLCD(0x20); else writeIntToLCD(SPM2); if (SPM1 == 0 && SPMCheck < 10) writeCharToLCD(0x20); else writeIntToLCD(SPM1); writeIntToLCD(SPMAverage%10); SPMTime = 0; SPMCount = 0; batteryTime++; break; case '4': // Measure battery voltage and update battery icon ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start while (ADC10CTL1 & ADC10BUSY); // ADC10BUSY? batteryLevel = ADC10MEM; if (batteryLevel > 0x28F) batteryStatus = '4'; // > 3.2v after .7 diode drop else if (batteryLevel > 0x27A) batteryStatus = '3'; // > 3.1v after .7 diode drop else if (batteryLevel > 0x266) batteryStatus = '2'; // > 3.0v after .7 diode drop else if (batteryLevel > 0x251) batteryStatus = '1'; // > 2.9v after .7 diode drop else batteryStatus = '0'; //Update battery and charge indicator (high on pin 1.3 indicates charge) if(0x08 & P1IN) { setAddr(73,0); writeCharToLCD(0x20); } else { setAddr(73,0); writeCharToLCD(0x85); } switch(batteryStatus) { case '4': writeCharToLCD(0x80); break; case '3': writeCharToLCD(0x81); break; case '2': writeCharToLCD(0x82); break; case '1': writeCharToLCD(0x83); break; case '0': writeCharToLCD(0x84); break; } batteryTime = 0; break; } if(SPMTime > 9) displayUpdate = '3'; else if (batteryTime > 5) displayUpdate = '4'; else { displayUpdate = '0'; _BIS_SR(LPM3_bits + GIE); } } } // Interrupt vectors #pragma vector=WDT_VECTOR __interrupt void watchdog_timer (void) { timeSinceReset++; SPMTime++; displayUpdate = '1'; _BIC_SR_IRQ(LPM3_bits); } #pragma vector=PORT1_VECTOR __interrupt void Port_1(void) { SPMCount++; totalStrikes++; displayUpdate = '2'; _BIC_SR_IRQ(LPM3_bits); P1IFG &= ~0x10; } // LCD Code 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 writeIntToLCD(int input) { unsigned char i; for(i = 0; i < 5; i++) { writeToLCD(LCD5110_DATA, font[16 + input][i]); } writeToLCD(LCD5110_DATA, 0); } void writeBlockToLCD(char *byte, unsigned char length) { unsigned char c = 0; while(c < length) { writeToLCD(LCD5110_DATA, *byte++); c++; } } void writeGraphicToLCD(char *byte, unsigned char transform) { int c = 0; char block[8]; if(transform & FLIP_V) { SPI_LSB_FIRST; } if(transform & ROTATE) { c = 1; while(c != 0) { (*byte & 0x01) ? (block[7] |= c) : (block[7] &= ~c); (*byte & 0x02) ? (block[6] |= c) : (block[6] &= ~c); (*byte & 0x04) ? (block[5] |= c) : (block[5] &= ~c); (*byte & 0x08) ? (block[4] |= c) : (block[4] &= ~c); (*byte & 0x10) ? (block[3] |= c) : (block[3] &= ~c); (*byte & 0x20) ? (block[2] |= c) : (block[2] &= ~c); (*byte & 0x40) ? (block[1] |= c) : (block[1] &= ~c); (*byte & 0x80) ? (block[0] |= c) : (block[0] &= ~c); *byte++; c <<= 1; } } else { while(c < 8) { block[c++] = *byte++; } } if(transform & FLIP_H) { c = 7; while(c > -1) { writeToLCD(LCD5110_DATA, block[c--]); } } else { c = 0; while(c < 8) { writeToLCD(LCD5110_DATA, block[c++]); } } SPI_MSB_FIRST; } 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 clearBank(unsigned char bank) { setAddr(0, bank); int c = 0; while(c < PCD8544_HPIXELS) { writeToLCD(LCD5110_DATA, 0); c++; } setAddr(0, bank); } 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); }
     
    // PCD8544.h (modified for extra characters)
     
    #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
  12. Like
    nuetron reacted to rockets4kids in Software debouncing   
    Jack Ganssle has a *great* article on debouncing, both hardware and software:
     
    http://www.eng.utah.edu/~cs5780/debouncing.pdf
     
    Definitely worth reading even if you already have a working debounce routine.
  13. Like
    nuetron got a reaction from dacoffey in Nokia 5110, '2452, small GUI [got pics!]   
    Just a small thing I've been playing with, has six microswitches and a pushbutton to latch in the instructions.
    Four microswitches are connected to the lower nibble of port 2, one on bit7 of port 2, one on bit 4 of port 1, and the pushbutton is on bit 6 of port 2.

     
    Available instructions are (CMD bit high):


    [*:204z8i3q]0x0 (NIBBLE = x)Toggle backlight
    [*:204z8i3q]0x9 (NIBBLE = 1) Move the addr pointer back one char
    [*:204z8i3q]0x9 (NIBBLE = 0) Backspace
    [*:204z8i3q]0xA (NIBBLE = 1) Secondary font set (rearranged ASCII) - to be used with my external PS/2 keyboard controller
    [*:204z8i3q]0xA (NIBBLE = 0) Primary font - normal ASCII
    [*:204z8i3q]0xB (NIBBLE = 1) Copy the value in the address char into the input char (I don't know what for)
    [*:204z8i3q]0xB (NIBBLE = 0) Copy the value in the input char into the address char (much more useful)
    [*:204z8i3q]0xC (NIBBLE = x) Write one char from input buffer
    [*:204z8i3q]0xD (NIBBLE = x) Set text Address (14 x 6)
    [*:204z8i3q]0xE (NIBBLE = x) Clear bank
    [*:204z8i3q]0xF (NIBBLE = x) Clear LCD
     
    (CMD bit low):


    (NIBBLE = 1) Write upper nibble to input buffer
    (NIBBLE = 0) Write lower nibble to input buffer
    The char preview is always available.
     
    LCD code based on RobG's Nokia 5110
    main.cpp
    main.cpp

    #include "msp430g2452.h" //P1 I/O #define LCD5110_SCE_PIN BIT0 #define LCD5110_DC_PIN BIT1 #define LCD5110_LED_PIN BIT2 #define LCD5110_SCLK_PIN BIT5 #define LCD5110_DN_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 //P2 I/O #define INT BIT6 #define CS_INT0 BIT5 #define CS_INT1 BIT4 #define SPI_MSB_FIRST USICTL0 &= ~USILSB // or UCA0CTL0 |= UCMSB (USCIA) or USICTL0 &= ~USILSB (USI) #define SPI_LSB_FIRST USICTL0 |= USILSB // or UCA0CTL0 &= ~UCMSB or USICTL0 |= USILSB (USI) void writeStringToLCD(const char *string); void writeCharToLCD(char c); void writeBlockToLCD(char *byte, unsigned char length); void writeGraphicToLCD(char *byte, unsigned char transform); void writeToLCD(unsigned char dataCommand, unsigned char data); void clearLCD(); void clearBank(unsigned char bank); void setAddr(unsigned char xAddr, unsigned char yAddr); void initLCD(); unsigned char currXAddr = 0; //TODO this will be used for tracking current addr unsigned char currYAddr = 0; //not implemented //char testBlock[8] = {0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF}; char testBlock[8] = { 0x00, 0x7F, 0x7F, 0x33, 0x33, 0x03, 0x03, 0x03 }; char testBlock2[8] = { 0x00, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00 }; char smileylarge1[8] = { 0xF0, 0x08, 0x04, 0x02, 0xF1, 0xF1, 0xF1, 0x01 }; char smileylarge2[8] = { 0x0F, 0x10, 0x20, 0x4C, 0x94, 0xA4, 0xA4, 0xA4 }; void printinfo(char* input); #include "PCD8544.h" char addr = 0; char buffer = 0; char string[4] = {'0', '0', '0', '0'}; const char* fontset = &font[0][0]; void main(void) { WDTCTL = WDTPW + WDTHOLD; // disable WDT BCSCTL1 = CALBC1_1MHZ; // 1MHz clock DCOCTL = CALDCO_1MHZ; P1OUT |= LCD5110_SCE_PIN; P1REN |= BIT4; P1DIR |= LCD5110_SCE_PIN + LCD5110_DC_PIN + LCD5110_LED_PIN; P2OUT = P2REN = 0x8F | (P2IE = INT|CS_INT0); P2IES = 0; P2DIR = P2IFG = P2SEL = 0; // setup USI USICTL0 |= USIPE5 | USIPE6 | USIPE7 | USIMST | USIOE; USICTL0 &= ~USILSB; USICTL1 |= USICKPH; // + USIIE; USICKCTL = USISSEL_2; USICTL0 &= ~USISWRST; USICNT = 0; initLCD(); clearLCD(); P1OUT |= LCD5110_LED_PIN; writeStringToLCD("Ready"); printinfo(0); _EINT(); LPM0; } // /* void translnibble(char nibble, char *byte) { *byte = "0123456789ABCDEF"[nibble & 0x0F]; } bool strshrink(char* byte, char* str){ *byte = 0; for(char i=0; i<2; i++){ if((str[i] & 0xF0) == 0x30){ *byte |= (str[i] & 0x0F); } else if((str[i] & 0xF0) == 0x40){ *byte |= ((str[i] & 0x0F) + 9); } else return false; if(!i) *byte <<=4; if(i && ((*byte < 0x20)||(*byte > 0x7F))) *byte = ' '; } return true; } void printinfo(char* input){ const char* box = fontset; fontset = &font[0][0]; if(input){ switch((*input>>4) & 0x7){ case 0: (*input & BIT7) ? translnibble(*input, string) : translnibble(*input, string+1); break; } } clearBank(5); writeStringToLCD("0x00 ' ' 0x00"); setAddr((2 * 6), 5); writeCharToLCD(string[0]); writeCharToLCD(string[1]); strshrink(&buffer, string); setAddr((12 * 6), 5); writeCharToLCD(string[2]); writeCharToLCD(string[3]); setAddr((6 * 6), 5); translnibble(addr>>4, string+2); translnibble(addr, string+3); fontset = box; writeCharToLCD(buffer); setAddr(((addr & 0xF) * 6), ((addr>>4) & 0xF)); } void keyhandler(char command, char value){ if(command == 0x2) { (value & BIT7) ? (command=1) : (command=0); } if(command){ switch(value & 0xF){ case 0x0: P1OUT ^= LCD5110_LED_PIN; break; case 0x9: { addr--; setAddr(((addr & 0xF) * 6), ((addr>>4) & 0xF)); if(!(value & BIT7)){ writeCharToLCD(' '); setAddr(((addr & 0xF) * 6), ((addr>>4) & 0xF)); } } break; case 0xA: { const char* box; fontset = &font[0][0]; clearBank(5); if(value & BIT7){ box = &font2[0][0]; writeStringToLCD("Secondary "); } else{ box = &font[0][0]; writeStringToLCD("Primary "); } writeStringToLCD("Font"); __delay_cycles(1000000); printinfo(0); fontset = box; break; } case 0xB: { (value & BIT7) ? (addr=buffer):(buffer=addr); printinfo(0); } break; case 0xC: { writeCharToLCD(buffer); addr++; if((addr & 0xF) > 12){ addr &= ~0x0F; addr += 0x10;} if(((addr>>4) & 0xF) > 4){ addr=0;} printinfo(0); } break; case 0xD: setAddr(((buffer & 0xF) * 6), ((buffer>>4) & 0xF)); break; case 0xE: { clearBank((addr &= ~0xF) & 0x7); printinfo(0); } break; case 0xF: { clearLCD(); addr=0; printinfo(0); } break; } } else { printinfo(&value); } } char getbyte(char data){ P2OUT &= ~CS_INT0; __delay_cycles(50); USISRL = data; USICNT |= 8; while (!(USIIFG & USICTL1)) ; // wait for SPI flag to trip P2OUT |= CS_INT0; return (char) USISRL; } #pragma vector=PORT2_VECTOR __interrupt void inputs(void){ if(P2IFG & INT){ __delay_cycles(200000); char a = (P2IN & 0x8F); keyhandler((P1IN & BIT4), a); } if(P2IFG & CS_INT0){ (!(P2IN & CS_INT0)); keyhandler(2, getbyte(0)); } P2IFG = 0; }// */
    PCD8544.h
    PCD8544.h
    #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
  14. Like
    nuetron reacted to RobG in Nokia 5110, '2452, small GUI [got pics!]   
    Here's my $0.02 re optimization.
     
    If you only have one SPI device attached, you can just select it once (CS) at the beginning and leave it selected. This will save you few clock cycles.
     
    Because you send data much more often than command, you can write a separate function for command and for data and toggle data/command pin just in command function. You could even call data function from command function. Another few clock cycles saved.
  15. Like
    nuetron reacted to oPossum in Nokia 5110, '2452, small GUI [got pics!]   
    Consider this code...

    void lcd_init(void) { const unsigned char init[] = { PCD8544_FUNCTIONSET | PCD8544_EXTENDEDINSTRUCTION, PCD8544_SETVOP | 0x3F, PCD8544_SETTEMP | 0x02, PCD8544_SETBIAS | 0x03, PCD8544_FUNCTIONSET, PCD8544_DISPLAYCONTROL | PCD8544_DISPLAYNORMAL }; lcd_write(lcd_command, init, sizeof(init)); }
    The init array will be sized based on the array initializer. The write to the LCD uses sizeof() to ensure the exact number of bytes is written. You can edit the array initializer without having to change any code and it will work properly.
     
    This is an other way...

    void lcd_init(void) { const unsigned char init[8] = { PCD8544_FUNCTIONSET | PCD8544_EXTENDEDINSTRUCTION, PCD8544_SETVOP | 0x3F, PCD8544_SETTEMP | 0x02, PCD8544_SETBIAS | 0x03, PCD8544_FUNCTIONSET, PCD8544_DISPLAYCONTROL | PCD8544_DISPLAYNORMAL }; lcd_write(lcd_command, init, 7); }
     
    There are two mistakes. The compiler may warn you of one, but not the other.
     
    So using sizeof() reduces the chances of making stupid mistakes in array sizing at both initialization and use.
  16. Like
    nuetron reacted to oPossum in Nokia 5110, '2452, small GUI [got pics!]   
    It is very common to have to send multiple command or data bytes to the LCD. So making a function that can send one or more bytes can eliminate for() loops and multiple write() calls from the rest of the LCD library code. It also reduces the manipulation of enable and data/command lines for a small improvement in efficiency.
     
    Here is a function that can send command bytes, data bytes, or repeat a single data byte using USI. (note: untested)

    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; void lcd_write(const lcd_cmd_type type, const unsigned char *data, unsigned len) { P1OUT &= ~LCD5110_SCE_PIN; // Enable LCD if(type == lcd_command) P1OUT &= ~LCD5110_DC_PIN;// Sending command? do { // USISRL = *data; // Setup SPI data to send USICNT |= 8; // Send 8 bits if(!(type & 2)) ++data; // Increment data pointer if not repeat while(!(USIIFG & USICTL1)); // Wait for all bits to be sent } while(--len); // While more data... P1OUT |= LCD5110_DC_PIN; // Default to data P1OUT |= LCD5110_SCE_PIN; // Disable LCD } //
     
    The various support functions can then be more compact by elimination of for() loops and multiple write() calls...

    void lcd_send_font_char(const unsigned char *font, unsigned width, const char c) { // Send one char of a font with specified width (8 bit high) // Note: this function assumes the font begins with character lcd_write(lcd_data, font + ((c - ' ') * width), width); lcd_write(lcd_data, font, 1); } void lcd_home(void) { static const unsigned char home[] = { 0x40, 0x80 }; lcd_write(lcd_command, home, sizeof(home)); } void lcd_pos(unsigned char x, unsigned char y) { unsigned char c[2]; c[0] = 0x80 | x; c[1] = 0x40 | y; lcd_write(lcd_command, c, sizeof(c)); } void lcd_clear(void) { static const char x = 0; lcd_home(); lcd_write(lcd_data_repeat, &x, 504); lcd_home(); } void lcd_init(void) { const unsigned char init[] = { PCD8544_FUNCTIONSET | PCD8544_EXTENDEDINSTRUCTION, PCD8544_SETVOP | 0x3F, PCD8544_SETTEMP | 0x02, PCD8544_SETBIAS | 0x03, PCD8544_FUNCTIONSET, PCD8544_DISPLAYCONTROL | PCD8544_DISPLAYNORMAL }; lcd_write(lcd_command, init, sizeof(init)); }
     
    Using the "object_action" function naming makes refactoring for the C++ "object.function" syntax easier.
  17. Like
    nuetron reacted to oPossum in Nokia 5110, '2452, small GUI [got pics!]   
    writeToLCD(LCD5110_DATA, fontset[ ( (c - 0x20) * 5) + i ] );
     
    If you put a loop inside writeToLCD(), it will reduce code size and improve speed. Take a look at any of the code I have written for 5110/7110 to see how this works.
     
     
    The translnibble() function can be reduced to this...

    void translnibble(char nibble, char *byte) { *byte = "0123456789ABCDEF"[nibble & 0x0F]; }
  18. Like
    nuetron reacted to Sonic in first post - newbie seeking guidance!   
    Thanks for the warm welcome!
     
    Yes bluehash, I've seen RobG's projects they look very interesting indeed. They seem to require the msp430g2553 though. I suspect they use some functionality or other that the lower-end processors of the value series do not provide. Some samples arrived yesterday from TI, but my g2553s are backordered and won't come for a couple of weeks.
     
    Being new to microprocessors I've decided to do my best to learn everything thoroughly from the ground up. I just started MSP430 Microcontroller Basics by John Davies and it looks very promising. I'm using this PDF until my print edition arrives. http://myweb.wit.edu/johnsont/Classes/244/MSP430%20Microcontroller%20Basics.pdf
     
    I'll come back and post details once I get stuck into my Midi-CV clock project.
  19. Like
    nuetron got a reaction from larsie in Nokia 5110, '2452, small GUI [got pics!]   
    Just a small thing I've been playing with, has six microswitches and a pushbutton to latch in the instructions.
    Four microswitches are connected to the lower nibble of port 2, one on bit7 of port 2, one on bit 4 of port 1, and the pushbutton is on bit 6 of port 2.

     
    Available instructions are (CMD bit high):


    [*:204z8i3q]0x0 (NIBBLE = x)Toggle backlight
    [*:204z8i3q]0x9 (NIBBLE = 1) Move the addr pointer back one char
    [*:204z8i3q]0x9 (NIBBLE = 0) Backspace
    [*:204z8i3q]0xA (NIBBLE = 1) Secondary font set (rearranged ASCII) - to be used with my external PS/2 keyboard controller
    [*:204z8i3q]0xA (NIBBLE = 0) Primary font - normal ASCII
    [*:204z8i3q]0xB (NIBBLE = 1) Copy the value in the address char into the input char (I don't know what for)
    [*:204z8i3q]0xB (NIBBLE = 0) Copy the value in the input char into the address char (much more useful)
    [*:204z8i3q]0xC (NIBBLE = x) Write one char from input buffer
    [*:204z8i3q]0xD (NIBBLE = x) Set text Address (14 x 6)
    [*:204z8i3q]0xE (NIBBLE = x) Clear bank
    [*:204z8i3q]0xF (NIBBLE = x) Clear LCD
     
    (CMD bit low):


    (NIBBLE = 1) Write upper nibble to input buffer
    (NIBBLE = 0) Write lower nibble to input buffer
    The char preview is always available.
     
    LCD code based on RobG's Nokia 5110
    main.cpp
    main.cpp

    #include "msp430g2452.h" //P1 I/O #define LCD5110_SCE_PIN BIT0 #define LCD5110_DC_PIN BIT1 #define LCD5110_LED_PIN BIT2 #define LCD5110_SCLK_PIN BIT5 #define LCD5110_DN_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 //P2 I/O #define INT BIT6 #define CS_INT0 BIT5 #define CS_INT1 BIT4 #define SPI_MSB_FIRST USICTL0 &= ~USILSB // or UCA0CTL0 |= UCMSB (USCIA) or USICTL0 &= ~USILSB (USI) #define SPI_LSB_FIRST USICTL0 |= USILSB // or UCA0CTL0 &= ~UCMSB or USICTL0 |= USILSB (USI) void writeStringToLCD(const char *string); void writeCharToLCD(char c); void writeBlockToLCD(char *byte, unsigned char length); void writeGraphicToLCD(char *byte, unsigned char transform); void writeToLCD(unsigned char dataCommand, unsigned char data); void clearLCD(); void clearBank(unsigned char bank); void setAddr(unsigned char xAddr, unsigned char yAddr); void initLCD(); unsigned char currXAddr = 0; //TODO this will be used for tracking current addr unsigned char currYAddr = 0; //not implemented //char testBlock[8] = {0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF}; char testBlock[8] = { 0x00, 0x7F, 0x7F, 0x33, 0x33, 0x03, 0x03, 0x03 }; char testBlock2[8] = { 0x00, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00 }; char smileylarge1[8] = { 0xF0, 0x08, 0x04, 0x02, 0xF1, 0xF1, 0xF1, 0x01 }; char smileylarge2[8] = { 0x0F, 0x10, 0x20, 0x4C, 0x94, 0xA4, 0xA4, 0xA4 }; void printinfo(char* input); #include "PCD8544.h" char addr = 0; char buffer = 0; char string[4] = {'0', '0', '0', '0'}; const char* fontset = &font[0][0]; void main(void) { WDTCTL = WDTPW + WDTHOLD; // disable WDT BCSCTL1 = CALBC1_1MHZ; // 1MHz clock DCOCTL = CALDCO_1MHZ; P1OUT |= LCD5110_SCE_PIN; P1REN |= BIT4; P1DIR |= LCD5110_SCE_PIN + LCD5110_DC_PIN + LCD5110_LED_PIN; P2OUT = P2REN = 0x8F | (P2IE = INT|CS_INT0); P2IES = 0; P2DIR = P2IFG = P2SEL = 0; // setup USI USICTL0 |= USIPE5 | USIPE6 | USIPE7 | USIMST | USIOE; USICTL0 &= ~USILSB; USICTL1 |= USICKPH; // + USIIE; USICKCTL = USISSEL_2; USICTL0 &= ~USISWRST; USICNT = 0; initLCD(); clearLCD(); P1OUT |= LCD5110_LED_PIN; writeStringToLCD("Ready"); printinfo(0); _EINT(); LPM0; } // /* void translnibble(char nibble, char *byte) { *byte = "0123456789ABCDEF"[nibble & 0x0F]; } bool strshrink(char* byte, char* str){ *byte = 0; for(char i=0; i<2; i++){ if((str[i] & 0xF0) == 0x30){ *byte |= (str[i] & 0x0F); } else if((str[i] & 0xF0) == 0x40){ *byte |= ((str[i] & 0x0F) + 9); } else return false; if(!i) *byte <<=4; if(i && ((*byte < 0x20)||(*byte > 0x7F))) *byte = ' '; } return true; } void printinfo(char* input){ const char* box = fontset; fontset = &font[0][0]; if(input){ switch((*input>>4) & 0x7){ case 0: (*input & BIT7) ? translnibble(*input, string) : translnibble(*input, string+1); break; } } clearBank(5); writeStringToLCD("0x00 ' ' 0x00"); setAddr((2 * 6), 5); writeCharToLCD(string[0]); writeCharToLCD(string[1]); strshrink(&buffer, string); setAddr((12 * 6), 5); writeCharToLCD(string[2]); writeCharToLCD(string[3]); setAddr((6 * 6), 5); translnibble(addr>>4, string+2); translnibble(addr, string+3); fontset = box; writeCharToLCD(buffer); setAddr(((addr & 0xF) * 6), ((addr>>4) & 0xF)); } void keyhandler(char command, char value){ if(command == 0x2) { (value & BIT7) ? (command=1) : (command=0); } if(command){ switch(value & 0xF){ case 0x0: P1OUT ^= LCD5110_LED_PIN; break; case 0x9: { addr--; setAddr(((addr & 0xF) * 6), ((addr>>4) & 0xF)); if(!(value & BIT7)){ writeCharToLCD(' '); setAddr(((addr & 0xF) * 6), ((addr>>4) & 0xF)); } } break; case 0xA: { const char* box; fontset = &font[0][0]; clearBank(5); if(value & BIT7){ box = &font2[0][0]; writeStringToLCD("Secondary "); } else{ box = &font[0][0]; writeStringToLCD("Primary "); } writeStringToLCD("Font"); __delay_cycles(1000000); printinfo(0); fontset = box; break; } case 0xB: { (value & BIT7) ? (addr=buffer):(buffer=addr); printinfo(0); } break; case 0xC: { writeCharToLCD(buffer); addr++; if((addr & 0xF) > 12){ addr &= ~0x0F; addr += 0x10;} if(((addr>>4) & 0xF) > 4){ addr=0;} printinfo(0); } break; case 0xD: setAddr(((buffer & 0xF) * 6), ((buffer>>4) & 0xF)); break; case 0xE: { clearBank((addr &= ~0xF) & 0x7); printinfo(0); } break; case 0xF: { clearLCD(); addr=0; printinfo(0); } break; } } else { printinfo(&value); } } char getbyte(char data){ P2OUT &= ~CS_INT0; __delay_cycles(50); USISRL = data; USICNT |= 8; while (!(USIIFG & USICTL1)) ; // wait for SPI flag to trip P2OUT |= CS_INT0; return (char) USISRL; } #pragma vector=PORT2_VECTOR __interrupt void inputs(void){ if(P2IFG & INT){ __delay_cycles(200000); char a = (P2IN & 0x8F); keyhandler((P1IN & BIT4), a); } if(P2IFG & CS_INT0){ (!(P2IN & CS_INT0)); keyhandler(2, getbyte(0)); } P2IFG = 0; }// */
    PCD8544.h
    PCD8544.h
    #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
  20. Like
    nuetron got a reaction from bluehash in Nokia 5110, '2452, small GUI [got pics!]   
    Just a small thing I've been playing with, has six microswitches and a pushbutton to latch in the instructions.
    Four microswitches are connected to the lower nibble of port 2, one on bit7 of port 2, one on bit 4 of port 1, and the pushbutton is on bit 6 of port 2.

     
    Available instructions are (CMD bit high):


    [*:204z8i3q]0x0 (NIBBLE = x)Toggle backlight
    [*:204z8i3q]0x9 (NIBBLE = 1) Move the addr pointer back one char
    [*:204z8i3q]0x9 (NIBBLE = 0) Backspace
    [*:204z8i3q]0xA (NIBBLE = 1) Secondary font set (rearranged ASCII) - to be used with my external PS/2 keyboard controller
    [*:204z8i3q]0xA (NIBBLE = 0) Primary font - normal ASCII
    [*:204z8i3q]0xB (NIBBLE = 1) Copy the value in the address char into the input char (I don't know what for)
    [*:204z8i3q]0xB (NIBBLE = 0) Copy the value in the input char into the address char (much more useful)
    [*:204z8i3q]0xC (NIBBLE = x) Write one char from input buffer
    [*:204z8i3q]0xD (NIBBLE = x) Set text Address (14 x 6)
    [*:204z8i3q]0xE (NIBBLE = x) Clear bank
    [*:204z8i3q]0xF (NIBBLE = x) Clear LCD
     
    (CMD bit low):


    (NIBBLE = 1) Write upper nibble to input buffer
    (NIBBLE = 0) Write lower nibble to input buffer
    The char preview is always available.
     
    LCD code based on RobG's Nokia 5110
    main.cpp
    main.cpp

    #include "msp430g2452.h" //P1 I/O #define LCD5110_SCE_PIN BIT0 #define LCD5110_DC_PIN BIT1 #define LCD5110_LED_PIN BIT2 #define LCD5110_SCLK_PIN BIT5 #define LCD5110_DN_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 //P2 I/O #define INT BIT6 #define CS_INT0 BIT5 #define CS_INT1 BIT4 #define SPI_MSB_FIRST USICTL0 &= ~USILSB // or UCA0CTL0 |= UCMSB (USCIA) or USICTL0 &= ~USILSB (USI) #define SPI_LSB_FIRST USICTL0 |= USILSB // or UCA0CTL0 &= ~UCMSB or USICTL0 |= USILSB (USI) void writeStringToLCD(const char *string); void writeCharToLCD(char c); void writeBlockToLCD(char *byte, unsigned char length); void writeGraphicToLCD(char *byte, unsigned char transform); void writeToLCD(unsigned char dataCommand, unsigned char data); void clearLCD(); void clearBank(unsigned char bank); void setAddr(unsigned char xAddr, unsigned char yAddr); void initLCD(); unsigned char currXAddr = 0; //TODO this will be used for tracking current addr unsigned char currYAddr = 0; //not implemented //char testBlock[8] = {0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF}; char testBlock[8] = { 0x00, 0x7F, 0x7F, 0x33, 0x33, 0x03, 0x03, 0x03 }; char testBlock2[8] = { 0x00, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00 }; char smileylarge1[8] = { 0xF0, 0x08, 0x04, 0x02, 0xF1, 0xF1, 0xF1, 0x01 }; char smileylarge2[8] = { 0x0F, 0x10, 0x20, 0x4C, 0x94, 0xA4, 0xA4, 0xA4 }; void printinfo(char* input); #include "PCD8544.h" char addr = 0; char buffer = 0; char string[4] = {'0', '0', '0', '0'}; const char* fontset = &font[0][0]; void main(void) { WDTCTL = WDTPW + WDTHOLD; // disable WDT BCSCTL1 = CALBC1_1MHZ; // 1MHz clock DCOCTL = CALDCO_1MHZ; P1OUT |= LCD5110_SCE_PIN; P1REN |= BIT4; P1DIR |= LCD5110_SCE_PIN + LCD5110_DC_PIN + LCD5110_LED_PIN; P2OUT = P2REN = 0x8F | (P2IE = INT|CS_INT0); P2IES = 0; P2DIR = P2IFG = P2SEL = 0; // setup USI USICTL0 |= USIPE5 | USIPE6 | USIPE7 | USIMST | USIOE; USICTL0 &= ~USILSB; USICTL1 |= USICKPH; // + USIIE; USICKCTL = USISSEL_2; USICTL0 &= ~USISWRST; USICNT = 0; initLCD(); clearLCD(); P1OUT |= LCD5110_LED_PIN; writeStringToLCD("Ready"); printinfo(0); _EINT(); LPM0; } // /* void translnibble(char nibble, char *byte) { *byte = "0123456789ABCDEF"[nibble & 0x0F]; } bool strshrink(char* byte, char* str){ *byte = 0; for(char i=0; i<2; i++){ if((str[i] & 0xF0) == 0x30){ *byte |= (str[i] & 0x0F); } else if((str[i] & 0xF0) == 0x40){ *byte |= ((str[i] & 0x0F) + 9); } else return false; if(!i) *byte <<=4; if(i && ((*byte < 0x20)||(*byte > 0x7F))) *byte = ' '; } return true; } void printinfo(char* input){ const char* box = fontset; fontset = &font[0][0]; if(input){ switch((*input>>4) & 0x7){ case 0: (*input & BIT7) ? translnibble(*input, string) : translnibble(*input, string+1); break; } } clearBank(5); writeStringToLCD("0x00 ' ' 0x00"); setAddr((2 * 6), 5); writeCharToLCD(string[0]); writeCharToLCD(string[1]); strshrink(&buffer, string); setAddr((12 * 6), 5); writeCharToLCD(string[2]); writeCharToLCD(string[3]); setAddr((6 * 6), 5); translnibble(addr>>4, string+2); translnibble(addr, string+3); fontset = box; writeCharToLCD(buffer); setAddr(((addr & 0xF) * 6), ((addr>>4) & 0xF)); } void keyhandler(char command, char value){ if(command == 0x2) { (value & BIT7) ? (command=1) : (command=0); } if(command){ switch(value & 0xF){ case 0x0: P1OUT ^= LCD5110_LED_PIN; break; case 0x9: { addr--; setAddr(((addr & 0xF) * 6), ((addr>>4) & 0xF)); if(!(value & BIT7)){ writeCharToLCD(' '); setAddr(((addr & 0xF) * 6), ((addr>>4) & 0xF)); } } break; case 0xA: { const char* box; fontset = &font[0][0]; clearBank(5); if(value & BIT7){ box = &font2[0][0]; writeStringToLCD("Secondary "); } else{ box = &font[0][0]; writeStringToLCD("Primary "); } writeStringToLCD("Font"); __delay_cycles(1000000); printinfo(0); fontset = box; break; } case 0xB: { (value & BIT7) ? (addr=buffer):(buffer=addr); printinfo(0); } break; case 0xC: { writeCharToLCD(buffer); addr++; if((addr & 0xF) > 12){ addr &= ~0x0F; addr += 0x10;} if(((addr>>4) & 0xF) > 4){ addr=0;} printinfo(0); } break; case 0xD: setAddr(((buffer & 0xF) * 6), ((buffer>>4) & 0xF)); break; case 0xE: { clearBank((addr &= ~0xF) & 0x7); printinfo(0); } break; case 0xF: { clearLCD(); addr=0; printinfo(0); } break; } } else { printinfo(&value); } } char getbyte(char data){ P2OUT &= ~CS_INT0; __delay_cycles(50); USISRL = data; USICNT |= 8; while (!(USIIFG & USICTL1)) ; // wait for SPI flag to trip P2OUT |= CS_INT0; return (char) USISRL; } #pragma vector=PORT2_VECTOR __interrupt void inputs(void){ if(P2IFG & INT){ __delay_cycles(200000); char a = (P2IN & 0x8F); keyhandler((P1IN & BIT4), a); } if(P2IFG & CS_INT0){ (!(P2IN & CS_INT0)); keyhandler(2, getbyte(0)); } P2IFG = 0; }// */
    PCD8544.h
    PCD8544.h
    #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
  21. Like
    nuetron reacted to bluehash in Nokia 5110, '2452, small GUI [got pics!]   
    Would love to see some pics nuetron.
  22. Like
    nuetron reacted to CptanPanic in A sub-forum for displays (LCDs, OLEDs, etc)...   
    A good way to solve this is with tags. That way you can just tag a post with 'Displays', and then you can easily browse all of the posts with this topic. Maybe the forum can add this feature?
  23. Like
    nuetron reacted to RobG in TI Logo   
    Here's one possibility that would shave off 50-100 bytes of f of oPossum's image.
    First byte tells you how many bytes of info there are before image data. Then 2 bytes for each repeated byte, 10-12 bits for position and the rest for number of repeats, after that image data. This method would make sense when there are 4 or more bytes with the same bit pattern.
     
    However, you will need more than 100 bytes to decompress
  24. Like
    nuetron reacted to bluehash in A sub-forum for displays (LCDs, OLEDs, etc)...   
    Not sure if this is a good idea. The forum may become very fragmented. People may also start asking forums for other sections such as radios.
  25. Like
    nuetron reacted to gordon in Have outside links open in new window/tab   
    I for one have not and will not spend a split second on a site (any site) that thinks keeping me is best done with technical measures (especially if I perceive the measures as "annoying") and not relevant content.
     
    To some problems the solution is not technology, even if the technology to solve the problem exists .
×
×
  • Create New...