Jump to content
43oh

oPossum

Members
  • Content Count

    925
  • Joined

  • Last visited

  • Days Won

    103

Reputation Activity

  1. Like
    oPossum reacted to tripwire in Read a line of input from the Code Composer Studio (CCS) console using an MSP430   
    This turned out to be an interesting one, and you're probably going to kick yourself when you see why fgets wasn't working for you...
     
    Initially my gut feeling was that there was no support for reading from the console window on the target*. Having dug a little further I found that the CIO system does support reading from the target side, so I set up a test program to try it out. It didn't work. I noticed that you'd mentioned setting the heap size, so I set mine. That fixed printf but not fgets.
     
    Stepping into the library code revealed that the problem was with allocating the stream buffer for stdin. I'd set the heap to 512 bytes, and each stream requires 256 bytes buffer space plus 32 bytes of header. The printf call was allocating a buffer for stdout and then the heap had insufficient space to allocate a buffer for stdin. While printf causes the program to exit when it fails to initialise the buffer, fgets and getc just return immediately.
     
    Setting the heap size greater than 576 bytes fixed the issue for me.
     

    * Mainly because I've never seen anyone else even try it - stdio.h is commonly regarded as being a bit "heavyweight" for MSP430. The default stream buffer size is bigger than the ram on the msp430g2553! Most example code I've seen uses the UART backchannel instead, or at least a very cut-down printf implementation with a much smaller buffer.
  2. Like
    oPossum got a reaction from advaneharshal in tone generator on MSP430 g2553   
    /*     *** NOTE: THIS IS LICENSED (C)OPYRIGHTED SOFTWARE - DO NOT REMOVE THE FOLLOWING 20 LINES ***         Copyright (C) 2013  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 <http://www.gnu.org/licenses/>         Revision History     ----------------     001 2013.05.10     Written for doomedeggplant who is to lazy to do his homework     */ #include <msp430.h> #include <stdint.h> static uint32_t gpi(unsigned n){     static const uint32_t nt[]={         0x19F10C37,0x1B7BF1E9,0x1D1E52F3,0x1ED994C9,0x20AF3220,0x22A0BC34,         0x24AFDC18,0x26DE542B,0x292E0191,0x2BA0DDCE,0x2E390075,0x30F8A0F2};     static const unsigned f=116;unsigned o=0;while(n<f)n+=12,++o;return nt[n-f]>>o; }static volatile uint32_t pi=0,pa=0; static volatile int32_t t; static void p(const uint8_t *b,const uint8_t*const e,int s,const uint8_t m){     while(P1IN&BIT3);t=10;while(b!=e){P1OUT&=~m;pa=pi=0;t+=13115L;while(t>0);         P1OUT|=m;pi=gpi(*;t+=32787L;while(t>0);b+=s;}P1OUT&=~m;pa=pi=0; }void main(void){     WDTCTL=WDTPW|WDTHOLD;DCOCTL=0;BCSCTL1=CALBC1_16MHZ;DCOCTL=CALDCO_16MHZ;     P1DIR=~BIT3&~BIT1;P1REN=BIT3;P1OUT=BIT2|BIT3;P1SEL=BIT4|BIT1;     TA0CCR0=(16000000L/(1L<<16))-1;TA0CTL=TASSEL_2|MC_1;     TA0CCTL0|=CCIE;_enable_interrupts();     for(;{static const uint8_t z[]="<=>?@ABCDEF"; p(z,z+sizeof(z)-1,1,BIT6);p(z+sizeof(z)-2,z-1,-1,BIT0);} } #pragma vector=TIMER0_A0_VECTOR __interrupt void timer_a0_isr(void){(pa&(1UL<<31))?(P1OUT|=BIT5):(P1OUT&=~BIT5);pa+=pi;--t;} Extra credit: http://forum.43oh.com/topic/2047-rtttl-ring-tone-text-transfer-language-player/?p=17515
  3. Like
    oPossum got a reaction from GeekDoc in WS2811 LED controller driver   
    To use the high speed protocol just change write_ws2811() to write_ws2811_hs(). That will give you the most precise timing possible and allow use of any pin on port 1. SPI/IIC remains free for other uses.
     
    Here is some code for RTC: http://forum.43oh.com/topic/1957-software-real-time-clock-rtc-two-methods/
     
    The 32 kHz crystal is used just for the RTC - the MSP430 can still run at 16 MHz.
  4. Like
    oPossum reacted to Xuan in Fixing damaged dell power adapter using MSP430G2211   
    This is all about learning OneWire communications. I'm able to make a small "adapter" playing the "man in the middle" hack between dell laptop and its power brick to provide "fake" wattage information. For me I'm using it to "fix" a power adapter which has a damaged identification chip. Of course it can also be used to use non-dell power adapter (on your own risk of damaging the laptop, or even burn your house, who knows...)
     
    All the code and pcb design can be found at https://github.com/HclX/DELL_POWER_SPOOFER.git and my http://hclxing.wordpress.com/2014/02/26/hacking-a-dell-power-adapter-final-not-really/
     
    Some pictures:
      schematic:

     
    pcb layout:

     
    final populated pcb, toner transferred and hand soldered, some of the parts are salvaged from old dvd rom pcb:


     
    dc jack from a broken dell laptop, it took me a fair amount of work to cut the pcb into that shape using my dremel so I can solder the dc jack

     
    connecting with a working power adapter

     
    to prove it's working, i'm faking my working 90W adapter as 65W 


     
    There is still work to do like enabling push button to import data from the connected working adapter, or switching between multiple imported data, making use the led indicator, ...
  5. Like
    oPossum got a reaction from KwaiChang in TV-B-Gone using Launchpad   
    This is a reimplementation of adafruit's TV-B-Gone kit. It has been written from scratch to be more efficient and more precise than the AVR version. Assembly code is used for the critical timing, everything else is in C. Clock is 1 MHz (vs. 8 MHz for AVR).
     
    This code is small enough to fit in a G2231 (2K flash, 128 RAM) that comes with the launchpad. There are only 39 codes due to limited flash capacity. Obviously larger parts like the G2553 could be used to fit all codes and add additional features.
     
    main code (excerpt)

    void send_code(TIRCODE * const ic) { const uint8_t *code_byte; unsigned code_bitmask; static uint8_t idx[100]; // static so it is not on the stack unsigned n, j; uint8_t *p; // Make sure there is room for all indicies if(ic->pair_count > sizeof(idx)) return; // Convert variable bit count to uint8_t n = ic->pair_count; code_byte = ic->bitstream; code_bitmask = 0x80; p = idx; // Iterate indicies while(n--) { *p = 0; j = ic->bits_per_index; // Iterate bits while(j--) { *p <<= 1; if(*code_byte & code_bitmask) *p |= 4; code_bitmask >>= 1; if(!code_bitmask) ++code_byte, code_bitmask = 0x80; } ++p; } if(ic->carrier_period) { TACCR0 = ic->carrier_period; TACCR1 = ic->carrier_period >> 1; tx_ir_carrier(ic->pair_count, idx, ic->durations); } else { tx_ir_pulse(ic->pair_count, idx, ic->durations); } } void main(void) { unsigned n; WDTCTL = WDTPW + WDTHOLD; // Disable watchdog // DCOCTL = 0; // Use 1 MHz calibration BCSCTL1 = CALBC1_1MHZ; // DCOCTL = CALDCO_1MHZ; // // // See chart for I/O assignment P1OUT = 0x0E; // Txd, Rxd, S2 high P1REN = 0x0C; // Rxd / S2 pullup enabled P1DIR = 0xF3; // Rxd / S2 in, all others out P1SEL = 0x50; // Timer A T0.1 / SMCLK TACTL = TASSEL_2 | MC_1; // Clock = SMCLK, Mode = UP // do { // /// todo: Sleep while waiting for S2 press // while(P1IN & 8); // Wait for S2 press // for(n = 0; n < code_count; ++n) { // P1OUT |= 0x01; // LED on delay10us(450 * 100u); // Wait 450 ms P1OUT &= ~0x01; // LED off send_code(CodeList[n]); // Send code } // } while(1); // }
     
    ir transmission code (excerpt)

    tx_ir_carrier ; void tx_ir_carrier(unsigned n, uint8_t *i, TDUR *d) ; R12 Duration pair count ; R13 Pointer to duration indicies ; R14 Pointer to durations ; mov #OUTMOD_7, R10 ; IR Carrier On (reset/set output mode) mov #OUTMOD_5, R11 ; IR Carrier Off (reset output mode) ; ir_tx_loop mov.b @R13, R15 ; Get duration index add R14, R15 ; Add duration pointer mov @R15, R15 ; Get duration ; mov R10, &TACCTL1 ; Turn on IR call #delay ; Wait for on duration ; nop2 ; Precise timing ; mov.b @R13+, R15 ; Get duration index and increment pointer incd R15 ; Adjust for off duration add R14, R15 ; Add duration pointer mov @R15, R15 ; Get duration ; mov R11, &TACCTL1 ; Turn off IR call #delay ; Wait for off duration ; dec R12 ; Decrement pair count jne ir_tx_loop ; Do next duration pair... ; ret ; Return ; ; ; ; - Delay in units of 10 cycles (10 us at 1 MHz) delay cmp #4, R15 ; Compare to minimum jlo dlyret ; Below minimum, return... sub #2, R15 ; Adjust loop count for overhead jmp eloop ; Make the first iteration shorter ; delay10us mov R12, R15 ; C callable ; dloop nop2 ; 7 cycles of nop nop2 ; nop2 ; eloop nop ; dec R15 ; Decrement loop count - 1 cycle jne dloop ; Loop if not zero - 2 cycles ; dlyret ret ;
     
    Complete code attached
    tvbg_lp.zip
  6. Like
    oPossum got a reaction from dangpzanco in tone generator on MSP430 g2553   
    /*     *** NOTE: THIS IS LICENSED (C)OPYRIGHTED SOFTWARE - DO NOT REMOVE THE FOLLOWING 20 LINES ***         Copyright (C) 2013  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 <http://www.gnu.org/licenses/>         Revision History     ----------------     001 2013.05.10     Written for doomedeggplant who is to lazy to do his homework     */ #include <msp430.h> #include <stdint.h> static uint32_t gpi(unsigned n){     static const uint32_t nt[]={         0x19F10C37,0x1B7BF1E9,0x1D1E52F3,0x1ED994C9,0x20AF3220,0x22A0BC34,         0x24AFDC18,0x26DE542B,0x292E0191,0x2BA0DDCE,0x2E390075,0x30F8A0F2};     static const unsigned f=116;unsigned o=0;while(n<f)n+=12,++o;return nt[n-f]>>o; }static volatile uint32_t pi=0,pa=0; static volatile int32_t t; static void p(const uint8_t *b,const uint8_t*const e,int s,const uint8_t m){     while(P1IN&BIT3);t=10;while(b!=e){P1OUT&=~m;pa=pi=0;t+=13115L;while(t>0);         P1OUT|=m;pi=gpi(*;t+=32787L;while(t>0);b+=s;}P1OUT&=~m;pa=pi=0; }void main(void){     WDTCTL=WDTPW|WDTHOLD;DCOCTL=0;BCSCTL1=CALBC1_16MHZ;DCOCTL=CALDCO_16MHZ;     P1DIR=~BIT3&~BIT1;P1REN=BIT3;P1OUT=BIT2|BIT3;P1SEL=BIT4|BIT1;     TA0CCR0=(16000000L/(1L<<16))-1;TA0CTL=TASSEL_2|MC_1;     TA0CCTL0|=CCIE;_enable_interrupts();     for(;{static const uint8_t z[]="<=>?@ABCDEF"; p(z,z+sizeof(z)-1,1,BIT6);p(z+sizeof(z)-2,z-1,-1,BIT0);} } #pragma vector=TIMER0_A0_VECTOR __interrupt void timer_a0_isr(void){(pa&(1UL<<31))?(P1OUT|=BIT5):(P1OUT&=~BIT5);pa+=pi;--t;} Extra credit: http://forum.43oh.com/topic/2047-rtttl-ring-tone-text-transfer-language-player/?p=17515
  7. Like
    oPossum got a reaction from jazz in Software async serial tx/rx without timer   
    Had some requests for this in IRC so here it is. This is an improved version of the serial tx previously posted and new serial rx code. Both tx and rx are blocking and interrupts should be disabled before calling.
     
    C code to show how to use the serial_setup(), putc(), puts(), and getc() functions.
    This will receive a character, increment it and echo it back. So if you type 'A', then 'B' will be echoed.

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

    ; serial.asm .cdecls C, LIST, "msp430g2231.h" .bss in_bit_mask, 2 ; Serial in pin .bss out_bit_mask, 2 ; Serial out pin .bss bit_dur, 2 ; Bit duration in cycles .bss half_dur, 2 ; Half bit duration in cycles ; .text ; .def serial_setup ; void serial_setup(unsigned out_mask, unsigned in_mask, unsigned bit_duration); .def putc ; void putc(unsigned c); .def puts ; void puts(char *s); .def getc ; unsigned getc(void); ; ; serial_setup ; - Setup serial I/O bitmasks and bit duration (32 minimum) mov R12, &out_bit_mask ; Save serial output bitmask mov R13, &in_bit_mask ; Save serial input bitmask bis.b R12, &P1DIR ; Setup output pin bis.b R12, &P1OUT ; bic.b R13, &P1DIR ; Setup input pin or R13, R12 ; bic.b R12, &P1SEL ; Setup peripheral select mov R14, R12 ; sub #16, R14 ; Adjust count for loop overhead rla R14 ; Multiply by 2 because NOP is two bytes mov R14, &bit_dur ; Save bit duration sub #32, R12 ; Adjust count for loop overhead mov R12, &half_dur ; Save half bit duration ret ; Return ; ; - Send a single char putc ; Char to tx in R12 ; R12, R13, R14, R15 trashed mov &out_bit_mask, R15 ; Serial output bitmask mov &bit_dur, R14 ; Bit duration or #0x0300, R12 ; Stop bit(s) jmp bit_low ; Send start bit... ; tx_bit mov R14, R13 ; Get bit duration tx_delay nop ; 4 cycle loop sub #8, R13 ; jc tx_delay ; subc R13, PC ; 0 to 3 cycle delay nop ; 3 nop ; 2 nop ; 1 ; rra R12 ; Get bit to tx, test for zero jc bit_high ; If high... bit_low bic.b R15, &P1OUT ; Send zero bit jmp tx_bit ; Next bit... bit_high bis.b R15, &P1OUT ; Send one bit jnz tx_bit ; If tx data is not zero, then there are more bits to send... ; ret ; Return when all bits sent ; ; ; - Send a NULL terminated string puts ; Tx string using putc push R11 ; mov R12, R11 ; String pointer in R12, copy to R11 putsloop ; mov.b @R11+, R12 ; Get a byte, inc pointer tst.b R12 ; Test if end of string jz putsx ; Yes, exit... call #putc ; Call putc jmp putsloop ; putsx pop R11 ; ret ; ; getc ; - Get a char mov &bit_dur, R14 ; Bit duration mov &in_bit_mask, R13 ; Input bitmask mov #0x01FF, R12 ; 9 bits - 8 data + stop ; rx_start ; Wait for start bit mov.b &P1IN, R15 ; Get serial input and R13, R15 ; Mask and test bit jc rx_start ; Wait for low... ; mov &half_dur, R13 ; Wait for 1/2 bit time ; rx_delay nop ; Bit delay sub #8, R13 ; jc rx_delay ; subc R13, PC ; 0 to 3 cycle delay nop ; 3 nop ; 2 nop ; 1 ; mov.b &P1IN, R15 ; Get serial input and &in_bit_mask, R15 ; rrc R12 ; Shift in a bit ; mov R14, R13 ; Setup bit timer jc rx_delay ; Next bit... ; rla R12 ; Move stop bit to carry swpb R12 ; Move rx byte to lower byte, start bit in msb ret ; Return with rx char and start bit in R12, stop bit in carry ; .end ;
  8. Like
    oPossum got a reaction from Nisarg 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); }
  9. Like
    oPossum reacted to jrychter in 120 LED Ring Clock   
    I'm not sure if it will help in your design, but I've found that you can save some board space by going with milled cutouts for screws instead of holes. Yes, you still need room for the screw top, but less than you'd need if you had the hole in the middle of the board. See the attached picture for an example (the bottom cutout is marginal, parts are placed slightly too close)

  10. Like
    oPossum reacted to xiaodoudou172 in Driving a 7 segment LCD using 2452   
    Hi! I am new to here. Several months ago I got a Launchpad with two chips 2553 & 2452 inside the box. I am really enjoying it except one thing: They have no LCD driver. Considering an external LCD module will bring terrible power consumption, I wonder if I can drive a simple 3 1/2 digits 7 segments LCD with very little power consumption.
     
    After searching the internet I found Maxim's 4 digits decoder ICM7211 might be a choice, but it is hard to access and so expensive that I cannot accept. Another choice is to use BCD to 7 segments decoder, finally I found 4543 BCD to 7 segments decoder for LCD, it can directly drive static LCD (one COM) without extra components. The 4543 functional diagram is shown below:
     

     
    The 3 1/2 digit LCD is one of the most common LCD and very easy to access. I bought one for only one dollar. But the question is 4543 can only drive a 7 segments digit while the LCD has 3 dots, one colon, '1' on the 4th digit and some other segments. MSP430 cannot drive them directly, they need special circuit. My way is to use 4070 or 4030 quad exclusive-or gate to drive them. One of the input of the gate is connected to the back panel and another is controlled by the MSP430. 
     
    The schematic is shown below:
     
     
     
    Note that 4543 and 4070 need square wave to drive the LCD (for static LCD, 60 - 90Hz may work well), PWM will be a great way to produce square wave, I only use CCR0 in TIMER0_A3 to produce a 64Hz, 50%duty square wave. CCR0 is set to 255 (128Hz), and PWM mode 4 (Toggle), so the actual PWM frequency is 64Hz.
     
    I designed a simple LCD clock with three 4543s and one 4070, and use only two XOR gates in 4070 to drive the hour's ten bit and the colon.  The clock is 12 hours mode and the colon will blink every second.
     
    To set the time, first press "MODE" for about 3 seconds, press "SET" to set hours when only hours display on the screen, then press "MODE" again to set minutes, after that, press "MODE" to finish setting. The seconds will be automatically set to zero when quitting time set mode. 
     
    I also designed a small PCB for the project. After fixing some bugs it works well now.
     
    Front:
     
     
    Back:
     
     
    A 22uF capacitor is in parallel connection with the battery, the clock can continuously run about 15 seconds after taking the battery away. A CR2032 coin cell is at 3V and the minimum supply voltage of MSP430G2452  is 1.8V, which meas the total consumption of the project is (3 -1.8)v / 15s x 22u = 1.76uA, a 200mAh CR2032 coin cell may let the clock running for about 13 years, considering the lifetime of a coin cell, it probably may work for about 5 years.
     
    The software is written using CCS, grace makes things so convenient. 
     
    Code for the project can be downloaded here, sorry for the original Eagle file is in my school's PC, I will upload them as soon as I return to school.
    LCD Clock.rar
    Update?I updated the software version to make the main function shorter, and added a full display of every used segments when power on. The new version with Eagle files (SCH only, sorry) can be download here:
    LCD Clock V2.rar
  11. Like
    oPossum reacted to greeeg in 120 LED Ring Clock   
    Hey, It's been along time since I've posted. but I've been keeping busy with uni and working on some cool projects for the last year.
     
    This is something I'd like to share with you guys, it's not finished yet but the hardware is more or less complete. It is an RGB LED ring clock.
     

     
    The clock is comprised of 2 rings of 60 LEDs each. the LEDs are WS2812 parts, which include a built-in driver.
     
    The PCB is one of the interesting parts of this clock. I designed the board in altium as a single 6 LED segment. and then left pads at each end to allow them to be soldered onto another segment.
     

     
    Using seeed's 10pcs PCB program I was able to create the full ring.
     
    Currently I am using a MSP-EXP430FR5739 board to drive it, using some very in-efficient assembly code that requires a 20MHz clock.
     
    I'd like to optimise the code to use an internal SPI module? or timer to bring that clock speed down.
    Hopefully also design a control segment with LEDs on one side that could replace one of the current segments in the ring.
     

     
     
    Edit: I've built up a simple controller based on the G2121. yes, 1kb Flash, 128b of RAM!
     
    I decided to test my asmebly skills and use naken430 the msp430 assembler. Here is my code
    G2121_ledRing.zip
     
    I also added a ring of perspex to help difuse the LEDs
     
    Here is a video of the clock in action.
    http://www.youtube.com/watch?v=tBCvR4BA7pw
     
     
    edit: 06/03/14
    Version 2_02!
    Major differences:
    "double" so you need only 5 pcs to make a full ring, the pieces fit in 5x10cm Uses new 4 pin WS2812b parts
     
    PCBs arrived, been tested and is functional, but has some very small issues.
    Known Errata:
    Doesn't account for very small milling tolerance, means small gaps at joins No silkscreen for LED footprint, only shows orientation Edge connectors a few mm from the edge. Vias connecting to pour have star connections, should be direct connection Thin soldermask trace around OSHW logo is to thin 1 LED under OSHW logo isn't concentric with the rest of the LEDs (<1mm off)  
     
    There is also a special controller board in the mail, this will be tested and documented when it arrives.
     
    edit 2/06/13
    Please see this project for lot of photos and additional information about version 2_02
     
    Version 3!

    Boards have been designed, and I have some prototypes on the way. Designed mainly to upgrade the MSP430 used in the last design to a more capable one.  Boards arrived Some small errata found, pads to small for regulator, JTAG pins in wrong order. New board has been design to fix these issues. There is a tindie page where you can register any interest in buying.
    https://www.tindie.com/products/Greeeg/ledring-clock/
  12. Like
    oPossum got a reaction from SouLSLayeR in A useful dongle for G2553s on the LaunchPad.   
    Switchable jumper block built with 2 x 3 female header.
     
    A piece of #20 solid core wire is used to make a handle to allow easy removal and installation.


  13. Like
    oPossum got a reaction from bluehash in Stellaris Drum Machine   
    This is a quick test of playback of vintage drum machine sounds. In the 80's there where several popular drum machines that used samples of real drums stored in 27xx series EPROMs. They would simply sequentially address the EPROM and the data was sent to a companding DAC (Am6070). Some sounds also had a filter or envelope applied - this code does not do that. These old machines had numerous EPROM chips to store the samples. With modern flash technology it is possible to put a complete sample set right in the microcontroller itself.
     
    Right now this just loops through all the samples in a set. There is no MIDI or any sort of trigger support yet.
     
    Samples are included for:
    Linn LM-1
    Linndrum (LM-2)
    Linn 9000 Drum Computer
    Oberheim DX
    Oberheim DMX
     
     

    StellarisDrums.zip
  14. Like
    oPossum reacted to keithq in MSP430TCH5E HAPTOUCH is available   
    Yes, there's some similarity with the G2553 b/c the design was derived from it.  The exact changes are proprietary, so I'm not allowed to go into detail...  But they relate to the implementation of Immersion's technology into the device to enable the library. 
     
    The net result is that the combination of the TCH5E and MSP430 Haptics Library lets you do haptics without patent infringement.  We licensed Immersion's IP and built our library around it.  Immersion approves of this combination, and an Immersion license for use on a given TCH5E is included with its purchase.  You can't run the library on a different MSP430 derivative -- the library calls won't work. 
     
    The wide variety in haptics effects in the library are pretty cool. There's a lot of room for creativity -- you can chain effects together into complex sequences.  For example, the default ones Immersion provided include "machine gun", "rolling dice", etc., and they feel pretty realistic. 
     
    To help people create their own sequences, we added the HapTouch GUI, so you can tweak sequences real-time without having to re-build the code each time (or need the FET tool).  I'd wanted to even write an export/import feature to make it easy for people to share their sequences online, but we ran out of time.  If there turns out to be a lot of interest, I may still end up doing this and push an update. 
  15. Like
    oPossum got a reaction from larryfraz in Stellaris Drum Machine   
    OK, set a breakpoint in the ISR to determine if the timer setup is working properly.
     
    There may be some difference in the Tiva PWM vs the Stellaris PWM that is the problem.
     
    I don't have a Tiva LP, so can't test it myself.
  16. Like
    oPossum got a reaction from larryfraz in Stellaris Drum Machine   
    This is a quick test of playback of vintage drum machine sounds. In the 80's there where several popular drum machines that used samples of real drums stored in 27xx series EPROMs. They would simply sequentially address the EPROM and the data was sent to a companding DAC (Am6070). Some sounds also had a filter or envelope applied - this code does not do that. These old machines had numerous EPROM chips to store the samples. With modern flash technology it is possible to put a complete sample set right in the microcontroller itself.
     
    Right now this just loops through all the samples in a set. There is no MIDI or any sort of trigger support yet.
     
    Samples are included for:
    Linn LM-1
    Linndrum (LM-2)
    Linn 9000 Drum Computer
    Oberheim DX
    Oberheim DMX
     
     

    StellarisDrums.zip
  17. Like
    oPossum reacted to chicken in TIVA C Launch Pad Fails at below 0 C and above 40 C temperatures   
    Agree on the frustration of getting direct support from large companies, being it TI or others.
     
    Working for a large software company, I know that people are more reactive to reports that already tracked down the exact point of failure as it saves them time. Engineers typically already have their plate full with work for customers with deeper pockets and/or the phone number of the CEO.
     
    That's why I try to dumb things down until it's undeniably clear where the core issue lies. In your case, toggle pins to confirm whether clock variance over temperature is inside or outside spec.
  18. Like
    oPossum reacted to roadrunner84 in RTFM - Read The Fabulous Manual   
    I so agree with you! More than once I have to point people to the innards of Energia to explain why their code is behaving oddly. Apart from the obscured controller, virtually all benefits and virtues gained from the low power design are lost with Energia. (Yes, you can do low power and Energia, but they don't like each other. When doing plain C there is a real synergy between design of code and controller).
    As you may know I'm preparing a tutorial for low power design with the MSP430. I will hint on how to use them with Energia, but switch to plain C very early in the tutorial.
     
    I (as an electronics engineer) found the datasheet, family guide and C API (msp430.h + intrinsics.h + pragma vector)  very clean and easy on the brains. I can understand that this might be different for software engineers that are not accustomed to reading data sheets in the first place. I can see some folks would prefer a document with the data sheet and a distilled version of the family guide packed into a single document, which would certainly have some benefits, but the power of shared properties between members of the same MSP430 family would get lost in translation.
    The family guide describes the interrupt vectors, but the lot of them (all but reset, nmi and wdt) are "device specific"; please read the data sheet. The same story goes for PxSEL and PxSEL2, which are described (in a not so readable fashion) in the data sheet. Having these condensed in a format similar to the family guide would make flipping back and forth between PDFs less necessary.
  19. Like
    oPossum reacted to rockets4kids in RTFM - Read The Fabulous Manual   
    I don't think anyone has questioned the accuracy or veracity of TI's documentation.
     
    I can't speak for others, but I do not use the E2E forums because the software is just so ungodly awful.  I am not a fan of web forums in general, but E2E is just fingers-across-a-chalkboard unpleasant.  I might be inclined to use it if there was good content, but every time I have wound up there as a result of a google search I have never found anything worthwhile.
     
    And again, I still think the main reason more people don't RTFM is simply because they have never actually *found* TFM.
     
    Yes, the family datasheets are 600-odd pages of densely worded text.  There is no doubt that reading them is often difficult.  That is par for the course when working with microcontrollers.
     
    There is indeed a huge gap between TI's introductory material and the datasheets.  I have stated time and time again that if TI wants the Launchpad to be a useful educational tool, they should do a better job of bridging that documentation gap.
     
    Unfortunately, it is now clear that TI has chosen instead to devote it's resources to Energia.  I think this is a terrible decision for a whole host of reasons, but mostly because it obscures how the chips actually work rather than teaching how they do work.  What makes this sadder still is is that the MSP430 is far and away the best architecture to learn using microcontrollers natively. 
     
    And if Energia truly is the future, for better or worse, it is sad that TI would do such a poor job at fostering the community supporting it.
  20. Like
    oPossum got a reaction from link 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); }
  21. Like
    oPossum got a reaction from rostlaur in The Terminal - 43oh OLED Booster Pack   
    MikroElektronica GLCD Font Creator (free)
     
    "GLCD Font Creator is the ultimate solution to create personalized fonts, symbols and icons for Graphic LCD (GLCD). It lets you create fonts for Liquid Crystal Displays (LCD) and Graphic LCD. It provides a very nice and intuitive user interface. GLCD Font Creator lets you create fonts and symbols from scratch, or by importing existing fonts on your system. It lets you modify and adjust them for your needs, apply effects to them, and finally export them as source code for use in your favorite language compiler."
  22. Like
    oPossum reacted to chicken in If you can't 'C' - then this   
    @@roadrunner84 I admire that you had a go at this
     
    I think it helps the discussion to first agree on what terms like complexity, bloat, abstraction mean.
     
    My personal definitions:
    * complexity: what's the amount of knowledge and work required to achieve a given task
    * abstraction layer: means to hide complexity from programmer, can be tools (Energia), languages (Forth), libraries..
    * bloat: price paid in performance and/or effective code size to abstract complexity
     
    From that perspective, Energia and Forth offer an abstraction layer to reduce the complexity of developing on MSP430 (including less complex code) at the price of an overall larger memory footprint (when including Energia core and Forth interpreter) and less powerful tools (e.g. no integrated debugger, no direct access to compiler options and output, cumbersome management of projects spanning many files, ..).
     
    This is not good or bad, it's about horses for courses (and riders!).
     
    So before the next poster starts bashing CCS, please consider that there are many like me, who find it a great and very productive IDE. Yes, even within the limits of the free version - so far I'm more concerned about running out of MSP430's scarce RAM than the 16K limit of the compiler.
  23. Like
    oPossum reacted to rockets4kids in Suggestions/Thoughts on a donation button   
    My suggestion would be to price items from the store more appropriately and use profits from the store to support the site.
     
    I have recently gotten in to R/C, and one of the sites most rapidly growing in popularity is flitetest.com.  While I personally consider their products to be insanely overpriced, they have had such such great response that they have actually had to hire additional employees to fulfill all of their orders.
  24. Like
    oPossum reacted to pabigot in mspgcc right shift question (energia)   
    To slightly clarify roadrunner84's comment:  "char" is neither signed nor unsigned.  It is a type distinct from both "signed char" and "unsigned char", and the compiler must specify that its behavior is equivalent to one or the other.
     
    gcc treats char as equivalent to signed char while IAR and CCS make it equivalent to unsigned char.
     
    Using uint8_t and int8_t is the right choice of data type when operating on specifically 8-bit data (as opposed to character data, where char is correct).  I do use "unsigned char" when I mean "the unsigned form of the smallest integral data type supported by the processor", though, just as I'll use "unsigned int" for "the unsigned form of the native integral data type" in preference to uint16_t when it really isn't the range that I'm concerned about.  Thus I have no problem using unsigned char to hold the value of P1IN when programming an MSP430.
    So many choices.
  25. Like
    oPossum reacted to cubeberg in Small Quadruped   
    Hey guys - haven't been around much lately - but wanted to post my latest WIP.  I'm working on an MSP430-powered (G2553 for now) Quadruped.  It's based on this design from Thingiverse: http://www.thingiverse.com/thing:38159.  I've modified it a bit to work with some metal-gear servos (http://www.ebay.com/itm/161066818608).  
     
    Just using Energia for servo-testing right now, but wanted to post some pics.  I've got the STL files that seem to be working well.  I'll upload them when everything looks good - but if someone is interested in getting started earlier - let me know.
     
    Only pics right now - no video.  I lost a servo - think it was stuck or something when I applied power - *poof* - magic smoke gone.  I'll post some video once I get a replacement (hopefully here on Monday).
     
    Oh - and if you're interested but don't have a 3D printer - let me know - I'd be glad to send off a set of parts.


×
×
  • Create New...