Jump to content

gordon

Members
  • Content Count

    536
  • Joined

  • Last visited

  • Days Won

    13

Reputation Activity

  1. Like
    gordon reacted to oPossum in 24x16 text on VGA using Launchpad w/ G2553   
    Using the more powerful F5418A at 25 MHz allows the full 640 x 480 resolution to be used for up to 80x40 text display.
    This requires sending SPI data at 25 Mbps - that is one byte every 8 clock cycles. Each byte requires reading the text buffer, font table lookup, and SPI tx. There is no time to check SPI status or to decrement and test a loop counter. An unrolled loop with exactly 8 cycles per byte is used to make this work.
     

    .loop 80 ; mov.b @R10+, R15 ; Get a text char add R12, R15 ; Add font pointer mov.b @R15, &UCB0TXBUF ; Output font data to SPI nop ; Exactly 8 cycles per byte .endloop ;
     
    Lower horizontal resolutions use more conventional coding. Still have some work to do on this before making code available.
     


  2. Like
    gordon reacted to RobG in TLV data (calibration) parse and display   
    BLAHx defines single bit, BLAH_x defines set of bits. So OUTMOD0 | OUTMOD2 = OUTMOD_5
  3. Like
    gordon reacted to lakeweb in List of MSP430 Webpages and Blogs   
    Hi,
     
    This may help a little. My old MSP430 site:
    http://lakeweb.net/MSP430/
     
    Note that I have a small DOS suitable for the SD card there. I'll see about doing a version 2 in April. It needs more bells and whistle options. I'll also do everything with stdint.h
     
    Best, Dan.
  4. Like
    gordon reacted to RobG in Programmable servo controller   
    After receiving few emails regarding my servo code, I have decided to revisit this topic and create a programmable servo controller.
     
    The controller will have 4 servo outputs and 4 ADC inputs.
    Leftmost and rightmost position of each servo can be set using the Terminal.
    Min pulse 0.5ms, max pulse 2.5ms.
    ADC start and end positions can also be set using the Terminal.
    Possible resolutions are 100, 128, 200, 256 steps (also considering 500, 512, 1000, and 1024.)
    Default values and set values can be saved to and restored from Flash.
    ADC can be turned on and off for each channel.
    Servos can be controlled from the Terminal.
    ADC values can be sent back to the Terminal.
     
    Code: still in progress
     
    Each servo will get 5ms. The pulse width can vary from 0.5ms - 2.5ms (this is more that the specified 1ms-2ms, but might be useful for some special cases.) The remaining 4.5ms - 2.5ms will be used for two things, ADC sampling (samples will be averaged) and sending data back to the Terminal (when enabled.)
     
     
     

     
    Command formats (c - command bit, ss - servo number, b - data bits, msb first, k - command bits)
    sent to the Terminal:
    2 bytes in 7 bit mode
    css00000 0bbbbbbb
    2 bytes in 10 bit mode
    css0bbbb 00bbbbbb
     
    from the Terminal (running command does not include command byte)
    2 or 1 byte in 7 bit mode
    csskkkkk 0bbbbbbb
    3 or 2 bytes in 10 bit mode
    csskkkkk 0100bbbb 00bbbbbb
     
    Setting position example:
    0x81 // set servo one start position
    0x1B // move to the right one coarse step
    0x1B
    ... // repeat until required position is reached
    0x80 // done
    0x8C // save
    0x5A // send key to prevent accidental saves/restores
     
    Move servo from the Terminal
    0x90 // disable ADC for servo 1
    0x80 // select servo 1 (previous command will also set the current servo to 1)
    0x7F // move all the way to the right
    0x00 // move all the way to the left
    ...
     

    // commands DONE 0x00 SET_SERVO_START 0x01 SET_SERVO_END 0x02 SET_ADC_START 0x05 SET_ADC_END 0x06 SET_RESOLUTION 0x08 SAVE 0x0C // TODO SAVE_DEFAULT 0x0D // TODO REVERT 0x0E // TODO RESET 0x0F // TODO DISABLE_ADC 0x10 ENABLE_ADC 0x11 DISABLE_TX 0x12 ENABLE_TX 0x13 DISABLE_10BIT 0x14 ENABLE_10BIT 0x15 STEP_DOWN 0x1A STEP_UP 0x1B FINE_STEP_DOWN 0x1C FINE_STEP_UP 0x1D SERVO1_SELECT 0x00 SERVO2_SELECT 0x20 SERVO3_SELECT 0x40 SERVO4_SELECT 0x60 COMMAND_BYTE 0x80 KEY 0x5A // used for saving to and restoring from memory
  5. Like
    gordon got a reaction from OppaErich in Launchpad Modification #32874537339847   
    http://en.wikipedia.org/wiki/Pogo_pin
  6. Like
    gordon reacted to Rickta59 in PetiteFS FATfs SDCard USCI code   
    I went ahead and tested the booster pack and added the write support in the attached zip file. You should take a look at the Petit FatFS documentation regarding the write limitations. PetiteFS only supports writing to preexisting files and you can't grow or shrink the size of the file.
     
    For the example code to work, create a file called 'write.txt' on your sdcard. The example writes 100 lines of quick brown fox type text to the file. At the command prompt type
     
    > di
    > fi
    > fl
     
    Make sure you can see the file 'WRITE.TXT' in the listing. To write to the file type:
     
    > fw
     
    To see if it worked type:
     
    > fo WRITE.TXT
    > ft
     
    You should see numbered lines of quick brown fox...
     
    -rick
    SDCARD_PetiteFS_2553_v0.02.zip
  7. Like
    gordon got a reaction from Tribes in Launchpad Modification #32874537339847   
    http://en.wikipedia.org/wiki/Pogo_pin
  8. Like
    gordon reacted to SugarAddict in $4.30 LCD Booster - Sold Out   
    And a little later... they are all done. Please post if you find something inside one hahaha I'll have these nicely packaged up tomorrow and in the mail to bluehash Friday!! Man, I feel like I accomplished something Hope you all enjoy!!!!!!!!!!!! :mrgreen: 8-)
  9. Like
    gordon reacted to oPossum in 24x16 text on VGA using Launchpad w/ G2553   
    This is derived from NTSC/PAL video text display using launchpad. video_vga.asm is a drop in replacement for video.asm.
     

     
    The sync timing is for 640x480 60 Hz VGA mode. A 330 ohm resistor must be used on all video lines (R/G/B) because they are analog signals with a max allowed voltage of about 1 volt. Only one of the R/G/B lines can be driven directly from the MSP430 due to current limitations. A buffer such as 74AHC125 could be used to drive all three if desired.
     
    Wiring

    Gnd ------------ Ground [5, 6, 7, 8, 10] P1.5 ----------- Vertical Sync [14] P1.6 ----------- Horizontal Sync [13] P1.7 ---[330]--- Video out (R [1], G [2] or B [3])
     
    video_vga.asm
    ;
    ; Copyright © 2011, 2012 Kevin Timmerman
    ;
    ; This program is free software: you can redistribute it and/or modify
    ; it under the terms of the GNU General Public License as published by
    ; the Free Software Foundation, either version 3 of the License, or
    ; (at your option) any later version.
    ;
    ; This program is distributed in the hope that it will be useful,
    ; but WITHOUT ANY WARRANTY; without even the implied warranty of
    ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    ; GNU General Public License for more details.
    ;
    ; You should have received a copy of the GNU General Public License
    ; along with this program. If not, see .
    ;
     
    .cdecls C, LIST, "msp430g2553.h"
     
    .text
    .def video_init ; void video_init(void); - Initialize video generation
    .def field_timer ; extern int field_timer; - Decremented at each vsync
    .def vblank ; Vertical blanking flag
    .ref text ; Text buffer
    .ref font ; Font 8 x 12, grouped by row
    ;
    ;
    .bss sync_state, 2 ; Sync state
    .bss sync_lines, 2 ; Lines until next sync state
    .bss video_state, 2 ; Video generation state
    .bss vblank, 2 ; Vertical blanking flag
    .bss field_timer, 2 ; Decrement at vsync
    .bss text_ptr, 2 ; Text buffer pointer
    .bss font_ptr, 2 ; Font pointer
     
     
    ; --- Ideal VGA 640 x 480 60 Hz Timing ---
    ; Pixel clock 25.175 MHz
    ; Horizontal 31.47 kHz (pix / 800, negative sync)
    ; Vertical 59.94 Hz (pix / 420000, negative sync)
    ; - Horizontal timing (line)
    ; Scanline part Pixels Time [
  10. Like
    gordon got a reaction from RobG in Color LCD Booster Pack   
    As far as I can tell, you can't really go over 12-ish MHz on 3.0V ([tipdf]SLAU144[/tipdf] page 21 figure 2).
  11. Like
    gordon got a reaction from xpg in Eclipse plugin for mspdebug and msp430-gcc   
    Is it still the case with 0.19 as well (which has this)?
     
    Don't know what that string is, but if it's a full line (ie. terminated with LF), that should help your case. If not, I suggest to take it up with Daniel -- pretty sure he'll come up with something.
  12. Like
    gordon got a reaction from advaneharshal in LP Booster Pack Eagle footprints   
    (OK, I have no idea where to put this. BH, feel free to move it around.)
     
    Continuing from viewtopic.php?f=9&t=1348&start=40#p11369
     
    This is the final version; I don't think it can be made any better as well as generic at the same time.
     
    All variants verified against the TI LaunchPad Eagle files.
     
    Thanks to SugarAddict for the corrections.
     
    Pro tip: make your References layer yellow (or any other unused bright color) while placing your components.
     
    Addendum: DipTrace users look here: viewtopic.php?f=35&t=2972
    TI_launchpad.zip
  13. Like
    gordon reacted to cde in C5000   
    Demonstrates Implementation in existing projects without needing to port over code? Demonstrates availability for hobbyists who wouldn't be able to work with the more complicated aspects of a DSP like bootloading, or who don't have access to more expensive development tools?
  14. Like
    gordon got a reaction from nuetron 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 .
  15. Like
    gordon reacted to oPossum in USCI UART bit rate setting   
    The MSP430x2xx Family User's Guide has several forumulas and tables for UART bit rate calculation. Makes it look more complicated than it is. Here is simple code to setup the bit rate divisor and modulator (for oversampling mode).
     
    First you need to know the SMCLK frequency and the desired bit rate.

    const unsigned long smclk_freq = 16000000; // SMCLK frequency in hertz const unsigned long bps = 19200; // Async serial bit rate Then a 20 bit divisor value can be calculated.
    const unsigned long brd = (smclk_freq + (bps >> 1)) / bps; // Bit rate divisor Shift and mask to setup the registers.
    UCA0BR1 = (brd >> 12) & 0xFF; // High byte of whole divisor UCA0BR0 = (brd >> 4) & 0xFF; // Low byte of whole divisor UCA0MCTL = ((brd << 4) & 0xF0) | UCOS16; // Fractional divisor, oversampling mode That's it! 
    A function for UART setup at a specified bit rate...

    const unsigned long smclk_freq = 16000000; // SMCLK frequency in hertz void setup_UART(const unsigned long bps) // Async serial bit rate { const unsigned long brd = (smclk_freq + (bps >> 1)) / bps; // Bit rate divisor UCA0CTL1 = UCSWRST; // Hold USCI in reset to allow configuration UCA0CTL0 = 0; // No parity, LSB first, 8 bits, one stop bit, UART (async) UCA0BR1 = (brd >> 12) & 0xFF; // High byte of whole divisor UCA0BR0 = (brd >> 4) & 0xFF; // Low byte of whole divisor UCA0MCTL = ((brd << 4) & 0xF0) | UCOS16; // Fractional divisor, oversampling mode UCA0CTL1 = UCSSEL_2; // Use SMCLK for bit rate generator, release reset }
  16. Like
    gordon reacted to SugarAddict in Eagle DRC error, how serious?   
    I tend to leave a .1 inch gap because I dremel cut my panels. But yes, you want to push back your polygon lines (you can drag the polygon line itself) to leave a big enough gap that you can cut/break your boards and not have the ground plane visible in the cut/break.
  17. Like
    gordon reacted to RobG in Eagle DRC error, how serious?   
    Use Restrict layers to keep GND away from the cut line, just like here, look at the boards in the top right corner.
    10mil space is not much, but if you order 1mm boards and use sharp knife, I think you can pull it off (I did it on my nanoPad and it was really, really tight, but no problems.)
  18. Like
    gordon reacted to oPossum in Software Real Time Clock (RTC) - two methods   
    The Launchpad comes with a 32.768 kHz crystal that can be used when timing more precise than the DCO is needed. The crystal frequency is useful for simple timing tasks, such as a RTC, because it is a power of 2. That allows a simple cascade of 15 flip-flops to create a 1 pulse per second time base. It is common for microcontroller timers to have prescalers, postscalers and/or preset divisors that are simply a tap on the flip-flip chain. The watchdog timer in the MSP430 is an example of a timer with power of 2 presets (64, 512, 8192, 32768). TimerA units have a prescaler with power of 2 presets (1, 2, 4, 8).
     
    The sample code in this post uses the watchdog timer to create an interrupt that occurs once per second. TimerA can also be used to do this. One of the advantages of using TimerA is the ability to change the preset +/- 1 every N cycles to allow for calibration and temperature compensation of the crystal. I chose to use the watchdog timer so that TimerA was free to be used for alarm tones or PWM backlight control.
     

     
    Using the C standard library time functions for a RTC
    The C standard library provides several functions for working with real time. The function prototypes are in time.h. The type time_t is typically an integer type that is in units of 1 second. It doesn't have to be that, but usually is. The epoch is usually January 1, 1970 for "unix time." Be aware that CCS uses an epoch of January 1, 1900 and time_t is unsigned rather than signed. I assume GCC uses the more common unix time epoch and time_t is signed.
     
    Since time_t is in units of 1 second, the ISR for timekeeping is trivial...

    #pragma vector = WDT_VECTOR // - Watchdog timer interrupt vector __interrupt void wdt_isr(void) // This interrupt will occur once per second { // ++tt; // Increment time_t } //
     
    To display the time it can be converted to a tm structure that has elements for hours, minutes, day, month, ect. There are two functions to do this: gmtime() and localtime(). gmtime() converts to UTC, and localtime converts to the time zone for the set locale. Both functions take a time_t and return a pointer to a static tm struct.
     
    To set the time the mktime() function will convert a tm struct to a time_t value. It will also determine day of week and day or year for you.
     
    Benefits
    Tivial ISR. Simple and efficient.
    Portable code - the C standard library time functions work on almost any device with a C compiler.
    Easy to calulate time deltas - use ordinary integer math on time_t values.
    Easy to compare times using <, >, ==, etc.
    Compact representation of time (32 bit time_t typically) is good for timestamps of data logs.
    Some file systems (not FAT unfortunately) use time_t as for timestamps.
     
    Concerns
    Converting from time_t to tm struct takes quite a few clock cycles, so not good for low power (battery powered) systems.
    Time functions take up quite a bit of flash - will not fit in G2211 for example.
     
    Software model of a hardware RTC
    Hardware real time clocks typically have counters for seconds, minutes, hours, ect. Each counter will reset at the appropriate
    limit - 60 seconds, 24 hours, ect. This approch can be use for a software RTC. The ISR has more code than the previous version...

    #pragma vector = WDT_VECTOR // - Watchdog timer interrupt vector __interrupt void wdt_isr(void) // This interrupt will occur once per second { // if(++t.tm_sec > 59) { // Increment seconds, check for overflow t.tm_sec = 0; // Reset seconds if(++t.tm_min > 59) { // Increment minutes, check for overflow t.tm_min = 0; // Reset minutes if(++t.tm_hour > 23) { // Increment hours, check for overflow t.tm_hour = 0; // Reset hours ++t.tm_yday; // Increment day of year if(++t.tm_wday > 6) // Increment day of week, check for overflow t.tm_wday = 0; // Reset day of week // Increment day of month, check for overflow if(++t.tm_mday > dim[t.tm_mon][is_leap_year(t.tm_year + 1900)]) { t.tm_mday = 1; // Reset day of month if(++t.tm_mon > 11) { // Increment month, check for overflow t.tm_mon = 0; // Reset month t.tm_yday = 0; // Reset day of year ++t.tm_year; // Increment year } // - year } // - month } // - day } // - hour } // - minute } //
     
    Most of the time the ISR will just increment the seconds member and return. The worst case is at the end of the year when the year is incremented and all other counters are reset to inital values.
     
    There is no need for any conversion for display of the time or setting the time. Be aware that day of week and day of year must be explicity set and can be out-of-sync if not properly set.
     
    Benefits
    No conversion function needed for display of time or setting of time.
    Small code size. Fits in G2211.
    High efficiency is good for battery powered applications.
    Use of tm struct provides some familiarity to those who have used the C standard library functions.
     
    Concerns
    No easy to way calulate time delta.
    No support for time zones / localization.
    Time comparison (for alarms) requires more MCU cycles because several structure members require comparason rather than just a long integer.
     


    This sample code can be configured to use either of the two methods descibed by (un)commenting the "#define USE_STDLIB_TIME" in main.c
     
    main.c

    #include #include #include #include "rtc.h" #include "lcd.h" //#define USE_STDLIB_TIME // Use functions in time.h 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 *d; if(t->tm_hour < 10) { x = -1; lcd_fill(0, 1, 10, 2, 0); } else { x = 4; lcd_fill(0, 1, 4, 2, 0); lcd_pd12(t->tm_hour / 10, x, 1); } lcd_pd12(t->tm_hour % 10, x + 11, 1); lcd_pd12(11, x + 22, 1); lcd_pd12(t->tm_min / 10, x + 27, 1); lcd_pd12(t->tm_min % 10, x + 38, 1); lcd_pd12(11, x + 49, 1); lcd_pd12(t->tm_sec / 10, x + 54, 1); lcd_pd12(t->tm_sec % 10, x + 65, 1); lcd_fill(x + 76, 1, 8 - x, 2, 0); if(t->tm_mon < 9) { x = -4; lcd_fill(0, 3, 7, 2, 0); } else { x = 1; lcd_fill(0, 3, 1, 2, 0); lcd_pd12((t->tm_mon + 1) / 10, x, 3); } lcd_pd12((t->tm_mon + 1) % 10, x + 11, 3); lcd_pd12(13, x + 22, 3); lcd_pd12(t->tm_mday / 10, x + 30, 3); lcd_pd12(t->tm_mday % 10, x + 41, 3); lcd_pd12(13, x + 52, 3); lcd_pd12(t->tm_year %100 / 10, x + 60, 3); lcd_pd12(t->tm_year % 10, x + 71, 3); lcd_fill(x + 82, 3, 2 - x, 2, 0); d = dow[t->tm_wday]; w = strlen(d) * 6; x = (84 - w) >> 1; lcd_fill(0, 5, x, 1, 0); lcd_print(d, x, 5); x += w; lcd_fill(x, 5, 84 - x, 1, 0); } // struct tm ts; // Time structure time_t tt; // Time in seconds since epoch // // #pragma vector = WDT_VECTOR // - Watchdog timer interrupt vector __interrupt void wdt_isr(void) // This interrupt will occur once per second { // #ifdef USE_STDLIB_TIME // ++tt; // Increment time_t #else // rtc_tick(&ts); // Increment tm struct #endif // __bic_SR_register_on_exit(LPM0_bits); // Wakeup main code } // // void main(void) // { // WDTCTL = WDTPW | WDTHOLD; // Disable watchdog reset // lcd_init(); // Init LCD lcd_clear(0); // lcd_print("MSP430 RTC", 12, 0); // // // 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() // #ifdef USE_STDLIB_TIME // Convert tm struct to time_t tt = mktime(&ts); // #endif // // for(; { // for-ever #ifdef USE_STDLIB_TIME // show_time(localtime(&tt)); // Convert time_t to tm struct and show on LCD #else // show_time(&ts); // Show time on LCD #endif // __bis_SR_register(LPM0_bits + GIE); // Sleep until WDT interrupt } // } //
     
    rtc.h

    void rtc_tick(struct tm *t);
     
    rtc.c - Software model of hardware RTC

    #include static int is_leap_year(const int y) { if(y & 3) return 0; // Not divisible by 4 switch(y % 400) { // Divisible by 100, but not by 400 (1900, 2100, 2200, 2300, 2500, 2600) case 100: case 200: case 300: return 0; } return 1; // Divisible by 4 and !(100 and !400) } void rtc_tick(struct tm *t) { static const signed char dim[12][2] = { // Number of days in month for non-leap year and leap year 31, 31, // January 28, 29, // February 31, 31, // March 30, 30, // April 31, 31, // May 30, 30, // June 31, 31, // July 31, 31, // August 30, 30, // September 31, 31, // October 30, 30, // November 31, 31 // December }; // // if(++t->tm_sec > 59) { // Increment seconds, check for overflow t->tm_sec = 0; // Reset seconds if(++t->tm_min > 59) { // Increment minutes, check for overflow t->tm_min = 0; // Reset minutes if(++t->tm_hour > 23) { // Increment hours, check for overflow t->tm_hour = 0; // Reset hours ++t->tm_yday; // Increment day of year if(++t->tm_wday > 6) // Increment day of week, check for overflow t->tm_wday = 0; // Reset day of week // Increment day of month, check for overflow if(++t->tm_mday > dim[t->tm_mon][is_leap_year(t->tm_year + 1900)]) { t->tm_mday = 1; // Reset day of month if(++t->tm_mon > 11) { // Increment month, check for overflow t->tm_mon = 0; // Reset month t->tm_yday = 0; // Reset day of year ++t->tm_year; // Increment year } // - year } // - month } // - day } // - hour } // - minute } //
     
    lcd.h

    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_send(const unsigned char *cmd, unsigned len, const lcd_cmd_type type); void lcd_home(void); void lcd_pos(unsigned char x, unsigned char y); void lcd_clear(unsigned char x); void lcd_init(void); void lcd_fill(unsigned x, unsigned y, unsigned w, unsigned h, unsigned char z); void lcd_print(const char *s, unsigned x, unsigned y); void lcd_pd12(unsigned n, unsigned x, unsigned y);
     
    lcd.c

    #include #include "lcd.h" //static const unsigned TXD = BIT1; static const unsigned RXD = BIT2; static const unsigned SWITCH = BIT3; static const unsigned LCD_CLK = BIT5; static const unsigned LCD_BACKLIGHT = BIT6; static const unsigned LCD_DATA = BIT7; static const unsigned LCD_DC = BIT0; // PORT2 static const unsigned LCD_CE = BIT1; // PORT2 void lcd_send(const unsigned char *cmd, unsigned len, const lcd_cmd_type type) { register unsigned mask; P2OUT &= ~LCD_CE; do { mask = 0x0080; do { if(*cmd & mask) { P1OUT &= ~LCD_CLK; P1OUT |= LCD_DATA; } else { P1OUT &= ~(LCD_CLK | LCD_DATA); } P1OUT |= LCD_CLK; mask >>= 1; } while(!(mask & 1)); if(!type) P2OUT &= ~LCD_DC; if(*cmd & mask) { P1OUT &= ~LCD_CLK; P1OUT |= LCD_DATA; } else { P1OUT &= ~(LCD_CLK | LCD_DATA); } P1OUT |= LCD_CLK; P2OUT |= LCD_DC; if(!(type & 2)) ++cmd; } while(--len); P2OUT |= LCD_CE; } static const unsigned char home[] = { 0x40, 0x80 }; void lcd_home(void) { lcd_send(home, sizeof(home), lcd_command); } void lcd_pos(unsigned char x, unsigned char y) { unsigned char c[2]; c[0] = 0x80 | x; c[1] = 0x40 | y; lcd_send(c, sizeof(c), lcd_command); } void lcd_clear(unsigned char x) { lcd_home(); lcd_send(&x, 504, lcd_data_repeat); lcd_home(); } void lcd_init(void) { static const unsigned char init[] = { 0x20 + 0x01, // function set - extended instructions enabled 0x80 + 64, // set vop (contrast) 0 - 127 0x04 + 0x02, // temperature control 0x10 + 0x03, // set bias system 0x20 + 0x00, // function set - chip active, horizontal addressing, basic instructions 0x08 + 0x04 // display control - normal mode }; P1REN = RXD | SWITCH; P1DIR = LCD_CLK | LCD_BACKLIGHT | LCD_DATA; P1OUT = LCD_CLK | RXD | SWITCH | LCD_BACKLIGHT; P2REN = 0; P2DIR = LCD_DC | LCD_CE; P2OUT = LCD_CE; __delay_cycles(20000); P2OUT |= LCD_DC; __delay_cycles(20000); lcd_send(init, sizeof(init), lcd_command); } void lcd_fill(unsigned x, unsigned y, unsigned w, unsigned h, unsigned char z) { unsigned yy = y + h; unsigned char c[2]; c[0] = 0x80 | x; for(;y < yy; ++y) { c[1] = 0x40 | y; lcd_send(c, sizeof(c), lcd_command); lcd_send(&z, w, lcd_data_repeat); } } static const unsigned char font6x8[96][5] = { 0x00, 0x00, 0x00, 0x00, 0x00, // 20 32 0x00, 0x00, 0x5F, 0x00, 0x00, // 21 33 ! 0x00, 0x07, 0x00, 0x07, 0x00, // 22 34 " 0x14, 0x7F, 0x14, 0x7F, 0x14, // 23 35 # 0x24, 0x2A, 0x7F, 0x2A, 0x12, // 24 36 $ 0x23, 0x13, 0x08, 0x64, 0x62, // 25 37 % 0x36, 0x49, 0x56, 0x20, 0x50, // 26 38 & 0x00, 0x08, 0x07, 0x03, 0x00, // 27 39 ' 0x00, 0x1C, 0x22, 0x41, 0x00, // 28 40 ( 0x00, 0x41, 0x22, 0x1C, 0x00, // 29 41 ) 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, // 2A 42 * 0x08, 0x08, 0x3E, 0x08, 0x08, // 2B 43 + 0x00, 0x40, 0x38, 0x18, 0x00, // 2C 44 , 0x08, 0x08, 0x08, 0x08, 0x08, // 2D 45 - 0x00, 0x00, 0x60, 0x60, 0x00, // 2E 46 . 0x20, 0x10, 0x08, 0x04, 0x02, // 2F 47 / 0x3E, 0x51, 0x49, 0x45, 0x3E, // 30 48 0 0x00, 0x42, 0x7F, 0x40, 0x00, // 31 49 1 0x42, 0x61, 0x51, 0x49, 0x46, // 32 50 2 0x21, 0x41, 0x49, 0x4D, 0x33, // 33 51 3 0x18, 0x14, 0x12, 0x7F, 0x10, // 34 52 4 0x27, 0x45, 0x45, 0x45, 0x39, // 35 53 5 0x3C, 0x4A, 0x49, 0x49, 0x30, // 36 54 6 0x41, 0x21, 0x11, 0x09, 0x07, // 37 55 7 0x36, 0x49, 0x49, 0x49, 0x36, // 38 56 8 0x06, 0x49, 0x49, 0x29, 0x1E, // 39 57 9 0x00, 0x00, 0x14, 0x00, 0x00, // 3A 58 : 0x00, 0x00, 0x40, 0x34, 0x00, // 3B 59 ; 0x00, 0x08, 0x14, 0x22, 0x41, // 3C 60 < 0x14, 0x14, 0x14, 0x14, 0x14, // 3D 61 = 0x00, 0x41, 0x22, 0x14, 0x08, // 3E 62 > 0x02, 0x01, 0x51, 0x09, 0x06, // 3F 63 ? 0x3E, 0x41, 0x5D, 0x59, 0x4E, // 40 64 @ 0x7C, 0x12, 0x11, 0x12, 0x7C, // 41 65 A 0x7F, 0x49, 0x49, 0x49, 0x36, // 42 66 B 0x3E, 0x41, 0x41, 0x41, 0x22, // 43 67 C 0x7F, 0x41, 0x41, 0x41, 0x3E, // 44 68 D 0x7F, 0x49, 0x49, 0x49, 0x41, // 45 69 E 0x7F, 0x09, 0x09, 0x09, 0x01, // 46 70 F 0x3E, 0x41, 0x49, 0x49, 0x7A, // 47 71 G 0x7F, 0x08, 0x08, 0x08, 0x7F, // 48 72 H 0x00, 0x41, 0x7F, 0x41, 0x00, // 49 73 I 0x20, 0x40, 0x41, 0x3F, 0x01, // 4A 74 J 0x7F, 0x08, 0x14, 0x22, 0x41, // 4B 75 K 0x7F, 0x40, 0x40, 0x40, 0x40, // 4C 76 L 0x7F, 0x02, 0x1C, 0x02, 0x7F, // 4D 77 M 0x7F, 0x04, 0x08, 0x10, 0x7F, // 4E 78 N 0x3E, 0x41, 0x41, 0x41, 0x3E, // 4F 79 O 0x7F, 0x09, 0x09, 0x09, 0x06, // 50 80 P 0x3E, 0x41, 0x51, 0x21, 0x5E, // 51 81 Q 0x7F, 0x09, 0x19, 0x29, 0x46, // 52 82 R 0x26, 0x49, 0x49, 0x49, 0x32, // 53 83 S 0x01, 0x01, 0x7F, 0x01, 0x01, // 54 84 T 0x3F, 0x40, 0x40, 0x40, 0x3F, // 55 85 U 0x1F, 0x20, 0x40, 0x20, 0x1F, // 56 86 V 0x3F, 0x40, 0x38, 0x40, 0x3F, // 57 87 W 0x63, 0x14, 0x08, 0x14, 0x63, // 58 88 X 0x03, 0x04, 0x78, 0x04, 0x03, // 59 89 Y 0x61, 0x51, 0x49, 0x45, 0x43, // 5A 90 Z 0x00, 0x7F, 0x41, 0x41, 0x41, // 5B 91 [ 0x02, 0x04, 0x08, 0x10, 0x20, // 5C 92 '\' 0x00, 0x41, 0x41, 0x41, 0x7F, // 5D 93 ] 0x04, 0x02, 0x01, 0x02, 0x04, // 5E 94 ^ 0x80, 0x80, 0x80, 0x80, 0x80, // 5F 95 _ 0x00, 0x03, 0x07, 0x08, 0x00, // 60 96 ' 0x20, 0x54, 0x54, 0x54, 0x78, // 61 97 a 0x7F, 0x28, 0x44, 0x44, 0x38, // 62 98 b 0x38, 0x44, 0x44, 0x44, 0x28, // 63 99 c 0x38, 0x44, 0x44, 0x28, 0x7F, // 64 100 d 0x38, 0x54, 0x54, 0x54, 0x18, // 65 101 e 0x00, 0x08, 0x7E, 0x09, 0x02, // 66 102 f 0x18, 0xA4, 0xA4, 0xA4, 0x7C, // 67 103 g 0x7F, 0x08, 0x04, 0x04, 0x78, // 68 104 h 0x00, 0x44, 0x7D, 0x40, 0x00, // 69 105 i 0x00, 0x20, 0x40, 0x40, 0x3D, // 6A 106 j 0x00, 0x7F, 0x10, 0x28, 0x44, // 6B 107 k 0x00, 0x41, 0x7F, 0x40, 0x00, // 6C 108 l 0x7C, 0x04, 0x78, 0x04, 0x78, // 6D 109 m 0x7C, 0x08, 0x04, 0x04, 0x78, // 6E 110 n 0x38, 0x44, 0x44, 0x44, 0x38, // 6F 111 o 0xFC, 0x18, 0x24, 0x24, 0x18, // 70 112 p 0x18, 0x24, 0x24, 0x18, 0xFC, // 71 113 q 0x7C, 0x08, 0x04, 0x04, 0x08, // 72 114 r 0x48, 0x54, 0x54, 0x54, 0x24, // 73 115 s 0x04, 0x04, 0x3F, 0x44, 0x24, // 74 116 t 0x3C, 0x40, 0x40, 0x20, 0x7C, // 75 117 u 0x1C, 0x20, 0x40, 0x20, 0x1C, // 76 118 v 0x3C, 0x40, 0x30, 0x40, 0x3C, // 77 119 w 0x44, 0x28, 0x10, 0x28, 0x44, // 78 120 x 0x4C, 0x90, 0x90, 0x90, 0x7C, // 79 121 y 0x44, 0x64, 0x54, 0x4C, 0x44, // 7A 122 z 0x00, 0x08, 0x36, 0x41, 0x00, // 7B 123 { 0x00, 0x00, 0x77, 0x00, 0x00, // 7C 124 | 0x00, 0x41, 0x36, 0x08, 0x00, // 7D 125 } 0x02, 0x01, 0x02, 0x04, 0x02, // 7E 126 ~ 0x00, 0x06, 0x09, 0x09, 0x06, // 7F 127 degrees }; void lcd_print(const char *s, unsigned x, unsigned y) { unsigned char c[2]; c[0] = 0x80 | x; c[1] = 0x40 | y; lcd_send(c, sizeof(c), lcd_command); while(*s) { lcd_send(&font6x8[*s - 32][0], 5, lcd_data); lcd_send(&font6x8[0][0], 1, lcd_data); ++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 }; void lcd_pd12(unsigned n, unsigned x, unsigned y) { unsigned char c[2]; c[0] = 0x80 | x; c[1] = 0x40 + y; lcd_send(c, 2, lcd_command); lcd_send(num11x16[n], 11, lcd_data); c[1] = 0x41 + y; lcd_send(c, 2, lcd_command); lcd_send(num11x16[n] + 11, 11, lcd_data); }
  19. Like
    gordon reacted to oPossum in Using the internal temperature sensor   
    TI has some sample code for the internal temperature sensor, but it does not explain how to scale the ADC reading to useful units of degrees. Here is a step-by-step explanation of how to do the scaling with integer math for degrees C, K and F. There is also sample code to display the temperature on a Nokia 5110 LCD.

     
    The data sheet (SLAU144) has this formula for converting temperature in degrees Celsius to voltage.
    V = 0.00355 * C + 0.986

    What we need is a formula for converting voltage to temperature.
     
    Rewrite the data sheet fomula with temperature on the left
    0.00355 * C + 0.986 = V
     
    Divide both sides by 0.00355
    C + 277.75 = V / 0.00355
     
    Subtract 277.75 from both sides
    C = V / 0.00355 - 277.75
     
    Now we have a formula for converting voltage to temperature.
     
    The data sheet has this formula for converting voltage to ADC value, once again the opposite of what we neeed.

    For Vref- == 0
    A = 1023 * V / Vref
     
    Swap sides
    1023 * V / Vref = A
     
    Multiply by Vref
    1023 * V = A * Vref
     
    Divide by 1023
    V = A * Vref / 1023
     
    For a 1.5V reference
    V = A * 1.5 / 1023
     
    Simplify
    V = A * 0.0014663
     
    Substitute ADC conversion forumula for voltage in the temperature conversion formula.
    C = A * 0.0014663 / 0.00355 - 277.75
     
    Simplify
    C = A * 0.413 - 277.75
     
    Now we have a formula to convert ADC reading to temperature.
    It uses real numbers, so floating point math is required for good precision.
    Floating point is slow and requires more flash, so let's use integer math instead.
    Multiply by 65536 (2^16) and then divide by the same.
    C = (A * 27069 - 18202393) / 65536
     
    Use a right shift instead of divide. This will become a move of high word to low word.
    C = (A * 27069 - 18202393) >> 16
     
    Add 0.5 * 65536 to impove rounding.
    C = (A * 27069 - 18202393 + 32768) >> 16
     
    Simplify.
    C = (A * 27069 - 18169625) >> 16
     
    So that is how to go from ADC to degrees Celsius.
     
     
    To convert degrees C to degees K.
    K = C + 273.15
     
    Applied to ADC to degrees C conversion formula.
    K = (A * 27069 - 18169625) >> 16 - 273.15
     
    Implement with integer math by multiplying by 65536
    K = (A * 27069 - 18169625 - 17,901,158) >> 16
     
    Simplify.
    K = (A * 27069 - 268467) >> 16
     
    To convert degrees C to degrees F.
    F = C * 9 / 5 + 32
     
    Applied to voltage to degrees C conversion forumula
    F = (V / 0.00355 - 277.75) * 9 / 5 + 32
     
    Multiply by 9
    F = (V / 0.0003944 - 2499.75) / 5 + 32
     
    Divide by 5
    F = (V / 0.0019722 - 499.95) + 32
     
    Add 32
    F = V / 0.0019722 - 467.95
     
    Substitute ADC to voltage forumula
    F = A * 0.0014663 / 0.0019722 - 467.95
     
    Simplifiy
    F = A * 0.7435 - 467.95
     
    Convert to integer
    F = (A * 48724 - 30667156) >> 16
     
    Improve rounding
    F = (A * 48724 - 30667156 + 32768) >> 16
     
    Simplify
    F = (A * 48724 - 30634388) >> 16
     
    So now we have three formulas to convert ADC reading to degrees C, K and F using fast and compact integer math.
    C = (A * 27069 - 18169625) >> 16
    K = (A * 27069 - 268467) >> 16
    F = (A * 48724 - 30634388) >> 16
     
    Using the ADC value, rather than a different temperature scale, will ensure greatest precision for each temperature scale.
     
    main.c

    #include #include #include "lcd.h" #define ADC_SLEEP // Sleep during ADC conversion //#define SHOW_ADC // Show ADC raw and ADC millivolts // 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); pd12(d.rem, x -= 12, y); } while(d.quot); if(neg) pd12(14, x -= 12, y); while(x) pd12(10, x -= 12, y); } // Print integer from 0 to 9999 vertically using 6 x 8 font void print_v(int i, unsigned x) { unsigned y = 4; unsigned c; if(i < 0 || i > 9999) return; div_t d; d.quot = i; do { d = div(d.quot, 10); c = d.rem + '0'; lcd_print((char *)&c, x, --y); } while(d.quot); c = ' '; while(y) lcd_print((char *)&c, x, --y); } void main(void) { unsigned adc; // ADC value int c, k, f; // Temperature in degrees C, K, and F unsigned mv; // ADC reading in millivolts // WDTCTL = WDTPW | WDTHOLD; // Disable watchdog reset // lcd_init(); // Initialize LCD lcd_clear(0); // pd12(15, 48, 0); // Degrees pd12(17, 59, 0); // F pd12(15, 48, 2); // Degrees pd12(16, 58, 2); // C pd12(15, 48, 4); // Degrees pd12(18, 59, 4); // K #ifdef SHOW_ADC // lcd_print("Am", 72, 4); // AD / mV lcd_print("DV", 72, 5); // #endif // // ADC10CTL0 = 0; // Configure ADC ADC10CTL1 = INCH_10 | ADC10DIV_3; // ADC10CTL0 = SREF_1 | ADC10SHT_3 | REFON | ADC10ON | ADC10IE; //ADC10CTL0 = SREF_1 | ADC10SHT_3 | REFON | ADC10ON | ADC10IE | REF2_5V; #ifdef ADC_SLEEP // ADC10CTL0 |= ADC10IE; // Enable ADC conversion complete interrupt #endif // // for(; { // for-ever #ifdef ADC_SLEEP // ADC10CTL0 |= (ENC | ADC10SC); // Begin ADC conversion __bis_SR_register(LPM0_bits + GIE); // Sleep until conversion complete #else // ADC10CTL0 &= ~ADC10IFG; // Clear conversion complete flag ADC10CTL0 |= (ENC | ADC10SC); // Begin ADC conversion while(!(ADC10CTL0 & ADC10IFG)); // Wait for conversion to complete #endif // // adc = ADC10MEM; // Read ADC // // Convert to temperature c = ((27069L * adc) - 18169625L) >> 16; // Vref = 1.5V //c = ((45115L * adc) - 18169625L) >> 16; // Vref = 2.5V // k = ((27069L * adc) - 268467L) >> 16; // Vref = 1.5V //k = ((45115L * adc) - 268467L) >> 16; // Vref = 2.5V // f = ((48724L * adc) - 30634388L) >> 16; // Vref = 1.5V //f = ((81206L * adc) - 30634388L) >> 16; // Vref = 2.5V // // Convert to millivolts mv = (96094L * adc + 32768) >> 16; // Vref = 1.5V //mv = (160156L * adc + 32768) >> 16; // Vref = 2.5V // // Display on LCD print_int(f, 0); // Degrees F print_int(c, 2); // Degrees C print_int(k, 4); // Degrees K // #ifdef SHOW_ADC // print_v(adc, 72); // ADC print_v(mv, 78); // ADC millivolts #endif // // //__delay_cycles(100000); // } // } #pragma vector = ADC10_VECTOR // ADC conversion complete interrupt __interrupt void ADC10_ISR(void) // { // __bic_SR_register_on_exit(LPM0_bits); // Wakeup main code } //
     
    lcd.h

    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_send(const unsigned char *cmd, unsigned len, const lcd_cmd_type type); void lcd_home(void); void lcd_pos(unsigned char x, unsigned char y); void lcd_clear(unsigned char x); void lcd_init(void); void lcd_print(char *s, unsigned x, unsigned y); void pd12(unsigned n, unsigned x, unsigned y);
     
    lcd.c

    #include #include "lcd.h" //static const unsigned TXD = BIT1; static const unsigned RXD = BIT2; static const unsigned SWITCH = BIT3; static const unsigned LCD_CLK = BIT5; static const unsigned LCD_BACKLIGHT = BIT6; static const unsigned LCD_DATA = BIT7; static const unsigned LCD_DC = BIT0; // PORT2 static const unsigned LCD_CE = BIT1; // PORT2 void lcd_send(const unsigned char *cmd, unsigned len, const lcd_cmd_type type) { register unsigned mask; P2OUT &= ~LCD_CE; do { mask = 0x0080; do { if(*cmd & mask) { P1OUT &= ~LCD_CLK; P1OUT |= LCD_DATA; } else { P1OUT &= ~(LCD_CLK | LCD_DATA); } P1OUT |= LCD_CLK; mask >>= 1; } while(!(mask & 1)); if(!type) P2OUT &= ~LCD_DC; if(*cmd & mask) { P1OUT &= ~LCD_CLK; P1OUT |= LCD_DATA; } else { P1OUT &= ~(LCD_CLK | LCD_DATA); } P1OUT |= LCD_CLK; P2OUT |= LCD_DC; if(!(type & 2)) ++cmd; } while(--len); P2OUT |= LCD_CE; } static const unsigned char home[] = { 0x40, 0x80 }; void lcd_home(void) { lcd_send(home, sizeof(home), lcd_command); } void lcd_pos(unsigned char x, unsigned char y) { unsigned char c[2]; c[0] = 0x80 | x; c[1] = 0x40 | y; lcd_send(c, sizeof(c), lcd_command); } void lcd_clear(unsigned char x) { lcd_home(); lcd_send(&x, 504, lcd_data_repeat); lcd_home(); } void lcd_init(void) { static const unsigned char init[] = { 0x20 + 0x01, // function set - extended instructions enabled //0x80 + 64, // set vop (contrast) 0 - 127 0x80 + 66, // set vop (contrast) 0 - 127 0x04 + 0x02, // temperature control 0x10 + 0x03, // set bias system 0x20 + 0x00, // function set - chip active, horizontal addressing, basic instructions 0x08 + 0x04 // display control - normal mode }; P1REN = RXD | SWITCH; P1DIR = LCD_CLK | LCD_BACKLIGHT | LCD_DATA; P1OUT = LCD_CLK | RXD | SWITCH | LCD_BACKLIGHT; P2REN = 0; P2DIR = LCD_DC | LCD_CE; P2OUT = LCD_CE; __delay_cycles(20000); P2OUT |= LCD_DC; __delay_cycles(20000); lcd_send(init, sizeof(init), lcd_command); } static const unsigned char font6x8[96][5] = { 0x00, 0x00, 0x00, 0x00, 0x00, // 20 32 0x00, 0x00, 0x5F, 0x00, 0x00, // 21 33 ! 0x00, 0x07, 0x00, 0x07, 0x00, // 22 34 " 0x14, 0x7F, 0x14, 0x7F, 0x14, // 23 35 # 0x24, 0x2A, 0x7F, 0x2A, 0x12, // 24 36 $ 0x23, 0x13, 0x08, 0x64, 0x62, // 25 37 % 0x36, 0x49, 0x56, 0x20, 0x50, // 26 38 & 0x00, 0x08, 0x07, 0x03, 0x00, // 27 39 ' 0x00, 0x1C, 0x22, 0x41, 0x00, // 28 40 ( 0x00, 0x41, 0x22, 0x1C, 0x00, // 29 41 ) 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, // 2A 42 * 0x08, 0x08, 0x3E, 0x08, 0x08, // 2B 43 + 0x00, 0x40, 0x38, 0x18, 0x00, // 2C 44 , 0x08, 0x08, 0x08, 0x08, 0x08, // 2D 45 - 0x00, 0x00, 0x60, 0x60, 0x00, // 2E 46 . 0x20, 0x10, 0x08, 0x04, 0x02, // 2F 47 / 0x3E, 0x51, 0x49, 0x45, 0x3E, // 30 48 0 0x00, 0x42, 0x7F, 0x40, 0x00, // 31 49 1 0x42, 0x61, 0x51, 0x49, 0x46, // 32 50 2 0x21, 0x41, 0x49, 0x4D, 0x33, // 33 51 3 0x18, 0x14, 0x12, 0x7F, 0x10, // 34 52 4 0x27, 0x45, 0x45, 0x45, 0x39, // 35 53 5 0x3C, 0x4A, 0x49, 0x49, 0x30, // 36 54 6 0x41, 0x21, 0x11, 0x09, 0x07, // 37 55 7 0x36, 0x49, 0x49, 0x49, 0x36, // 38 56 8 0x06, 0x49, 0x49, 0x29, 0x1E, // 39 57 9 0x00, 0x00, 0x14, 0x00, 0x00, // 3A 58 : 0x00, 0x00, 0x40, 0x34, 0x00, // 3B 59 ; 0x00, 0x08, 0x14, 0x22, 0x41, // 3C 60 < 0x14, 0x14, 0x14, 0x14, 0x14, // 3D 61 = 0x00, 0x41, 0x22, 0x14, 0x08, // 3E 62 > 0x02, 0x01, 0x51, 0x09, 0x06, // 3F 63 ? 0x3E, 0x41, 0x5D, 0x59, 0x4E, // 40 64 @ 0x7C, 0x12, 0x11, 0x12, 0x7C, // 41 65 A 0x7F, 0x49, 0x49, 0x49, 0x36, // 42 66 B 0x3E, 0x41, 0x41, 0x41, 0x22, // 43 67 C 0x7F, 0x41, 0x41, 0x41, 0x3E, // 44 68 D 0x7F, 0x49, 0x49, 0x49, 0x41, // 45 69 E 0x7F, 0x09, 0x09, 0x09, 0x01, // 46 70 F 0x3E, 0x41, 0x49, 0x49, 0x7A, // 47 71 G 0x7F, 0x08, 0x08, 0x08, 0x7F, // 48 72 H 0x00, 0x41, 0x7F, 0x41, 0x00, // 49 73 I 0x20, 0x40, 0x41, 0x3F, 0x01, // 4A 74 J 0x7F, 0x08, 0x14, 0x22, 0x41, // 4B 75 K 0x7F, 0x40, 0x40, 0x40, 0x40, // 4C 76 L 0x7F, 0x02, 0x1C, 0x02, 0x7F, // 4D 77 M 0x7F, 0x04, 0x08, 0x10, 0x7F, // 4E 78 N 0x3E, 0x41, 0x41, 0x41, 0x3E, // 4F 79 O 0x7F, 0x09, 0x09, 0x09, 0x06, // 50 80 P 0x3E, 0x41, 0x51, 0x21, 0x5E, // 51 81 Q 0x7F, 0x09, 0x19, 0x29, 0x46, // 52 82 R 0x26, 0x49, 0x49, 0x49, 0x32, // 53 83 S 0x01, 0x01, 0x7F, 0x01, 0x01, // 54 84 T 0x3F, 0x40, 0x40, 0x40, 0x3F, // 55 85 U 0x1F, 0x20, 0x40, 0x20, 0x1F, // 56 86 V 0x3F, 0x40, 0x38, 0x40, 0x3F, // 57 87 W 0x63, 0x14, 0x08, 0x14, 0x63, // 58 88 X 0x03, 0x04, 0x78, 0x04, 0x03, // 59 89 Y 0x61, 0x51, 0x49, 0x45, 0x43, // 5A 90 Z 0x00, 0x7F, 0x41, 0x41, 0x41, // 5B 91 [ 0x02, 0x04, 0x08, 0x10, 0x20, // 5C 92 '\' 0x00, 0x41, 0x41, 0x41, 0x7F, // 5D 93 ] 0x04, 0x02, 0x01, 0x02, 0x04, // 5E 94 ^ 0x80, 0x80, 0x80, 0x80, 0x80, // 5F 95 _ 0x00, 0x03, 0x07, 0x08, 0x00, // 60 96 ' 0x20, 0x54, 0x54, 0x54, 0x78, // 61 97 a 0x7F, 0x28, 0x44, 0x44, 0x38, // 62 98 b 0x38, 0x44, 0x44, 0x44, 0x28, // 63 99 c 0x38, 0x44, 0x44, 0x28, 0x7F, // 64 100 d 0x38, 0x54, 0x54, 0x54, 0x18, // 65 101 e 0x00, 0x08, 0x7E, 0x09, 0x02, // 66 102 f 0x18, 0xA4, 0xA4, 0xA4, 0x7C, // 67 103 g 0x7F, 0x08, 0x04, 0x04, 0x78, // 68 104 h 0x00, 0x44, 0x7D, 0x40, 0x00, // 69 105 i 0x00, 0x20, 0x40, 0x40, 0x3D, // 6A 106 j 0x00, 0x7F, 0x10, 0x28, 0x44, // 6B 107 k 0x00, 0x41, 0x7F, 0x40, 0x00, // 6C 108 l 0x7C, 0x04, 0x78, 0x04, 0x78, // 6D 109 m 0x7C, 0x08, 0x04, 0x04, 0x78, // 6E 110 n 0x38, 0x44, 0x44, 0x44, 0x38, // 6F 111 o 0xFC, 0x18, 0x24, 0x24, 0x18, // 70 112 p 0x18, 0x24, 0x24, 0x18, 0xFC, // 71 113 q 0x7C, 0x08, 0x04, 0x04, 0x08, // 72 114 r 0x48, 0x54, 0x54, 0x54, 0x24, // 73 115 s 0x04, 0x04, 0x3F, 0x44, 0x24, // 74 116 t 0x3C, 0x40, 0x40, 0x20, 0x7C, // 75 117 u 0x1C, 0x20, 0x40, 0x20, 0x1C, // 76 118 v 0x3C, 0x40, 0x30, 0x40, 0x3C, // 77 119 w 0x44, 0x28, 0x10, 0x28, 0x44, // 78 120 x 0x4C, 0x90, 0x90, 0x90, 0x7C, // 79 121 y 0x44, 0x64, 0x54, 0x4C, 0x44, // 7A 122 z 0x00, 0x08, 0x36, 0x41, 0x00, // 7B 123 { 0x00, 0x00, 0x77, 0x00, 0x00, // 7C 124 | 0x00, 0x41, 0x36, 0x08, 0x00, // 7D 125 } 0x02, 0x01, 0x02, 0x04, 0x02, // 7E 126 ~ 0x00, 0x06, 0x09, 0x09, 0x06, // 7F 127 degrees }; void lcd_print(char *s, unsigned x, unsigned y) { unsigned char c[2]; c[0] = 0x80 | x; c[1] = 0x40 | y; lcd_send(c, sizeof(c), lcd_command); while(*s) { lcd_send(&font6x8[*s - 32][0], 5, lcd_data); lcd_send(&font6x8[0][0], 1, lcd_data); ++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 }; void pd12(unsigned n, unsigned x, unsigned y) { unsigned char c[2]; c[0] = 0x80 | x; c[1] = 0x40 + y; lcd_send(c, 2, lcd_command); lcd_send(num11x16[n], 11, lcd_data); c[1] = 0x41 + y; lcd_send(c, 2, lcd_command); lcd_send(num11x16[n] + 11, 11, lcd_data); }
  20. Like
    gordon got a reaction from fj604 in Programming/Debugging with external power   
    Conect test, reset and ground (but NOT VCC) from the FET to your target.
  21. Like
    gordon reacted to Tribes in MSP430 PC GUI Eval Tool   
    Sooo, I was bored today(and a little bit hungover)... so I was looking for something to do and remembered this:
     
    And I thought: Why not... shouldn't be that hard.
     
    GUI.cpp

    // Nathan Zimmerman MSP430 GUI EVAL // Version 0.4 // Copyright Nathan Zimmerman: Not authorized for commercial use or self promotion in any way. // Strictly for debug and learning purposes. //Sorry for the mess. Will be cleaned up when I finish #include #include #include #include #include //File includes #include // Serial // #include "serial.h" //Global Variables wxString comportnum; int send_c = 0; int send_d = 0; bool toggle_R = true; bool toggle_G = true; bool DO_mode = false; unsigned int port1_out_global = 0; unsigned int port2_out_global = 0; unsigned int port1_dir_global = 0; unsigned int port2_dir_global = 0; unsigned int port1_ren_global = 0; unsigned int port2_ren_global = 0; int port1ren = 0; wxString choices[] = { wxT("P1.0"), //0 wxT("P1.1(Locked)"), //1 wxT("P1.2(Locked)"), //2 wxT("P1.3"), //3 wxT("P1.4"), //4 wxT("P1.5"), //5 wxT("P1.6"), //6 wxT("P1.7"), //7 wxT("P2.0"), //8 wxT("P2.1"), //9 wxT("P2.2"), //10 wxT("P2.3"), //11 wxT("P2.4"), //12 wxT("P2.5"), //13 wxT("Select Port") }; wxString chipselect[] = { wxT("P1.0"), //0 wxT("P1.3"), //1 wxT("P1.4"), //2 wxT("P2.0"), //3 wxT("P2.1"), //4 wxT("P2.2"), //5 wxT("P2.3"), //6 wxT("P2.4"), //7 wxT("P2.5"), //8 wxT("Chip Select") }; wxString bytes_to_send[] = { wxT("1"), //0 wxT("2"), //1 wxT("3"), //2 wxT("4"), //3 wxT("5"), //4 wxT("6"), //5 wxT("7"), //6 wxT("8"), //7 wxT("# of Bytes to Send") }; wxString baud_select[] = { wxT("1Mhz (unstable)"), //0 wxT("500k (unstable)"), //1 wxT("100k"), //2 wxT("10k"), //3 wxT("1k"), //4 wxT("Select Baud") }; wxTimer *DI_TIMER; DWORD x; DWORD n; char buf[20]; char tbuf[20]; //Global Functions //Command Functions void P1DIR(unsigned int port, bool set_zero); void P1OUT(unsigned int port, bool set_zero); void P1REN(unsigned int port, bool set_zero); void P1SEL(unsigned int port, bool set_zero); void P1SEL2(unsigned int port, bool set_zero); void P2DIR(unsigned int port, bool set_zero); void P2OUT(unsigned int port, bool set_zero); void P2REN(unsigned int port, bool set_zero); void P2SEL(unsigned int port, bool set_zero); void P2SEL2(unsigned int port, bool set_zero); void PXIN(); //My App class MyApp : public wxApp { public: virtual bool OnInit(); }; class MyFrame : public wxFrame { public: wxBookCtrl *book; wxListBox *listbox1; wxTextCtrl *textLog; wxTextCtrl *comport_txt; wxTextCtrl *recieved_D; wxTextCtrl *port1DI, *port2DI,*portS; wxStaticText *connection_status; wxStaticText *m_text_display,*status_text_spi; wxStaticText *port_selected_text; wxButton *Red_LED_Button; wxButton *Green_LED_Button; wxCheckBox *CP10D, *CP11D, *CP12D, *CP13D, *CP14D, *CP15D, *CP16D, *CP17D, *CP20D,*CP21D,*CP22D,*CP23D,*CP24D,*CP25D; wxCheckBox *CP10O, *CP11O, *CP12O, *CP13O, *CP14O, *CP15O, *CP16O, *CP17O, *CP20O,*CP21O,*CP22O,*CP23O,*CP24O,*CP25O; wxCheckBox *Timer_Start; wxCheckBox *port_as_input; wxCheckBox *port_pullup_enable; wxChoice *DI_PORT_SELECT; wxChoice *select_baud, *select_bytes, *select_chip_select; wxButton *send_Packet; wxTextCtrl *send0, *send1, *send2, *send3, *send4, *send5, *send6, *send7, *recv0, *recv1, *recv2, *recv3, *recv4, *recv5, *recv6, *recv7; MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size); void OnPageChanged(wxBookCtrlEvent &event ); void OnButton1( wxCommandEvent &event ); void OnButton2( wxCommandEvent &event ); void OnListBoxDoubleClick( wxCommandEvent &event ); void OnQuit(wxCommandEvent& event); void OnClose(wxCloseEvent& event); void OnAbout(wxCommandEvent& event); void OnButtonConnect(wxCommandEvent &event); void OnChecked(wxCommandEvent &event); void onstartTimer(wxCommandEvent &event); void OnDITimer(wxTimerEvent& event); void DI_INPUT(wxCommandEvent &event); void On_DI_Check(wxCommandEvent &event); void On_send_Packet(wxCommandEvent &event); void On_select(wxCommandEvent &event); void On_chip(wxCommandEvent &event); private: DECLARE_EVENT_TABLE() }; // Declare some IDs. These are arbitrary. const int ID_BOOK = 1000; const int BOOKCTRL = 100; const int BUTTON1 = 101; const int BUTTON2 = 102; const int LISTBOX1 = 103; const int TEXTBOX1 = 104; const int CHECKEDBOX = 231; const int CONNECTBUTTON = 107; const int ID_DI_TIMER = 240; const int ID_Start_Timer = 241; const int ID_DI_INPUT = 242; const int ID_DI_CHECK =243; const int ID_send_Packet=244; const int ID_select = 245; const int ID_chip=246; const int FILE_QUIT = wxID_EXIT; const int HELP_ABOUT = wxID_ABOUT; // Attach the event handlers. Put this after MyFrame declaration. BEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_BOOKCTRL_PAGE_CHANGED(BOOKCTRL, MyFrame::OnPageChanged) EVT_TIMER (ID_DI_TIMER, MyFrame::OnDITimer) EVT_CHECKBOX(ID_Start_Timer, MyFrame::onstartTimer) EVT_BUTTON(BUTTON1, MyFrame::OnButton1) EVT_BUTTON(BUTTON2, MyFrame::OnButton2) EVT_BUTTON(ID_send_Packet, MyFrame::On_send_Packet) EVT_LISTBOX_DCLICK(LISTBOX1,MyFrame::OnListBoxDoubleClick) EVT_MENU(FILE_QUIT, MyFrame::OnQuit) EVT_CHECKBOX(CHECKEDBOX, MyFrame::OnChecked) EVT_CHECKBOX(ID_DI_CHECK, MyFrame::On_DI_Check) EVT_MENU(HELP_ABOUT, MyFrame::OnAbout) EVT_BUTTON(CONNECTBUTTON, MyFrame::OnButtonConnect) EVT_CHOICE(ID_DI_INPUT, MyFrame::DI_INPUT) EVT_CHOICE(ID_select, MyFrame::On_select) EVT_CHOICE(ID_chip, MyFrame::On_chip) EVT_CLOSE(MyFrame::OnClose) END_EVENT_TABLE() IMPLEMENT_APP(MyApp) bool MyApp::OnInit() { MyFrame *frame = new MyFrame( _("MSP430G2553 EVAL TOOL V0.4"), wxPoint(50, 50), wxSize(600, 400) ); //AP Title frame->Show(true); return true; } MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) : wxFrame(NULL, -1, title, pos, size) { int chkbx_height = 165; DI_TIMER = new wxTimer(this, ID_DI_TIMER); SetIcon(wxICON(sample)); wxMenu *fileMenu = new wxMenu; wxMenu *helpMenu = new wxMenu; helpMenu->Append(HELP_ABOUT, _T("&About...\tF1"), _T("Show about dialog")); fileMenu->Append(FILE_QUIT, _T("E&xit\tAlt-X"), _T("Quit this program")); wxMenuBar *menuBar = new wxMenuBar(); menuBar->Append(fileMenu, _T("&File")); menuBar->Append(helpMenu, _T("&Help")); SetMenuBar(menuBar); CreateStatusBar(1); SetStatusText(_T("Developed By Nathan Zimmerman"), 0); book = new wxBookCtrl(this, BOOKCTRL); wxPanel *panel = new wxPanel(book); (void)new wxStaticText(panel, wxID_ANY, _T("Welcome to the MSP430 Eval Tool! Please connect your device. "),wxPoint(5,5),wxSize(450,15)); (void)new wxStaticText(panel, wxID_ANY, _T("Enter Comm Port # (Example: \"COM1\")"),wxPoint(15, 30), wxSize(250, 20)); (void)new wxStaticText(panel, wxID_ANY, _T("Information: This tool is designed to function as a GUI to control specific port IO for the MSP430G2553 MCU. This GUI is meant to interface with the MSP430 Launchpad. Below are 2 example buttons that will toggle DO port 1.0 and 1.6. Leds on the launchpad should blink accordingly if set. "),wxPoint(5,110),wxSize(550,65)); comport_txt = new wxTextCtrl(panel, wxID_ANY, _T(""), wxPoint(15, 50),wxSize(100, 25)); recieved_D = new wxTextCtrl(panel, wxID_ANY, _T(""), wxPoint(350, 50),wxSize(100, 25)); connection_status = new wxStaticText(panel, wxID_ANY, _T("Status: Not Connected : GUI Disconnected"),wxPoint(15, 80), wxSize(250, 20)); m_text_display = new wxStaticText(panel, wxID_ANY, _T("Recieved RS232 Data:"),wxPoint(350, 30), wxSize(250, 20)); Red_LED_Button = new wxButton( panel, BUTTON2,_T("Toggle Red LED"), wxPoint(220,185), wxSize(200,30) ); Green_LED_Button = new wxButton( panel, BUTTON1,_T("Toggle Green LED"), wxPoint(10,185), wxSize(200,30) ); Red_LED_Button->Enable(false); Green_LED_Button->Enable(false); new wxButton( panel, CONNECTBUTTON , _T("Connect"), wxPoint(120,50), wxSize(100,25) ); book->AddPage(panel, _T("Connection"), true); panel = new wxPanel(book); (void)new wxStaticText(panel, wxID_ANY, _T("Digital Outputs Tab: Define any GPIO as an output else input. Set any GPIO output to 0/1. P1.1 and P1.2 are protected for USB Comm. \n\nDefine Ports as Digital Outputs: "),wxPoint(5,5),wxSize(500,65)); CP10D = new wxCheckBox (panel, CHECKEDBOX, _T("P1.0"),wxPoint(10, 80), wxSize(50, 20)); CP11D = new wxCheckBox (panel, CHECKEDBOX, _T("P1.1"),wxPoint(70, 80), wxSize(50, 20)); CP12D = new wxCheckBox (panel, CHECKEDBOX, _T("P1.2"),wxPoint(130, 80), wxSize(50, 20)); CP13D = new wxCheckBox (panel, CHECKEDBOX, _T("P1.3"),wxPoint(190, 80), wxSize(50, 20)); CP14D = new wxCheckBox (panel, CHECKEDBOX, _T("P1.4"),wxPoint(250, 80), wxSize(50, 20)); CP15D = new wxCheckBox (panel, CHECKEDBOX, _T("P1.5"),wxPoint(310, 80), wxSize(50, 20)); CP16D = new wxCheckBox (panel, CHECKEDBOX, _T("P1.6"),wxPoint(370, 80), wxSize(50, 20)); CP17D = new wxCheckBox (panel, CHECKEDBOX, _T("P1.7"),wxPoint(430, 80), wxSize(50, 20)); CP20D = new wxCheckBox (panel, CHECKEDBOX, _T("P2.0"),wxPoint(10, 110), wxSize(50, 20)); CP21D = new wxCheckBox (panel, CHECKEDBOX, _T("P2.1"),wxPoint(70, 110), wxSize(50, 20)); CP22D = new wxCheckBox (panel, CHECKEDBOX, _T("P2.2"),wxPoint(130, 110), wxSize(50, 20)); CP23D = new wxCheckBox (panel, CHECKEDBOX, _T("P2.3"),wxPoint(190, 110), wxSize(50, 20)); CP24D = new wxCheckBox (panel, CHECKEDBOX, _T("P2.4"),wxPoint(250, 110), wxSize(50, 20)); CP25D = new wxCheckBox (panel, CHECKEDBOX, _T("P2.5"),wxPoint(310, 110), wxSize(50, 20)); (void)new wxStaticText(panel, wxID_ANY, _T("Set Port Output to 0/1:"),wxPoint(5,140),wxSize(200,20)); CP10O = new wxCheckBox (panel, CHECKEDBOX, _T("P1.0"),wxPoint(10, chkbx_height), wxSize(50, 20)); CP11O = new wxCheckBox (panel, CHECKEDBOX, _T("P1.1"),wxPoint(70, chkbx_height), wxSize(50, 20)); CP12O = new wxCheckBox (panel, CHECKEDBOX, _T("P1.2"),wxPoint(130, chkbx_height), wxSize(50, 20)); CP13O = new wxCheckBox (panel, CHECKEDBOX, _T("P1.3"),wxPoint(190, chkbx_height), wxSize(50, 20)); CP14O = new wxCheckBox (panel, CHECKEDBOX, _T("P1.4"),wxPoint(250, chkbx_height), wxSize(50, 20)); CP15O = new wxCheckBox (panel, CHECKEDBOX, _T("P1.5"),wxPoint(310, chkbx_height), wxSize(50, 20)); CP16O = new wxCheckBox (panel, CHECKEDBOX, _T("P1.6"),wxPoint(370, chkbx_height), wxSize(50, 20)); CP17O = new wxCheckBox (panel, CHECKEDBOX, _T("P1.7"),wxPoint(430, chkbx_height), wxSize(50, 20)); CP20O = new wxCheckBox (panel, CHECKEDBOX, _T("P2.0"),wxPoint(10, chkbx_height+30), wxSize(50, 20)); CP21O = new wxCheckBox (panel, CHECKEDBOX, _T("P2.1"),wxPoint(70, chkbx_height+30), wxSize(50, 20)); CP22O = new wxCheckBox (panel, CHECKEDBOX, _T("P2.2"),wxPoint(130, chkbx_height+30), wxSize(50, 20)); CP23O = new wxCheckBox (panel, CHECKEDBOX, _T("P2.3"),wxPoint(190, chkbx_height+30), wxSize(50, 20)); CP24O = new wxCheckBox (panel, CHECKEDBOX, _T("P2.4"),wxPoint(250, chkbx_height+30), wxSize(50, 20)); CP25O = new wxCheckBox (panel, CHECKEDBOX, _T("P2.5"),wxPoint(310, chkbx_height+30), wxSize(50, 20)); CP11D->SetValue (true); CP12D->SetValue (true); CP11O->SetValue (true); CP12O->SetValue (true); CP10D->Enable(false); CP11D->Enable(false); CP12D->Enable(false); CP13D->Enable(false); CP14D->Enable(false); CP15D->Enable(false); CP16D->Enable(false); CP17D->Enable(false); CP20D->Enable(false); CP21D->Enable(false); CP22D->Enable(false); CP23D->Enable(false); CP24D->Enable(false); CP25D->Enable(false); CP10O->Enable(false); CP11O->Enable(false); CP12O->Enable(false); CP13O->Enable(false); CP14O->Enable(false); CP15O->Enable(false); CP16O->Enable(false); CP17O->Enable(false); CP20O->Enable(false); CP21O->Enable(false); CP22O->Enable(false); CP23O->Enable(false); CP24O->Enable(false); CP25O->Enable(false); book->AddPage(panel, _T("Digital Outputs"), false); panel = new wxPanel(book); (void)new wxStaticText(panel, wxID_ANY, _T("Digital Input Tab: Read 0/1 from any GPIO. Also has the capacity to set PD/PU."),wxPoint(5,5),wxSize(450,15)); Timer_Start = new wxCheckBox (panel, ID_Start_Timer, _T("Start Active Reading:"),wxPoint(10, 30), wxSize(400, 20)); Timer_Start->Enable(false); DI_PORT_SELECT = new wxChoice( panel, ID_DI_INPUT, wxPoint(10,60), wxSize(120,25), 15, choices ); DI_PORT_SELECT->SetSelection(14); port_as_input = new wxCheckBox (panel,ID_DI_CHECK, _T("Define Port as Input"),wxPoint(150, 65), wxSize(150, 20)); port_pullup_enable = new wxCheckBox (panel,ID_DI_CHECK, _T("Enable Internal Pull-Up"),wxPoint(300, 65), wxSize(150, 20)); (void)new wxStaticText(panel, wxID_ANY, _T("Read Status of Port Selected:"),wxPoint(10,100),wxSize(180,15)); portS = new wxTextCtrl(panel, wxID_ANY, _T("null"), wxPoint(200, 95),wxSize(50, 25)); (void)new wxStaticText(panel, wxID_ANY, _T("Port 1 Read Status:"),wxPoint(10,160),wxSize(120,15)); port1DI = new wxTextCtrl(panel, wxID_ANY, _T("null"), wxPoint(140, 155),wxSize(100, 25)); (void)new wxStaticText(panel, wxID_ANY, _T("Port 2 Read Status:"),wxPoint(260,160),wxSize(120,15)); port2DI = new wxTextCtrl(panel, wxID_ANY, _T("null"), wxPoint(390, 155),wxSize(100, 25)); port_selected_text = new wxStaticText(panel, wxID_ANY, _T(""),wxPoint(10, 500), wxSize(250, 20)); DI_PORT_SELECT->Enable(false); port_as_input->Enable(false); port_pullup_enable->Enable(false); portS->Enable(false); port1DI->Enable(false); port2DI->Enable(false); port_selected_text->Enable(false); book->AddPage(panel, _T("Digital Inputs"), false); panel = new wxPanel(book); book->AddPage(panel, _T("Analog Inputs"), false); panel = new wxPanel(book); unsigned int offset = 20; (void)new wxStaticText(panel, wxID_ANY, _T("SPI Master Tab: Hardware SPI ports are defined as follows: P1.5 -> SCLK, P1.6 --> MISO, P1.7 --> MOSI\n "),wxPoint(5,5),wxSize(550,15)); (void)new wxStaticText(panel, wxID_ANY, _T("Select Chip Select"),wxPoint(10,30),wxSize(120,15)); (void)new wxStaticText(panel, wxID_ANY, _T("Number Of Bytes To Send"),wxPoint(150,30),wxSize(150,15)); (void)new wxStaticText(panel, wxID_ANY, _T("Select Baud Rate"),wxPoint(310,30),wxSize(120,15)); select_chip_select = new wxChoice( panel,ID_chip, wxPoint(10,30+offset), wxSize(120,25), 10, chipselect ); select_chip_select->SetSelection(9); select_bytes = new wxChoice( panel, ID_select, wxPoint(150,30+offset), wxSize(140,25), 9, bytes_to_send ); select_bytes->SetSelection(8); select_baud = new wxChoice( panel, wxID_ANY, wxPoint(310,30+offset), wxSize(120,25), 6, baud_select); select_baud->SetSelection(5); send_Packet = new wxButton( panel,ID_send_Packet,_T("Transmit Data Packet"), wxPoint(360,130+offset), wxSize(160,40) ); (void)new wxStaticText(panel, wxID_ANY, _T("Send Buffer In Hex: \nMSB"),wxPoint(10,60+offset),wxSize(120,30)); (void)new wxStaticText(panel, wxID_ANY, _T("LSB"),wxPoint(290,60+offset+15),wxSize(50,15)); (void)new wxStaticText(panel, wxID_ANY, _T("7"),wxPoint(10,60+offset+30),wxSize(50,15)); (void)new wxStaticText(panel, wxID_ANY, _T("6"),wxPoint(50,60+offset+30),wxSize(50,15)); (void)new wxStaticText(panel, wxID_ANY, _T("5"),wxPoint(90,60+offset+30),wxSize(50,15)); (void)new wxStaticText(panel, wxID_ANY, _T("4"),wxPoint(130,60+offset+30),wxSize(50,15)); (void)new wxStaticText(panel, wxID_ANY, _T("3"),wxPoint(170,60+offset+30),wxSize(50,15)); (void)new wxStaticText(panel, wxID_ANY, _T("2"),wxPoint(210,60+offset+30),wxSize(50,15)); (void)new wxStaticText(panel, wxID_ANY, _T("1"),wxPoint(250,60+offset+30),wxSize(50,15)); (void)new wxStaticText(panel, wxID_ANY, _T("0"),wxPoint(290,60+offset+30),wxSize(50,15)); send7 = new wxTextCtrl(panel, wxID_ANY, _T("00"), wxPoint(10, 110+offset),wxSize(30, 25)); send6 = new wxTextCtrl(panel, wxID_ANY, _T("00"), wxPoint(50, 110+offset),wxSize(30, 25)); send5 = new wxTextCtrl(panel, wxID_ANY, _T("00"), wxPoint(90, 110+offset),wxSize(30, 25)); send4 = new wxTextCtrl(panel, wxID_ANY, _T("00"), wxPoint(130, 110+offset),wxSize(30, 25)); send3 = new wxTextCtrl(panel, wxID_ANY, _T("00"), wxPoint(170, 110+offset),wxSize(30, 25)); send2 = new wxTextCtrl(panel, wxID_ANY, _T("00"), wxPoint(210, 110+offset),wxSize(30, 25)); send1 = new wxTextCtrl(panel, wxID_ANY, _T("00"), wxPoint(250, 110+offset),wxSize(30, 25)); send0 = new wxTextCtrl(panel, wxID_ANY, _T("00"), wxPoint(290, 110+offset),wxSize(30, 25)); (void)new wxStaticText(panel, wxID_ANY, _T("Recieved Buffer In Hex: \nMSB"),wxPoint(10,140+offset),wxSize(200,35)); recv7 = new wxTextCtrl(panel, wxID_ANY, _T("00"), wxPoint(10, 180+offset),wxSize(30, 25)); recv6 = new wxTextCtrl(panel, wxID_ANY, _T("00"), wxPoint(50, 180+offset),wxSize(30, 25)); recv5 = new wxTextCtrl(panel, wxID_ANY, _T("00"), wxPoint(90, 180+offset),wxSize(30, 25)); recv4 = new wxTextCtrl(panel, wxID_ANY, _T("00"), wxPoint(130, 180+offset),wxSize(30, 25)); recv3 = new wxTextCtrl(panel, wxID_ANY, _T("00"), wxPoint(170, 180+offset),wxSize(30, 25)); recv2 = new wxTextCtrl(panel, wxID_ANY, _T("00"), wxPoint(210, 180+offset),wxSize(30, 25)); recv1 = new wxTextCtrl(panel, wxID_ANY, _T("00"), wxPoint(250, 180+offset),wxSize(30, 25)); recv0 = new wxTextCtrl(panel, wxID_ANY, _T("00"), wxPoint(290, 180+offset),wxSize(30, 25)); send7->Enable(false); send6->Enable(false); send5->Enable(false); send4->Enable(false); send3->Enable(false); send2->Enable(false); send1->Enable(false); recv7->Enable(false); recv6->Enable(false); recv5->Enable(false); recv4->Enable(false); recv3->Enable(false); recv2->Enable(false); recv1->Enable(false); select_chip_select->Enable(false); select_bytes->Enable(false); select_baud->Enable(false); send_Packet->Enable(false); status_text_spi = new wxStaticText(panel, wxID_ANY, _T("Recieved RS232 Data:"),wxPoint(400, 210+500), wxSize(250, 20)); book->AddPage(panel, _T("SPI Master COM"), false); panel = new wxPanel(book); book->AddPage(panel, _T("Other"), false); } // end of gui void MyFrame::On_chip(wxCommandEvent& WXUNUSED(event)) { unsigned int chipselect_p = select_chip_select->GetSelection(); unsigned int p1dir = port1_dir_global; unsigned int p1out = port1_out_global; unsigned int p2dir = port2_dir_global; unsigned int p2out = port2_out_global; switch(chipselect_p) { case 0: chipselect_p = 0x0; p1dir |= (1< P1DIR(p1dir,false); port1_dir_global =p1dir; p1out |= (1< P1OUT(p1out,false); port1_out_global =p1out; break; case 1: chipselect_p = 0x3; p1dir |= (1< P1DIR(p1dir,false); port1_dir_global =p1dir; p1out |= (1< P1OUT(p1out,false); port1_out_global =p1out; break; case 2: chipselect_p = 0x4; p1dir |= (1< P1DIR(p1dir,false); port1_dir_global =p1dir; p1out |= (1< P1OUT(p1out,false); port1_out_global =p1out; break; case 3: chipselect_p = (0x0); p2dir |= (1< P2DIR(p2dir,false); port2_dir_global =p2dir; p2out |= (1< P2OUT(p2out,false); port2_out_global =p2out; break; case 4: chipselect_p = (0x1); p2dir |= (1< P2DIR(p2dir,false); port2_dir_global =p2dir; p2out |= (1< P2OUT(p2out,false); port2_out_global =p2out; break; case 5: chipselect_p = (0x2); p2dir |= (1< P2DIR(p2dir,false); port2_dir_global =p2dir; p2out |= (1< P2OUT(p2out,false); port2_out_global =p2out; break; case 6: chipselect_p = (0x3); p2dir |= (1< P2DIR(p2dir,false); port2_dir_global =p2dir; p2out |= (1< P2OUT(p2out,false); port2_out_global =p2out; break; case 7: chipselect_p = (0x4); p2dir |= (1< P2DIR(p2dir,false); port2_dir_global =p2dir; p2out |= (1< P2OUT(p2out,false); port2_out_global =p2out; break; case 8: chipselect_p = (0x5); p2dir |= (1< P2DIR(p2dir,false); port2_dir_global =p2dir; p2out |= (1< P2OUT(p2out,false); port2_out_global =p2out; break; } } void MyFrame::On_select(wxCommandEvent& WXUNUSED(event)) { int select_byte_num =select_bytes->GetSelection(); switch(select_byte_num) { case 0: send7->Enable(false), send6->Enable(false),send5->Enable(false),send4->Enable(false),send3->Enable(false),send2->Enable(false),send1->Enable(false); recv7->Enable(false);recv6->Enable(false);recv5->Enable(false);recv4->Enable(false);recv3->Enable(false);recv2->Enable(false);recv1->Enable(false); break; case 1: send7->Enable(false), send6->Enable(false),send5->Enable(false),send4->Enable(false),send3->Enable(false),send2->Enable(false),send1->Enable(true); recv7->Enable(false);recv6->Enable(false);recv5->Enable(false);recv4->Enable(false);recv3->Enable(false);recv2->Enable(false);recv1->Enable(true); break; case 2: send7->Enable(false), send6->Enable(false),send5->Enable(false),send4->Enable(false),send3->Enable(false),send2->Enable(true),send1->Enable(true); recv7->Enable(false);recv6->Enable(false);recv5->Enable(false);recv4->Enable(false);recv3->Enable(false);recv2->Enable(true);recv1->Enable(true); break; case 3: send7->Enable(false), send6->Enable(false),send5->Enable(false),send4->Enable(false),send3->Enable(true),send2->Enable(true),send1->Enable(true); recv7->Enable(false);recv6->Enable(false);recv5->Enable(false);recv4->Enable(false);recv3->Enable(true);recv2->Enable(true);recv1->Enable(true); break; case 4: send7->Enable(false), send6->Enable(false),send5->Enable(false),send4->Enable(true),send3->Enable(true),send2->Enable(true),send1->Enable(true); recv7->Enable(false);recv6->Enable(false);recv5->Enable(false);recv4->Enable(true);recv3->Enable(true);recv2->Enable(true);recv1->Enable(true); break; case 5: send7->Enable(false), send6->Enable(false),send5->Enable(true),send4->Enable(true),send3->Enable(true),send2->Enable(true),send1->Enable(true); recv7->Enable(false);recv6->Enable(false);recv5->Enable(true);recv4->Enable(true);recv3->Enable(true);recv2->Enable(true);recv1->Enable(true); break; case 6: send7->Enable(false), send6->Enable(true),send5->Enable(true),send4->Enable(true),send3->Enable(true),send2->Enable(true),send1->Enable(true); recv7->Enable(false);recv6->Enable(true);recv5->Enable(true);recv4->Enable(true);recv3->Enable(true);recv2->Enable(true);recv1->Enable(true); break; case 7: send7->Enable(true), send6->Enable(true),send5->Enable(true),send4->Enable(true),send3->Enable(true),send2->Enable(true),send1->Enable(true); recv7->Enable(true);recv6->Enable(true);recv5->Enable(true);recv4->Enable(true);recv3->Enable(true);recv2->Enable(true);recv1->Enable(true); break; } } //////////ONCLOSE////////// void MyFrame::On_send_Packet(wxCommandEvent& WXUNUSED(event)) { wxString stringey; unsigned int send_bytes[10]; unsigned int recv_bytes[10]; unsigned int *send_bytes_ptr; unsigned int spi_command = 0xE; unsigned int crystal = 0x8; unsigned int chipselect = 0x16; unsigned int chipselect_p = select_chip_select->GetSelection(); unsigned int baudrate = select_baud->GetSelection(); unsigned int send_spi = 0x32; unsigned int data_length=select_bytes->GetSelection(); unsigned int i=0; send_bytes_ptr=send_bytes; switch(chipselect_p) { case 0: chipselect_p = 0x0; break; case 1: chipselect_p = 0x3; break; case 2: chipselect_p = 0x4; break; case 3: chipselect_p = (0x0 + 0x8); break; case 4: chipselect_p = (0x1 + 0x8); break; case 5: chipselect_p = (0x2 + 0x8); break; case 6: chipselect_p = (0x3 + 0x8); break; case 7: chipselect_p = (0x4 + 0x8); break; case 8: chipselect_p = (0x5 + 0x8); break; } stringey=send0->GetValue(); send_bytes[0] = Byte_To_HEX(stringey.mb_str()); stringey=send1->GetValue(); send_bytes[1] = Byte_To_HEX(stringey.mb_str()); stringey=send2->GetValue(); send_bytes[2] = Byte_To_HEX(stringey.mb_str()); stringey=send3->GetValue(); send_bytes[3] = Byte_To_HEX(stringey.mb_str()); stringey=send4->GetValue(); send_bytes[4] = Byte_To_HEX(stringey.mb_str()); stringey=send5->GetValue(); send_bytes[5] = Byte_To_HEX(stringey.mb_str()); stringey=send6->GetValue(); send_bytes[6] = Byte_To_HEX(stringey.mb_str()); stringey=send7->GetValue(); send_bytes[7] = Byte_To_HEX(stringey.mb_str()); i=0x0; if(data_length==8) { data_length=0; } wxMilliSleep(1); fflush(stdout); wxMilliSleep(1); CloseSerial(); wxMilliSleep(1); OpenSerial(comportnum, 9600); wxMilliSleep(1); while((data_length+1)>i) { wxMilliSleep(8); x = WriteSerial(&spi_command, 1); // Send Command for SPI function wxMilliSleep(8); x = WriteSerial(&i, 1); //data1 -> case0; wxMilliSleep(8); x = WriteSerial(&send_bytes[data_length - i], 1); //data2 -> 0 data; i++; } wxMilliSleep(8); x = WriteSerial(&spi_command, 1); // Send Command for SPI function wxMilliSleep(8); x = WriteSerial(&crystal, 1);//data 1 -> case0x8; wxMilliSleep(8); crystal = 0x3; x = WriteSerial(&baudrate, 1);//case0; wxMilliSleep(8); x = WriteSerial(&spi_command, 1); // Send Command for SPI function wxMilliSleep(8); x = WriteSerial(&chipselect, 1); //data 1 -> case0x8; wxMilliSleep(8); crystal = 0x3; x = WriteSerial(&chipselect_p, 1); //case0; wxMilliSleep(8); x = WriteSerial(&spi_command, 1); // Send Command for SPI function wxMilliSleep(8); x = WriteSerial(&send_spi, 1); //data 1 -> case0x8; wxMilliSleep(8); crystal = 0x3; x = WriteSerial(&crystal, 1); //case0; buf[0]=0;buf[1]=0;buf[2]=0;buf[3]=0;buf[4]=0; wxMilliSleep(1); n = ReadSerial(tbuf, sizeof(tbuf)); recv0->SetLabel(wxString::Format(wxT("%x"), tbuf[data_length])); if((data_length -1)>=0) recv1->SetLabel(wxString::Format(wxT("%x"), tbuf[data_length -1])); if((data_length -2)>=0) recv2->SetLabel(wxString::Format(wxT("%x"), tbuf[data_length-2])); if((data_length -3)>=0) recv3->SetLabel(wxString::Format(wxT("%x"), tbuf[data_length-3])); if((data_length -4)>=0) recv4->SetLabel(wxString::Format(wxT("%x"), tbuf[data_length-4])); if((data_length -5)>=0) recv5->SetLabel(wxString::Format(wxT("%x"), tbuf[data_length-5])); if((data_length -6)>=0) recv6->SetLabel(wxString::Format(wxT("%x"), tbuf[data_length-6])); if((data_length -7)>=0) recv7->SetLabel(wxString::Format(wxT("%x"), tbuf[data_length-7])); status_text_spi->SetLabel(wxString::Format(wxT("%x"), tbuf[1])); } void MyFrame::OnClose(wxCloseEvent& WXUNUSED(event)) { DI_TIMER->Stop(); wxMilliSleep(10); fflush(stdout); CloseSerial(); Destroy(); } ///ON PAGE CHANG EVENTS/////////// void MyFrame::OnPageChanged(wxBookCtrlEvent& event ) { int selOld = event.GetOldSelection(); int cursel = event.GetSelection(); if( cursel==1) { if((port1_dir_global & (1<<0))==(1<<0)) CP10D->SetValue(true); else CP10D->SetValue(false); if((port1_dir_global & (1<<3))==(1<<3)) CP13D->SetValue(true); else CP13D->SetValue(false); if((port1_dir_global & (1<<4))==(1<<4)) CP14D->SetValue(true); else CP14D->SetValue(false); if((port1_dir_global & (1<<5))==(1<<5)) CP15D->SetValue(true); else CP15D->SetValue(false); if((port1_dir_global & (1<<6))==(1<<6)) CP16D->SetValue(true); else CP16D->SetValue(false); if((port1_dir_global & (1<<7))==(1<<7)) CP17D->SetValue(true); else CP17D->SetValue(false); if((port2_dir_global & (1<<0))==(1<<0)) CP20D->SetValue(true); else CP20D->SetValue(false); if((port2_dir_global & (1<<1))==(1<<1)) CP21D->SetValue(true); else CP21D->SetValue(false); if((port2_dir_global & (1<<2))==(1<<2)) CP22D->SetValue(true); else CP22D->SetValue(false); if((port2_dir_global & (1<<3))==(1<<3)) CP23D->SetValue(true); else CP23D->SetValue(false); if((port2_dir_global & (1<<4))==(1<<4)) CP24D->SetValue(true); else CP24D->SetValue(false); if((port2_dir_global & (1<<5))==(1<<5)) CP25D->SetValue(true); else CP25D->SetValue(false); if((port1_out_global & (1<<0))==(1<<0)) CP10O->SetValue(true); else CP10O->SetValue(false); if((port1_out_global & (1<<3))==(1<<3)) CP13O->SetValue(true); else CP13O->SetValue(false); if((port1_out_global & (1<<4))==(1<<4)) CP14O->SetValue(true); else CP14O->SetValue(false); if((port1_out_global & (1<<5))==(1<<5)) CP15O->SetValue(true); else CP15O->SetValue(false); if((port1_out_global & (1<<6))==(1<<6)) CP16O->SetValue(true); else CP16O->SetValue(false); if((port1_out_global & (1<<7))==(1<<7)) CP17O->SetValue(true); else CP17O->SetValue(false); if((port2_out_global & (1<<0))==(1<<0)) CP20O->SetValue(true); else CP20O->SetValue(false); if((port2_out_global & (1<<1))==(1<<1)) CP21O->SetValue(true); else CP21O->SetValue(false); if((port2_out_global & (1<<2))==(1<<2)) CP22O->SetValue(true); else CP22O->SetValue(false); if((port2_out_global & (1<<3))==(1<<3)) CP23O->SetValue(true); else CP23O->SetValue(false); if((port2_out_global & (1<<4))==(1<<4)) CP24O->SetValue(true); else CP24O->SetValue(false); if((port2_out_global & (1<<5))==(1<<5)) CP25O->SetValue(true); else CP25O->SetValue(false); } if ( selOld == 2 ) { if((Timer_Start->GetValue()) ==1 ) { DI_TIMER->Stop(); portS->Enable(false); port1DI->Enable(false); port2DI->Enable(false); Timer_Start->SetValue (false); wxMessageBox( _("Stoped Timer"), _("Comm Port"), wxOK | wxICON_INFORMATION, this ); } } } //////////////CURRENTFUNCITON//////////////////////////////// void MyFrame::DI_INPUT(wxCommandEvent& WXUNUSED(event)) { unsigned int test1 =DI_PORT_SELECT->GetSelection(); unsigned int shift1 = 0; if (test1<=7) { shift1= (1< if((port1_dir_global & shift1)==shift1) { port_as_input->SetValue (false); } else { port_as_input->SetValue (true); } if((port1_ren_global & shift1)==shift1) { port_pullup_enable->SetValue (true); } else { port_pullup_enable->SetValue (false); } } if (test1>=8) { shift1= (1<<(test1 - 8)); } port_selected_text->SetLabel(wxString::Format(wxT("%d"), test1)); } ////// void MyFrame::On_DI_Check(wxCommandEvent& WXUNUSED(event)) { unsigned int p1ren=port1_ren_global; unsigned int p1dir= port1_dir_global; unsigned int p1out=port1_out_global; int check_input = port_as_input->GetValue(); int check_pullup =port_pullup_enable->GetValue(); int test1 =DI_PORT_SELECT->GetSelection(); if(test1<=7) { if(check_input ==1) { p1dir &=~(1< if(port1_dir_global != p1dir ) { P1DIR(~p1dir,true); port_selected_text->SetLabel(wxString::Format(wxT("%d"), p1dir)); port1_dir_global =p1dir; } } if(check_pullup ==1) { p1ren |=(1< p1out |=(1< if((p1ren !=port1_ren_global)|(p1out !=port1_out_global)) { P1REN(p1ren,false); P1OUT(p1ren,false); port1_ren_global= p1ren; port1_out_global=p1out; } } if(check_pullup ==0) { p1ren &=~(1< p1out &=~(1< if(p1ren != port1_ren_global) { P1REN(~p1ren,true); P1OUT(~p1out,true); port1_ren_global = p1ren; port1_out_global =p1out; } } } } //////TimerOutput Binary Function//////// void MyFrame::OnDITimer(wxTimerEvent& WXUNUSED(event)) { int databit0 = 0; int databit1 = 0; int c=0; char txtbuf[10]; char databit0b[14]; char databit1b[14]; char *data0bptr; char *data1bptr; char *txtbuffptr; int selected_p =0; selected_p =DI_PORT_SELECT->GetSelection(); PXIN(); n = ReadSerial(buf, sizeof(buf)); databit0 = (char)buf[0]; databit1 = (char)buf[1]; while(c<8) { if((databit0 & (1<<(7-c)))==(1<<(7-c))) { databit0b[c] ='1'; } else { databit0b[c] ='0'; } c++; } databit0b[c]=0; c=0; data0bptr = databit0b; while(c<8) { if((databit1 & (1<<(7-c)))==(1<<(7-c))) { databit1b[c] = '1'; } else { databit1b[c] = '0'; } c++; } databit1b[c]=0; data1bptr = databit1b; port1DI->SetLabel(wxString::Format(wxT("%s"),data0bptr)); port2DI->SetLabel(wxString::Format(wxT("%s"),data1bptr)); if (selected_p<=7) { sprintf(txtbuf,"%c",databit0b[(7-selected_p)]); txtbuffptr=txtbuf; portS->SetLabel(wxString::Format(wxT("%s"), txtbuffptr)); } } void MyFrame::onstartTimer(wxCommandEvent & WXUNUSED(event)) { if((Timer_Start->GetValue()) ==1 ) { DI_TIMER->Start(100); portS->Enable(true); port1DI->Enable(true); port2DI->Enable(true); } if((Timer_Start->GetValue()) ==0 ) { DI_TIMER->Stop(); portS->Enable(false); port1DI->Enable(false); port2DI->Enable(false); } } void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) { DI_TIMER->Stop(); wxMilliSleep(10); fflush(stdout); CloseSerial(); Close(true); } void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) { wxString msg; msg.Printf(_T("A simple GUI created by Nathan Zimmerman for hardware/software development with the msp430g2553. For source, visit https://github.com/NateZimmer/MSP430-Eval-Tool ")); wxMessageBox(msg, _T("About My Program"), wxOK | wxICON_INFORMATION, this); } void MyFrame::OnButton1(wxCommandEvent& WXUNUSED(event)) // Green LED { toggle_G =!toggle_G; comportnum =comport_txt->GetValue(); P1DIR((1<<6),false); P1OUT((1<<6),toggle_G); n = ReadSerial(buf, sizeof(buf)); recieved_D ->SetValue(wxString::Format(wxT("%s"), buf)); } void MyFrame::OnButton2(wxCommandEvent& WXUNUSED(event)) { toggle_R = !toggle_R; comportnum =comport_txt->GetValue(); P1DIR(0x1,false); P1OUT((0x1),toggle_R); n = ReadSerial(buf, sizeof(buf)); recieved_D ->SetValue(wxString::Format(wxT("%s"), buf)); } void MyFrame::OnListBoxDoubleClick( wxCommandEvent &event ) { *textLog << "ListBox double click string is: \n"; *textLog << event.GetString(); *textLog << "\n"; } void MyFrame::OnButtonConnect(wxCommandEvent& WXUNUSED(event)) { comportnum =comport_txt->GetValue(); send_c = 0x1; if(connected == true) { fflush(stdout); CloseSerial(); wxMilliSleep(10); } OpenSerial(comportnum, 9600); x = WriteSerial(&send_c, 1); wxMilliSleep(10); send_c = 0x00; x = WriteSerial(&send_c, 1); wxMilliSleep(10); x = WriteSerial(&send_c, 1); wxMilliSleep(1); n = ReadSerial(buf, sizeof(buf)); // if(buf[0] =='C') { connection_status -> SetLabel(wxString::Format(wxT("%s"), "Status: Now Connected")); Red_LED_Button->Enable(true); Green_LED_Button->Enable(true); CP10D->Enable(true); CP11D->Enable(false); CP12D->Enable(false); CP13D->Enable(true); CP14D->Enable(true); CP15D->Enable(true); CP16D->Enable(true); CP17D->Enable(true); CP20D->Enable(true); CP21D->Enable(true); CP22D->Enable(true); CP23D->Enable(true); CP24D->Enable(true); CP25D->Enable(true); CP10O->Enable(true); CP11O->Enable(false); CP12O->Enable(false); CP13O->Enable(true); CP14O->Enable(true); CP15O->Enable(true); CP16O->Enable(true); CP17O->Enable(true); CP20O->Enable(true); CP21O->Enable(true); CP22O->Enable(true); CP23O->Enable(true); CP24O->Enable(true); CP25O->Enable(true); Timer_Start->Enable(true); select_chip_select->Enable(true); select_bytes->Enable(true); select_baud->Enable(true); send_Packet->Enable(true); DI_PORT_SELECT->Enable(true); port_as_input->Enable(true); port_pullup_enable->Enable(true); port_selected_text->Enable(true); //button_toggle_g->Enable(true); } else { recieved_D ->SetValue(wxString::Format(wxT("%s"), buf)); wxMessageBox( _("Error: Failed Connection"), _("Comm Port"), wxOK | wxICON_INFORMATION, this ); fflush(stdout); CloseSerial(); } //m_text_display -> SetLabel(wxString::Format(wxT("%s"), buf)); recieved_D ->SetValue(wxString::Format(wxT("%s"), buf)); //fflush(stdout); //m_text_display -> SetLabel(wxString::Format(wxT("%s"), buf)); //CloseSerial(); connected = true; } void MyFrame::OnChecked(wxCommandEvent& WXUNUSED(event)) { unsigned int port1_out = 0; unsigned int port1_dir = 0; unsigned int port2_out = 0; unsigned int port2_dir = 0; if((CP10O->GetValue()) ==1 ) port1_out |= (1<<0); if((CP11O->GetValue()) ==1 ) port1_out |= (1<<1); if((CP12O->GetValue()) ==1 ) port1_out |= (1<<2); if((CP13O->GetValue()) ==1 ) port1_out |= (1<<3); if((CP14O->GetValue()) ==1 ) port1_out |= (1<<4); if((CP15O->GetValue()) ==1 ) port1_out |= (1<<5); if((CP16O->GetValue()) ==1 ) port1_out |= (1<<6); if((CP17O->GetValue()) ==1 ) port1_out |= (1<<7); if((CP20O->GetValue()) ==1 ) port2_out |= (1<<0); if((CP21O->GetValue()) ==1 ) port2_out |= (1<<1); if((CP22O->GetValue()) ==1 ) port2_out |= (1<<2); if((CP23O->GetValue()) ==1 ) port2_out |= (1<<3); if((CP24O->GetValue()) ==1 ) port2_out |= (1<<4); if((CP25O->GetValue()) ==1 ) port2_out |= (1<<5); //////////End Out Reads///////// if((CP10D->GetValue()) ==1 ) port1_dir |= (1<<0); if((CP11D->GetValue()) ==1 ) port1_dir |= (1<<1); if((CP12D->GetValue()) ==1 ) port1_dir |= (1<<2); if((CP13D->GetValue()) ==1 ) port1_dir |= (1<<3); if((CP14D->GetValue()) ==1 ) port1_dir |= (1<<4); if((CP15D->GetValue()) ==1 ) port1_dir |= (1<<5); if((CP16D->GetValue()) ==1 ) port1_dir |= (1<<6); if((CP17D->GetValue()) ==1 ) port1_dir |= (1<<7); if((CP20D->GetValue()) ==1 ) port2_dir |= (1<<0); if((CP21D->GetValue()) ==1 ) port2_dir |= (1<<1); if((CP22D->GetValue()) ==1 ) port2_dir |= (1<<2); if((CP23D->GetValue()) ==1 ) port2_dir |= (1<<3); if((CP24D->GetValue()) ==1 ) port2_dir |= (1<<4); if((CP25D->GetValue()) ==1 ) port2_dir |= (1<<5); /////End DIR Reads///// if(port1_dir_global != port1_dir) { P1DIR(port1_dir,false); // Set 1s P1DIR(~port1_dir,true); // Set 0s port1_dir_global = port1_dir; } if(port2_dir_global != port2_dir) { P2DIR(port2_dir,false); // Set 1s P2DIR(~port2_dir,true); // Set 0s port2_dir_global = port2_dir; } if(port1_out_global != port1_out) { P1OUT(port1_out,false); //Set 1s P1OUT(~port1_out,true); //Set 0s port1_out_global =port1_out; } if(port2_out_global != port2_out) { P2OUT(port2_out,false); //Set 1s P2OUT(~port2_out,true); //Set 0s port2_out_global = port2_out; } } void P1DIR(unsigned int port, bool set_zero) { int pstatus = 0; unsigned int null = 0x2; wxMilliSleep(5); x = WriteSerial(&null, 1); /*if( pstatus == 0 ) { fflush(stdout); CloseSerial(); wxMessageBox( _("Error: Could not write"), _("Comm Port"),wxOK | wxICON_INFORMATION ); }*/ wxMilliSleep(5); if (set_zero ==true) { null = 0x1; x = WriteSerial(&null, 1); } else { null = 0x00; x = WriteSerial(&null, 1); } wxMilliSleep(5); x = WriteSerial(&port, 1); wxMilliSleep(5); } void P1OUT(unsigned int port, bool set_zero) { unsigned int null = 0x3; wxMilliSleep(4); x = WriteSerial(&null, 1); wxMilliSleep(10); if (set_zero ==true) { null = 0x1; x = WriteSerial(&null, 1); } else { null = 0x00; x = WriteSerial(&null, 1); } wxMilliSleep(10); x = WriteSerial(&port, 1); wxMilliSleep(10); } void P1REN(unsigned int port, bool set_zero) { unsigned int null = 0x4; wxMilliSleep(4); x = WriteSerial(&null, 1); wxMilliSleep(10); if (set_zero ==true) { null = 0x1; x = WriteSerial(&null, 1); } else { null = 0x00; x = WriteSerial(&null, 1); } wxMilliSleep(10); x = WriteSerial(&port, 1); wxMilliSleep(10); } void P1SEL(unsigned int port, bool set_zero) { unsigned int null = 0x5; wxMilliSleep(4); x = WriteSerial(&null, 1); wxMilliSleep(10); if (set_zero ==true) { null = 0x1; x = WriteSerial(&null, 1); } else { null = 0x00; x = WriteSerial(&null, 1); } wxMilliSleep(10); x = WriteSerial(&port, 1); wxMilliSleep(10); } void P1SEL2(unsigned int port, bool set_zero) { unsigned int null = 0x6; wxMilliSleep(4); x = WriteSerial(&null, 1); wxMilliSleep(10); if (set_zero ==true) { null = 0x1; x = WriteSerial(&null, 1); } else { null = 0x00; x = WriteSerial(&null, 1); } wxMilliSleep(10); x = WriteSerial(&port, 1); wxMilliSleep(10); } void P2DIR(unsigned int port, bool set_zero) { unsigned int null = 0x7; wxMilliSleep(4); x = WriteSerial(&null, 1); wxMilliSleep(10); if (set_zero ==true) { null = 0x1; x = WriteSerial(&null, 1); } else { null = 0x00; x = WriteSerial(&null, 1); } wxMilliSleep(10); x = WriteSerial(&port, 1); wxMilliSleep(10); } void P2OUT(unsigned int port, bool set_zero) { unsigned int null = 0x8; wxMilliSleep(4); x = WriteSerial(&null, 1); wxMilliSleep(10); if (set_zero ==true) { null = 0x1; x = WriteSerial(&null, 1); } else { null = 0x00; x = WriteSerial(&null, 1); } wxMilliSleep(10); x = WriteSerial(&port, 1); wxMilliSleep(10); } void P2REN(unsigned int port, bool set_zero) { unsigned int null = 0x9; wxMilliSleep(4); x = WriteSerial(&null, 1); wxMilliSleep(10); if (set_zero ==true) { null = 0x1; x = WriteSerial(&null, 1); } else { null = 0x00; x = WriteSerial(&null, 1); } wxMilliSleep(10); x = WriteSerial(&port, 1); wxMilliSleep(10); } void P2SEL(unsigned int port, bool set_zero) { unsigned int null = 0xA; wxMilliSleep(4); x = WriteSerial(&null, 1); wxMilliSleep(10); if (set_zero ==true) { null = 0x1; x = WriteSerial(&null, 1); } else { null = 0x00; x = WriteSerial(&null, 1); } wxMilliSleep(10); x = WriteSerial(&port, 1); wxMilliSleep(10); } void P2SEL2(unsigned int port, bool set_zero) { unsigned int null = 0xB; wxMilliSleep(4); x = WriteSerial(&null, 1); wxMilliSleep(10); if (set_zero ==true) { null = 0x1; x = WriteSerial(&null, 1); } else { null = 0x00; x = WriteSerial(&null, 1); } wxMilliSleep(10); x = WriteSerial(&port, 1); wxMilliSleep(10); } void PXIN() { unsigned int null = 0xC; wxMilliSleep(4); x = WriteSerial(&null, 1); wxMilliSleep(10); x = WriteSerial(&null, 1); wxMilliSleep(10); x = WriteSerial(&null, 1); } void digital_output_mode() { if(DO_mode == false) { send_c = 0xFF; //OpenSerial(comportnum, 9600); x = WriteSerial(&send_c, 1); n = ReadSerial(buf, sizeof(buf)); if(buf[0] =='R') { } else { wxMessageBox( _("Error: Failed Connection"), _("Comm Port"), wxOK | wxICON_INFORMATION); } DO_mode = true; send_c = 0; } }
     
    serial.h

    // Serial Stuff for the MSP430 GUI EVAL HANDLE com_port = NULL; bool connected = false; static unsigned OpenSerial(wxString identifier, unsigned int bps); void CloseSerial(); unsigned int WriteSerial(void* data, unsigned int count); unsigned int ReadSerial(void* buf, unsigned int count);
     
    serial.cpp

    // Serial Stuff for the MSP430 GUI EVAL static unsigned OpenSerial(wxString identifier, unsigned int bps) { int pstatus=0; if((com_port = CreateFile("\\\\.\\" +identifier, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL))==0) { fflush(stdout); CloseHandle(com_port); wxMessageBox( _("Error: Could not create"), _("Comm Port"),wxOK | wxICON_INFORMATION ); } DCB dcb; ZeroMemory(&dcb, sizeof(dcb)); dcb.DCBlength = sizeof(dcb); dcb.BaudRate = bps; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.fParity = FALSE; dcb.fDtrControl = DTR_CONTROL_DISABLE; dcb.fRtsControl = RTS_CONTROL_DISABLE; dcb.fBinary = TRUE; pstatus = SetCommState(com_port, &dcb); if( pstatus == 0 ) { fflush(stdout); CloseHandle(com_port); wxMessageBox( _("Error: Could not set comm state"), _("Comm Port"),wxOK | wxICON_INFORMATION ); } COMMTIMEOUTS to; to.ReadIntervalTimeout = 40; to.ReadTotalTimeoutConstant = 40; to.ReadTotalTimeoutMultiplier = 1; to.WriteTotalTimeoutMultiplier = 1; to.WriteTotalTimeoutConstant = 10; pstatus = SetCommTimeouts(com_port, &to); if( pstatus == 0 ) { fflush(stdout); CloseHandle(com_port); wxMessageBox( _("Error: Could not set comm timeout"), _("Comm Port"),wxOK | wxICON_INFORMATION ); } SetCommMask(com_port, 0); if( pstatus == 0 ) { fflush(stdout); CloseHandle(com_port); wxMessageBox( _("Error: Could not set comm mask"), _("Comm Port"),wxOK | wxICON_INFORMATION ); } return 0; } void CloseSerial() { CloseHandle(com_port); } unsigned int WriteSerial(void* data, unsigned int count) { unsigned int out; // Number of Bytes written WriteFile(com_port, data, count, &out, NULL); return out; } unsigned int ReadSerial(void* buf, unsigned int count) { unsigned int in; // Number of Bytes read ReadFile(com_port, buf, count, &in, NULL); return in; }
     
    Unfortunately I am not able to test the code right now, so I can't assure it works, but it should(or at least I hope it does )
  22. Like
    gordon reacted to jim940 in OBD-II (On-Board Diagnostic) project idea   
    I just realized I forgot the "u" in forums. :oops:
     
    Anyways, I know more about the CAN Bus now then any other network protocol, spent a entire semester at my college studying it (first Semester of Project Design) so that when I did my project the next semester (Semester 2 we are supposed to build and make work the project) I was decently well versed in it:
     
    http://www.northerndtool.com/bionx
     
    Its Arduino I know, (don't kill me), but that is what I was asked to work with, so that is what I did. :shh:
     
    One thing that confused me as I learned about it, knowing the OSI model, is that technically the CAN Bus forgets about that style of operation. For example, for layer 1, connector types etc should be specified, instead, the higher OSI layers that are implemented on top of the CAN Bus Specifications (such as OBD-II) specify the connectors themselves, and while the OSI model relies heavily on the addressing of the node you wish to speak to, the CAN Bus system, is designed so that each and every node will get the same packets and will use the Message ID as a means to detect whether or not the data is useful to them.
     
    Say you have a home monitoring system running on the CAN Bus, you have a master home controller, a secondary back up controller, and a dozen temperature probes, a couple thermostats, a humidity sensor, oxygen sensor, a couple of smoke sensors and a dozen door sensors.
     
    You'd assign the smoke sensors, lower message ID's, to give them priority, as the CAN Bus will detect "on the fly" if there is a collision, and the lower the message ID bits, the higher priority it gains and wins out arbitration. As in the case of a fire, you want the data to always reach your main controller. So each message ID will be unique to the sensor itself and not its address, instead its what the smoke sensor will use to broadcast its data.
     

     
    Now, your worried about a B&E, so the next lowest set of ID's will go to your door sensors, followed by your oxygen sensor, humidity sensor, thermostats and temperature probes etc. or your own unique priorities.
     
    Since it doesn't rely on a messaging format such as IP routing in your home, BOTH your main controller and your back up controller will receive every packet from every sensor, however, while your programming the main controller regularly, your back up controller is programmed as a watch dog, so that, you'll have code such as, if (Temperature_probe1 < setpoint) && (main_con !sending_messages) then take over the bus and assume the main controller is "dead". And since all the probes, scattered throughout the house can be "dumb", and not actually know who they are sending the packages to, you can have any combination of back up systems in place that will allow your system to survive any number of failures. So any back up "master" nodes, just need to listen as my above example for the sensors (dumb devices) sending requests and the "master" nodes responses. If the master node is not responding, and the back up takes over, the furnace wouldn't know the difference between a packet from the master node, or from the back up master, it will just do what its told, and the system will not be compromised cause of a single (or multiple) failures.
     
    This is one of the reasons why, one of the neat things that the CAN Bus is being used for, beyond the typical industrial automation and automotive sectors, is aerospace, for both planes and space bound satellites, due to its redundancy which doesn't require human intervention to correct itself when properly implemented.
     
    Jim
  23. Like
    gordon reacted to oPossum in Comprehensive DCO calibration   
    The G series MSP430 have 1 or 4 factory calibrations for the DCO stored in info segment A. This firmware will store 96 DCO calibrations in info segments B, C, and D. After these calibrations have been stored it is possible to set the DCO to any frequency from 125 kHz to 16 MHz (128:1 range) with a simple function call...
     
    set_dco.c

    #include static const unsigned * const InfoSegA = (unsigned *)0x10C0; static const unsigned * const InfoSegD = (unsigned *)0x1000; int set_dco(const unsigned f) // Set DCO to specified frequency in kHz { // unsigned i; // unsigned rsel = 0; // Init rsel/dco unsigned dco = 0x20; // const unsigned *cal = InfoSegD; // Begin at info segment D do { // if(f >= cal[0] && f < cal[1]) { // Frequency in range? i = cal[1] - cal[0]; // Interpolate for MODx dco += ((((f - cal[0]) * 0x20) + (i >> 1)) / i); DCOCTL = dco; // Set the DCO/MOD BCSCTL1 = rsel; // and RSEL return 0; // Return success } // if((dco += 0x20) == 0xC0) // Next DCO/RSEL dco = 0x20, ++rsel, ++cal; // } while(++cal < InfoSegA); // While in info seg D, C, or B return -1; // Return failure }
     
    Make sure that CCS is configured to write only to main memory so the calibration constants are not erased. This is not the default configuration.

     
    The following code writes the DCO calibrations to the info segments. This only has to be done once for a specific chip. A 32 kHz crystal must be installed while this code is running, but is no longer needed once the calibration has been written.
     
    Serial output while running calibration...

    Info Segments - before calibration D 65535,65535,65535,65535,65535,65535,65535,65535, 65535,65535,65535,65535,65535,65535,65535,65535, 65535,65535,65535,65535,65535,65535,65535,65535, 65535,65535,65535,65535,65535,65535,65535,65535, C 65535,65535,65535,65535,65535,65535,65535,65535, 65535,65535,65535,65535,65535,65535,65535,65535, 65535,65535,65535,65535,65535,65535,65535,65535, 65535,65535,65535,65535,65535,65535,65535,65535, B 65535,65535,65535,65535,65535,65535,65535,65535, 65535,65535,65535,65535,65535,65535,65535,65535, 65535,65535,65535,65535,65535,65535,65535,65535, 65535,65535,65535,65535,65535,65535,65535,65535, A 35969,5886,65535,65535,65535,65535,65535,65535, 65535,65535,65535,65535,65535,4112,32786,0, 32209,742,0,32332,437,0,2302,65535, 65535,65535,65535,2049,36757,36504,36234,34506, Calibrating... 99,106,114,123,134,146,122,131, 141,152,165,181,170,182,196,212, 229,251,241,258,278,299,323,354, 338,361,388,418,450,493,484,517, 555,596,642,703,673,718,770,827, 891,973,949,1012,1084,1163,1252,1368, 1348,1437,1538,1649,1776,1937,1924,2048, 2189,2346,2526,2754,2738,2911,3109,3329, 3586,3906,3520,3746,4007,4299,4635,5057, 4731,5032,5374,5761,6213,6770,6427,6824, 7278,7786,8385,9123,9350,9928,10587,11331, 12209,13283,12672,13414,14248,15200,16325,17715, Info Segments - after calibration D 99,106,114,123,134,146,122,131, 141,152,165,181,170,182,196,212, 229,251,241,258,278,299,323,354, 338,361,388,418,450,493,484,517, C 555,596,642,703,673,718,770,827, 891,973,949,1012,1084,1163,1252,1368, 1348,1437,1538,1649,1776,1937,1924,2048, 2189,2346,2526,2754,2738,2911,3109,3329, B 3586,3906,3520,3746,4007,4299,4635,5057, 4731,5032,5374,5761,6213,6770,6427,6824, 7278,7786,8385,9123,9350,9928,10587,11331, 12209,13283,12672,13414,14248,15200,16325,17715, A 35969,5886,65535,65535,65535,65535,65535,65535, 65535,65535,65535,65535,65535,4112,32786,0, 32209,742,0,32332,437,0,2302,65535, 65535,65535,65535,2049,36757,36504,36234,34506, Done
     
    Calibration code...
     
    main.c

    #include void putc(unsigned); // serial_tx.asm void puts(char *); // serial_tx.asm void utoa(unsigned, char *); // utoa.asm static char s[8]; // buffer for printing unsigned int // Address of info segments static unsigned * const InfoSegA = (unsigned *)0x10C0; static unsigned * const InfoSegB = (unsigned *)0x1080; static unsigned * const InfoSegC = (unsigned *)0x1040; static unsigned * const InfoSegD = (unsigned *)0x1000; /* Freq = Count / Time Freq = Count / (100 / 32768) <-- 100 cycles of 32.768 kHz clock Freq (kHz) = Count / ((100 / 32768) * 1000) Freq (kHz) = Count / 3.0517578125 Freq (kHz) = Count * (1 / 3.0517578125) Freq (kHz) = Count * 0.32768 Freq (kHz) ~= (Count * 21475) / 65536 Freq (kHz) ~= (Count * 21475) >> 16 Freq (kHz) ~= ((Count * 21475) + 32768) >> 16 <-- Better rounding */ void cal_block(unsigned *d, unsigned rsel, unsigned dco) { unsigned n = 32; // Do 32 cals beginning at rsel/dco with // dco range of 0x20 to 0xA0 using 0x20 step // - no modulation - 6 values per rsel DCOCTL = 0; // DCOCTL = dco & 0xE0; // Set initial DCOx, MODx == 0 BCSCTL1 = rsel; // Set initial RSELx do { // __delay_cycles(3277); // Wait for DCO to settle for 100 ms TACTL |= TACLR; // Clear TimerA TACTL |= MC_2; // Start counting - TimerA continuous mode __delay_cycles(100 - 5); // 100 cycles (5 overhead from previous and next instructions) TACTL &= ~MC_2; // Stop counting - TimerA stop mode // *d++ = ((21475L * TAR) + 32768) >> 16; // Scale to kHz // if((DCOCTL += 0x20) == 0xE0) { // Increment DCOx, check if limit reached DCOCTL = 0x20; // Reset DCOx ++BCSCTL1; // Next RSELx } // } while(--n); // } void cal_write(const unsigned *c, unsigned *f) { // Write one full info segment - 64 bytes / 32 ints unsigned n; // DCOCTL = 0; // Run DCO at 1 MHz BCSCTL1 = CALBC1_1MHZ; // DCOCTL = CALDCO_1MHZ; // FCTL2 = FWKEY | FSSEL_2 | 3 - 1; // SMCLK / 3 for flash timing generator FCTL3 = FWKEY; // Clear lock bit FCTL1 = FWKEY | ERASE; // Set erase bit *f = 0; // Dummy write to erase segment FCTL1 = FWKEY | WRT; // Set wrt bit for write operation n = 32; do *f++ = *c++; while(--n); // Write flash FCTL1 = FWKEY; // Clear wrt bit FCTL3 = FWKEY | LOCK; // Set lock bit } void show_block(const unsigned *c) { // Show 32 unsigned ints unsigned a, b; // a = 4; // 4 lines do { // b = 8; // 8 columns do { // utoa(*c++, s); // Unsigned to ASCII puts(s); // Print it putc(','); // } while(--; // Next column puts("\r\n"); // Next line } while(--a); // } void show_all_info_segs(void) { puts("D\r\n"); // show_block(InfoSegD); // D puts("C\r\n"); // show_block(InfoSegC); // C puts("B\r\n"); // show_block(InfoSegB); // B puts("A\r\n"); // show_block(InfoSegA); // A puts("\r\n"); // } void main(void) // { // unsigned n; // unsigned cal[32]; // WDTCTL = WDTPW | WDTHOLD; // Disable watchdog reset // TACTL = TASSEL_2; // SMCLK (DCO) // P1DIR = BIT1; // P1OUT = BIT1; // // BCSCTL3 = XCAP_2; // 10 pF n = 0; // do { // - Wait for MSP430 to detect clock is stable IFG1 &= ~OFIFG; // Clear OFIFG while(--n); // Wait a while } while(IFG1 & OFIFG); // Loop until OFIFG remains cleared BCSCTL2 = SELM1 | SELM0; // - Use LFXT1CLK (32 kHz xtal) as clock source // // Show all the info segments before calibration puts("Info Segments - before calibration\r\n"); show_all_info_segs(); // // puts("Calibrating...\r\n"); // Do calibration and write to flash info segments D to B // cal_block(cal, 0, 0x20); // Calibrate cal_write(cal, InfoSegD); // Write show_block(cal); // Show on terminal // cal_block(cal, 5, 0x60); // cal_write(cal, InfoSegC); // show_block(cal); // // cal_block(cal, 10, 0xA0); // cal_write(cal, InfoSegB); // show_block(cal); // // puts("\r\n"); // // Show all the info segments after calibration has been written puts("Info Segments - after calibration\r\n"); show_all_info_segs(); // // puts("Done\r\n"); // // for(;; // }
     
    serial_tx.asm

    .cdecls C, LIST, "msp430g2211.h" .text .def putc, puts ; 32768 Hz / 2400 bps = 13.6533 cycles per bit ~= 41 cycles per 3 bits (14 / 13 / 14) ; Char to tx in R12 putc: or #0x0100, R12 ; Stop bit mov #0x02, R15 ; Serial out bitmask jmp bit_start ; ; bit0: jmp $ + 2 ; jmp $ + 2 ; nop ; rra R12 ; Bit 0/3/6 jc bit0h ; bic.b R15, &P1OUT ; 14/55/96 jmp bit1 ; bit0h: bis.b R15, &P1OUT ; 14/55/96 jmp bit1 ; ; bit1: jmp $ + 2 ; jmp $ + 2 ; rra R12 ; Bit 1/4/7 jc bit1h ; bic.b R15, &P1OUT ; 27/68/109 jmp bit2 ; bit1h: bis.b R15, &P1OUT ; 27/68/109 jmp bit2 ; ; bit2: jmp $ + 2 ; jmp $ + 2 ; nop ; rra R12 ; Bit Start/2/5/Stop jc bit2h ; bit_start: bic.b R15, &P1OUT ; 0/41/82/- jmp bit0 ; bit2h: bis.b R15, &P1OUT ; -/41/82/123 jne bit0 ; ret_ins: ret puts: ; Tx string using putc mov R12, R14 ; String pointer in R12, copy to R14 putsloop: ; mov.b @R14+, R12 ; Get a byte, inc pointer tst.b R12 ; Test if end of string jz ret_ins ; Yes, exit... call #putc ; Call putc jmp putsloop ; ; .end ;
     
    utoa.asm

    .cdecls C, LIST, "msp430g2211.h" .text .def utoa utoa: ; --- Unsigned to ASCII --- ; - Range 0 to 65535 ; - Leading zeros supressed push R10 ; clr R14 ; Clear packed BCD .loop 13 ; Do 13 bits rla R12 ; Get bit 15 to 3 of binary dadd R14, R14 ; Multiply BCD by 2 and add binary bit .endloop ; clr R15 ; Clear digit 1 of packed BCD .loop 3 ; Do 3 bits rla R12 ; Get bit 2 to 0 of binary dadd R14, R14 ; Multiply BCD by 2 and add binary bit dadd R15, R15 ; .endloop ; swpb R14 ; Swap digit order mov R14, R12 ; Copy packed BCD digits and #0x0F0F, R12 ; Mask digits 5 & 3 rra R14 ; Shift digits 4 & 2 to lower nibble rra R14 ; rra R14 ; rra R14 ; and #0x0F0F, R14 ; Mask digits 4 & 2 mov #('0' << 8) | '0', R10 ; Make ASCII add R10, R12 ; add R10, R14 ; add R10, R15 ; cmp.b R10, R15 ; Is first digit a 0? jne dig5 ; No... cmp.b R10, R14 ; Is second digit a 0? jne dig4 ; No, only the first... cmp.b R10, R12 ; Is third digit a 0? jne dig3 ; No, only the first two... cmp R10, R14 ; Is fourth digit a 0? (second is zero) jne dig2 ; No, only the first three... dig1: ; First four digits are all 0 swpb R12 ; Fifth digit to string mov.b R12, 0(R13) ; inc R13 ; clr.b 0(R13) ; NULL terminate string pop R10 ; ret ; Return ; dig5: ; mov.b R15, 0(R13) ; First digit to string inc R13 ; dig4: ; mov.b R14, 0(R13) ; Second digit to string inc R13 ; dig3: ; mov.b R12, 0(R13) ; Third digit to string inc R13 ; dig2: ; swpb R14 ; Fourth digit to string mov.b R14, 0(R13) ; inc R13 ; jmp dig1 ;
  24. Like
    gordon reacted to fj604 in Launchpad + AS1106 + 8x8 LED Matrix = fun!   
    The 2211 chip that came with the Launchpad is not useless! Here is what can be done with it:
     


     
    I decided to drive a LED matrix with the AS1106 chip from Austria Microsystems. It is a an equivalent of MAX7219 but can work with 3.3V that Launchpad supplies.
     
    Two buttons on a breadboard move the "catcher", and a single button on the Launchpad changes the game speed. Launchpad LEDs are used to indicate a catch (green) or a miss (red).
     
    A piezo buzzer can be added for (very annoying) sound effects beeps.
     
    I thought the whole thing has a certain 1970's touch to it
     

    #include #include #define DATA_PIN BIT4 // data for AS1106 #define LOAD_PIN BIT5 // load for AS1106 #define CLOCK_PIN BIT7 // clock for AS1106 #define BL_PIN BIT1 // Left button #define BR_PIN BIT2 // Right button #define SPEED_PIN BIT3 // Speed increase button #define GREEN_PIN BIT6 // Green LED on Launchpad (LED2) #define RED_PIN BIT0 // Red LED on Launchpad (LED1) #define BUZZER_PIN BIT7 // Piezo BUZZER = XOUT = P2.7 #define MAX_DELAY 2500 // Slowest speed #define MIN_DELAY 1000 // Fastest speed #define STEP_DELAY 300 // Speed step #define TONE_CATCH 5 // Tone on catch #define TONE_MISS 10 // Tone on miss #define TONE_CHIRP 2 // Chirp tone #define CHIRP_DUR 10 // Chirp duration #define TONE_DUR 300 // Catch / miss tone duration unsigned char bitmap[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; volatile unsigned char t = 3, // catcher x position refresh = 0, // flag to refresh matrix refreshing = 0; // set during refresh volatile unsigned int clk = 0, // clock ticks, 1 tick = 1/10000 sec delay = MAX_DELAY, // step delay tone = 0, // tone frequency, 1 = 5000 Hz, 5 = 1000 Hz sound = 0; // sound duration in ticks void pixel_set(unsigned char x, unsigned char y) { bitmap[x] |= 1 << y; } void pixel_clear(unsigned char x, unsigned char y) { bitmap[x] &= ~ (1 << y); } // Shift out data, MSB first void shiftout(unsigned char data) { unsigned char n; for (n = 0; n < 8; n++) { if (data & BIT7) P1OUT |= DATA_PIN; else P1OUT &= ~DATA_PIN; P1OUT |= CLOCK_PIN; P1OUT &= ~CLOCK_PIN; data <<= 1; } } // Send command to AS1106 void as1106(unsigned char addr, unsigned char data) { P1OUT &= ~LOAD_PIN; shiftout(addr); shiftout(data); P1OUT |= LOAD_PIN; } // show bitmap on the matrix void display(void) { refreshing = 1; // Set flag so that we do not change bitmap during refresh unsigned char c; for (c = 0; c < 8; c++) as1106(c + 1, bitmap[c]); refreshing = 0; // Clear flag } void as1106_init(void) { P1DIR |= (DATA_PIN | LOAD_PIN | CLOCK_PIN); P1OUT |= LOAD_PIN; P1OUT &= ~CLOCK_PIN; as1106(0x0C, 0x00); // shutdown display(); as1106(0x0F, 0x01); // Test on _delay_cycles(400000); as1106(0x0F, 0x00); // Test off _delay_cycles(200000); as1106(0x0E, BIT1); // Reset all control registers _delay_cycles(100); as1106(0x0E, 0); // Normal operation as1106(0x09, 0x00); // No decode as1106(0x0A, 0x0F); // full brightness as1106(0x0B, 0x0F); // display all rows as1106(0x0C, 0x81); // No shutdown } void clock_init(void) { BCSCTL1 = CALBC1_1MHZ; // Set DCO DCOCTL = CALDCO_1MHZ; } void timer_init(void) { TACCR0 = 100; // Generate interrupt 10000 times per second TACTL = TASSEL_2 + MC_1; // SMCLK, upmode TACCTL0 = CCIE; // Capture/Compare Interrupt Enable } void sound_init(void) { P2SEL = 0; // Disable XIN/XOUT P2DIR = BUZZER_PIN; // XOUT pin = P2.7 } void intro_sound(void) { for (tone = 10; tone > 0; tone--) { sound = 500; while(sound) ; } } void button_init(void) { P1DIR &= ~(BL_PIN | BR_PIN | SPEED_PIN); P1OUT |= BL_PIN | BR_PIN ; // Pull up P1REN |= BL_PIN | BR_PIN ; // Enable pull up resistors P1IE |= BL_PIN | BR_PIN | SPEED_PIN; // Interrupt enable P1IES |= BL_PIN | BR_PIN | SPEED_PIN; // Interrupt Edge Select high-to-low P1IFG &= ~ (BL_PIN | BR_PIN | SPEED_PIN); // Clear interrupt flag } void main(void) { unsigned char n, p; // n = dot y, p = catcher x, WDTCTL = WDTPW + WDTHOLD; // Disable watchdog timer (WDT) as1106_init(); button_init(); timer_init(); sound_init(); P1DIR |= RED_PIN | GREEN_PIN; P1OUT &= ~(RED_PIN | GREEN_PIN); pixel_set(t, 7); pixel_set(t+1, 7); _enable_interrupts(); intro_sound(); for (; { p = rand() % 8; // random drop x position for (n = 0; n < 7; n++) // drop { pixel_set(p, n); display(); refresh = 0; clk = 0; tone = TONE_CHIRP; sound = CHIRP_DUR; while (clk < delay) { _low_power_mode_0(); if (refresh) { display(); refresh = 0; } } pixel_clear(p, n); } if ((p == t) || (p == t + 1)) // if caught { P1OUT |= GREEN_PIN; P1OUT &= ~RED_PIN; tone = TONE_CATCH; } else { P1OUT &= ~GREEN_PIN; P1OUT |= RED_PIN; tone = TONE_MISS; } sound = TONE_DUR; } } #pragma vector=PORT1_VECTOR __interrupt void Port_1(void) { if (P1IFG & SPEED_PIN) // speed switch { if ((delay-= STEP_DELAY) < MIN_DELAY) delay = MAX_DELAY; } else if ((P1IFG & BL_PIN) && (t > 0) && !refreshing) // left { pixel_clear(t + 1, 7); pixel_set(--t, 7); refresh = 1; } else if ((P1IFG & BR_PIN) && (t < 6) && !refreshing) // right { pixel_clear(t, 7); pixel_set(++t + 1, 7); refresh = 1; } P1IFG &= ~ (BL_PIN | BR_PIN | SPEED_PIN); // clear interrupt flags for all buttons _low_power_mode_off_on_exit(); } #pragma vector=TIMERA0_VECTOR __interrupt void Timer_A (void) { static unsigned int z; clk++; if (sound) { --sound; if ((z++ % tone) == 0) P2OUT ^= BUZZER_PIN; // vibrate buzzer } _low_power_mode_off_on_exit(); }
  25. Like
    gordon got a reaction from Accoutkic in Error compiling mspdebug under Cygwin   
    Try this: http://pastebin.com/RYjAUT7T
×
×
  • Create New...