Jump to content
43oh

dacoffey

Members
  • Content Count

    14
  • Joined

  • Last visited

Reputation Activity

  1. Like
    dacoffey reacted to RobG in MIDI Booster Pack   
    Store Links:
    The MIDI BoosterPack
    The MIDI Standalone
    MIDI BoosterPack Kit


    This is a second version of my SoundPad booster pack, but I am calling it MIDI booster pack this time because it is meant to be used as a MIDI experimenter's board.

    What's new?
    MIDI out
    Opto isolator can be SMDIP or SOIC
    Got rid of all expansion headers (the new board is intended to be used with 2553 only.)

    Intended uses? How about this:
    MIDI controller (4 digital/analog inputs accessible via 6 pin header, can connect pots or switches, keep in mind that 1.3 has cap/resistor attached to it on the LP board.)
    MIDI arpeggiator
    MIDI delay/echo
    Mapping MIDI channels/notes
    Just use your imagination


  2. Like
    dacoffey reacted to RobG in Audio Spectrum Analyzer   
    My board and MSGEQ7 chip in action.
     
    Three 5x7 matrix displays (15x7) are connected to my 595 expander board.
    MSGEQ7 does all the hard work here, nothing fancy, no FFT.
     


  3. Like
    dacoffey reacted to ozymandias in BETA G2231 UART RX/SPI TX and SPI RX/ stepper signals   
    Project: control 3 MSP430G2231's using a single G2231 as a bridge/converter/demultiplexer that recieves data through the USB
     
    the bridge takes bytes and puts alternately sends them to recievers 1-3.
     
    the recievers' P1.0 and P1.6 go to stepper motor controllers to step on rising edge and control direction, respectively.
     
    "bridge" part:
    -recieves bytes from 2400 8N1 input to P1.1 (requires launchpad 'RXD' jumper to be removed and the pin on the FTDI side connected to P1.1)
     
    -after reception, transmits each byte out of P1.6 as MOSI and P1.5 as SCLK.
     
    -cycles through bringing one of three output pins low as a chip select
     

    #include #include // Conditions for 2400 Baud SW UART, ACLK = 32768 #define Bitime_5 0x06 // ~ 0.5 bit length + small adjustment #define Bitime 0x0E // 427us bit length ~ 2341 baud #define RXD 0x02 #define TXD 0x20 #define LED1 0x01 #define LED2 0x40 unsigned char RXTXData; unsigned char BitCnt; unsigned char temp; static void __inline__ delay(register unsigned int n); int main (void){ WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer CCTL0 = OUT; // TXD Idle as Mark TACTL = TASSEL_1 + MC_2; // ACLK, continuous mode P1SEL = TXD + RXD; // P1DIR = TXD + LED1 + BIT4 + BIT3; P1OUT = LED1 + BIT4 + BIT3; USICTL0 = USIPE7 | USIPE6 | USIPE5 | USIMST | USIOE | USISWRST; // Port, SPI Master USICTL1 = USICKPH | USIIE; USICKCTL = 0xE4;// /128 aclk? temp = 0; while(1){ P1OUT |= LED1 + BIT4 + BIT3; BitCnt = 0x8; // Load Bit counter CCTL0 = SCS + OUTMOD0 + CM1 + CAP + CCIE; // Sync, Neg Edge, Cap _BIS_SR(LPM3_bits + GIE); // Enter LPM3 w/ interr until char RXed if(temp == 2){ temp = 0; }else{ temp = temp +1; } } } // #pragma vector=TIMERA0_VECTOR interrupt(TIMERA0_VECTOR) Timer_A (void){ CCR0 += Bitime; // Add Offset to CCR0 if( CCTL0 & CAP ){ // Capture mode = start bit edge CCTL0 &= ~ CAP; // Switch from capture to compare mode CCR0 += Bitime_5; }else{ RXTXData = RXTXData >> 1; if (CCTL0 & SCCI) // Get bit waiting in receive latch RXTXData |= 0x80; BitCnt --; // All bits RXed? if ( BitCnt == 0){ USISRL = RXTXData; if(temp == 0){ P1OUT &= ~LED1; P1OUT |= BIT4 + BIT3; }else if(temp == 1){ P1OUT &= ~BIT4; P1OUT |= LED1 + BIT3; }else if(temp == 2){ P1OUT &= ~BIT3; P1OUT |= LED1 + BIT4; } USICNT |= 0x08; USICTL0 &= ~USISWRST; while (!(USIIFG & USICTL1)); USICTL0 |= USISWRST; delay(0); P1OUT |= LED1 + BIT4 + BIT3; CCTL0 &= ~ CCIE; // All bits RXed, disable interrupt _BIC_SR_IRQ(LPM3_bits + GIE); // Clear LPM3 bits from 0(SR) } } } static void __inline__ delay(register unsigned int n) { __asm__ __volatile__ ( "1: \n" " dec %[n] \n" " jne 1b \n" : [n] "+r"(n)); }
     
    The reciever recieves the byte from the bridge and in state machine fashion puts the byte in:
    -a counter for number of steps to take
    -determines to set or clear a direction bit
    -sets TACCR0 to control toggle rate
     

    #include #include unsigned int bufff; unsigned char count; int main(void){ WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer P1OUT = 0x00; // P1.4 set, else reset P1DIR = 0x01 + BIT6; // P1.0 output, else input USICTL0 |= USIPE7 + USIPE5; // Port, SPI slave USICTL1 |= USIIE; // Counter interrupt, flag remains set USICTL0 &= ~USISWRST; // USI released for operation USICNT = 8; // init-load counter bufff = 0; count = 0; TACTL = TASSEL_1 | MC_1; //Set TimerA to use auxiliary clock in UP mode TACCTL0 = CCIE; //Enable the interrupt for TACCR0 match TACCR0 = 2; _BIS_SR(LPM0_bits + GIE); // Enter LPM0 w/ interrupt while(1){ } } // USI interrupt service routine interrupt(USI_VECTOR) universal_serial_interface(void){ if(count == 0){//bufff if(USISRL > 0x7A){ bufff = bufff + 0xFF00; }else{ bufff = bufff + USISRL; } }else if(count == 1){//dir if(USISRL > 0x3F){ P1OUT |= BIT6; }else{ P1OUT &= ~BIT6; } }else if(count == 2){//speed TACCR0 = USISRL; }else{ count = 0; } count = count + 1; if(count == 3){ count = 0; } USICNT = 8; // re-load counter } interrupt(TIMERA0_VECTOR) TIMERA0_ISR(void) { if( bufff > 0){ P1OUT ^= BIT0; bufff = bufff - 1; } }
     
    PROBLEMS:
    -the bridge can't pass data through it too fast. one must wait about ~200ms until the next byte is sent to prevent data loss. (the code isn't optimized and kinda "fatty" in all likelihood).
    -since the TimerA assignments from USI data occur in the USI-ISR (and i haven't found a reliable way to do it otherwise), the data isn't 'pushed' into TimerA until the next byte is recieved.
    -it would be cool to not have to modify the jumpers on the launchpad to do the UART, but its based on TI code that worked so i went with it.
  4. Like
    dacoffey reacted to Jessters in Custom target board for cheap MSP430 development   
    Haven't been on the forum for a few months, been busy with a few projects for work(which I probably could have gotten some help with here had I bothered to log on... heh). Good to see the forum is growing. And experienced guys, get ready for a possible bag full of questions as I get started on a new project here shortly.
     
    On another note, here is a recent MSP430 based project I just wrapped up. Previously we had needed to purchase 7 separate TS430PM64 target boards to be added to projects on a permanent basis. As the target boards directly from TI can run 75+ USD my business partner and I decided to make our own. Essentially, I designed one main board that can be added to any project on a permanent basis, and runs less than 10 dollars to make. Since we work on industrial projects, this board is usually on the inside of aluminum frame and housing. Hence the need of a "permanent" addition, while still allowing for debugging and programming.
     
    A second board, which consists of a MSP430 of just about any 64PM variation, a 3.3v reg, and a crystal can then be plugged in to the main board. The reason we did it this way is that the main board itself can support various different MCU variants, but the Yamaichi clam shell socket for those MCU's runs around 90 dollars. Adding one of those completely defeat the purpose of the project due to cost. Simply making the secondary board and adding various MCU's as needed was MUCH more cost effective. In the end it came out as a set up similar to the old BASIC Stamp break out boards. But works seamlessly for what we needed.
     

  5. Like
    dacoffey reacted to MSP430Andy in Poor Man's Command Line Shell   
    I needed to serially input data in my "2553" LaunchPad using the hardware Uart.
    I hacked together some code which has Printf(), a receive ring buffer, Uart routines,
    and the case/switch Poor Man's Command Line Shell. You need to criss-cross the tx/rx on the LP
    header and use the terminal program in CCS 4.1. Please Note: CCS 5 does not have the terminal program installed ! :evil:
    Note: GRACE was used to setup the USCI_A0 hw UART at 9600 8 N 1
    Enjoy
     
    Edited. 1/27/12 Ti took out the terminal program in CCS v 5 but you can add it back into the software.
     
    http://processors.wiki.ti.com/index.php/How_to_install_the_terminal_plugin_in_CCSv5
     

    /*********************************************************************************/ /*! THIS SOFTWARE IS PROVIDED BY THE THE HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. IF YOU USE THIS SOFTWARE AND YOUR HOUSE BURNS DOWN AND YOUR WIFE AND CHILDREN BECOMES HOMELESS AND WORST OF ALL YOUR DOG DIES, DON'T HOLD ME RESPONSIBLE! YOU CAN USE THIS CODE BUT PLEASE GIVE CREDIT TO THOSE WHO CONTRIBUTED TO IT. PLEASE INCLUDE ALL COPYWRITES HEADERS/FOOTERS IN YOUR SOFTWARE. */ /*********************************************************************************/ /*********************************************************************************/ /*! Author: MSP430Andy Description: LP_2553_Cmd_Line - command line shell or interpreter. Program Revision: 1.0b (beta) Date: 2/1/12 PC Platform: Windows PC/SP3 Development platform: LaunchPad revision 2 firmware. PC compiler used: Eclipse with CCS 4.1 & 5 <--- Missing terminal program in 5 !!!!! Configuration setup I/O generated by: GRACE Device used: MSP430G2553 Pin DIP Software Module: USCI_A0 at 9600, 8 N 1 Bugs: 1. Syntax warnings in function printf()? - routine works but there were no errors in CCS 4.1? Code size: 2553 Device: 16K flash, 512 bytes RAM Flash used: xxx k RAM used: xxx bytes (without printf_Test() Program status OK */ /*********************************************************************************/ /*********************************************************************************/ /*! [includes] */ /*********************************************************************************/ #include // GRACE Include #include // Support Include #include // for printF #include /*********************************************************************************/ /*! [Defines] */ /*********************************************************************************/ // Red LED - on board on LaunchPad #define RED_LED_OFF() P1OUT &= ~BIT0 #define RED_LED_ON() P1OUT |= BIT0 #define RED_LED_FLIP() P1OUT ^= BIT0 // Green LED - on board on LaunchPad #define GRN_LED_OFF() P1OUT &= ~BIT6 #define GRN_LED_ON() P1OUT |= BIT6 #define GRN_LED_FLIP() P1OUT ^= BIT6 #define TX_RX_DIAG 0 // [1 = Toggles LP LEDs rx = grn & tx = red] [0 = all off] #define SYNC_BYTE 0x7E // 127 dec #define ESCAPE_BYTE 0x7D // 128 dec /*********************************************************************************/ /*! [Rx Ring Buffer] */ /*********************************************************************************/ //Ring Buffer #define RING_BUFFER_SIZE 32 char ring_buffer[RING_BUFFER_SIZE]; // usci_A0 rx ring buffer /* Size of RX ring buffer */ #define RING_BUFFER_MASK ( RING_BUFFER_SIZE - 1) #if ( RING_BUFFER_SIZE & RING_BUFFER_MASK ) #error RX ring buffer size is not a power of 2 #endif // Ring Buffer Global Variables int ring_buffer_data_size = 0; // number of chars in buffer int ring_buffer_read_pointer = 0; // indice number of last read char int ring_buffer_write_pointer = 0; // indice number of last written char /*********************************************************************************/ /*! [Printf] */ /*********************************************************************************/ //Printf Functions void printf_putc (unsigned char c); void printf_puts(char *s); void printf(char *, ...); void printf_Test(void); /*********************************************************************************/ /*! [Rx Receive Callback] */ /*********************************************************************************/ // Callbacks static uint8_t dummy_callback( uint8_t ); // default ring buffer callback // Holds pointers to all callback functions for USCI_AO rx buffer static uint8_t (*uart_rx_callback)( uint8_t ) = dummy_callback; /*********************************************************************************/ /*! [Function Prototypes] */ /*********************************************************************************/ // rx ring buffer prototypes int ring_buffer_full(void); int ring_buffer_empty(void); void ring_buffer_push_char(char c); // to ring buffer unsigned char ring_buffer_pull_char(void); // from ring buffer <------<<<< for rx void flush_ring_buffer(void); // clear ring buffer with spaces 0x20 // usci_a0 uart prototypes void uart_put_char( uint8_t ); // <-------<<<<< for tx void uart_write_buffer( uint8_t*, uint16_t ); void uart_write_buffer_escaped( uint8_t*, uint16_t ); uint8_t hex_to_string( uint8_t* , uint8_t*, uint8_t ); // cmd line prototypes void cmd_show_help(void); void poll_cmd(void); /*********************************************************************************/ /*! [Main] */ /*********************************************************************************/ void main(void) { CSL_init(); // Activate Grace-generated configuration __enable_interrupt(); // Set global interrupt enable flush_ring_buffer(); // clear receive ring buffer with spaces 0x20 //_________________________________________________________________________________ RED_LED_OFF(); GRN_LED_OFF(); //printf_Test(); cmd_show_help(); while(1){ poll_cmd(); } } // end of main /*********************************************************************************/ /*! [uART_USCI_A0_RX_ISR] */ /*********************************************************************************/ void UART_USCI_A0_RX_ISR(void){ // Process incoming byte from USART if( IFG2 & UCA0RXIFG ) { // Call rx callback function (default - dummy) or // ring_buffer_callback if selected if( uart_rx_callback( UCA0RXBUF ) ) { // If function returns something nonzero, wakeup the processor //__bic_SR_register_on_exit(LPM1_bits); _nop(); } } } /*********************************************************************************/ /*! [user Application Functions] */ /*********************************************************************************/ /*********************************************************************************/ /*! [uART Functions] */ /*********************************************************************************/ /*********************************************************************************/ /*! @fn uart_put_char( uint8_t character ) @brief transmit single character */ /*********************************************************************************/ void uart_put_char( uint8_t character ) { while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer ready? UCA0TXBUF = character; if (TX_RX_DIAG){ RED_LED_FLIP(); } } /*********************************************************************************/ /*! @fn uart_write_buffer( uint8_t character ) @brief transmit whole buffer */ /*********************************************************************************/ void uart_write_buffer( uint8_t* buffer, uint16_t length ) { uint16_t buffer_index; for( buffer_index = 0; buffer_index < length; buffer_index++ ) { while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer ready? UCA0TXBUF = buffer[buffer_index]; } } /*********************************************************************************/ /*! @fn uart_write_buffer_escaped( uint8_t character ) @brief transmit whole buffer while escaping characters The uart_write_buffer_escaped() is more for sending whole packets through the serial peripheral to the computer. Normally you just send a stream of bytes. Unfortunately, there is no way for the computer to know when a stream of data begins or ends. This function uses the 0x7E byte as a start and end of packets. This way, the receiver knows when to begin and end capturing data. If your data contains a 0x7E, that might confuse the receiver, so you must escape it by preceding it with a 0x7D and modifying it. The receiver must be aware of this to process it accordingly. */ /*********************************************************************************/ void uart_write_buffer_escaped( uint8_t* buffer, uint16_t length ) { uint16_t buffer_index; while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer ready? UCA0TXBUF = SYNC_BYTE; for( buffer_index = 0; buffer_index < length; buffer_index++ ) { if( (buffer[buffer_index] == SYNC_BYTE) | (buffer[buffer_index] == ESCAPE_BYTE) ) { while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer ready? UCA0TXBUF = ESCAPE_BYTE; while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer ready? UCA0TXBUF = buffer[buffer_index] ^ 0x20; } else { while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer ready? UCA0TXBUF = buffer[buffer_index]; } } while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer ready? UCA0TXBUF = SYNC_BYTE; } /*********************************************************************************/ /*! @fn void dummy_callback( uint8_t rx_char ) @brief empty function works as default callback */ /*********************************************************************************/ static uint8_t dummy_callback( uint8_t rx_char ) { if (TX_RX_DIAG){ GRN_LED_FLIP(); } //uart_put_char(rx_char); // turnaround echo to tx <----- for test only ring_buffer_push_char(rx_char); // Put/push char into ring buffer return 0; } /*********************************************************************************/ /*! @fn uint8_t hex_to_string( uint8_t* buffer_out, uint8_t* buffer_in, uint8_t buffer_in_size ) @brief DEBUG function used to convert hex values to [hex]string format The hex_to_string function was just for debugging. When you want to display a value, you usually use printf(). Unfortunately, printf takes a lot of cycles to format the data, and if you're doing time-sensitive stuff, you can't afford the delay. In cases where you don't have full debugging capability, you might want to print out the values of some registers or variables. the hex_to_string() function converts a value to a hexadecimal string. */ /*********************************************************************************/ uint8_t hex_to_string( uint8_t* buffer_out, uint8_t* buffer_in, uint8_t buffer_in_size ) { static const uint8_t hex_char[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; uint8_t counter = 0; while( counter < buffer_in_size * 2 ) { buffer_out[counter] = hex_char[((buffer_in[(counter>>1)]>>4) & 0xF)]; counter++; buffer_out[counter] = hex_char[(buffer_in[(counter>>1)] & 0xF)]; counter++; } // Terminate string with null character buffer_out[counter++] = 0; return counter; } /*********************************************************************************/ /*! [Printf Functions] */ /*********************************************************************************/ /*********************************************************************************/ /*! @fn void printf_putc (unsigned char c) @brief put char into tx buffer */ /*********************************************************************************/ void printf_putc (unsigned char c) { _nop(); while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer ready? UCA0TXBUF = c; // TX <-- c } /*********************************************************************************/ /*! @fn void printf_puts(char *s) { while(*s) printf_putc(*s++); @brief put string chars into into tx buffer */ /*********************************************************************************/ void printf_puts(char *s) { while(*s) printf_putc(*s++); } /*********************************************************************************/ /*! @fn @brief */ /*********************************************************************************/ static const unsigned long dv[] = { // 4294967296 // 32 bit unsigned max 1000000000, // +0 100000000, // +1 10000000, // +2 1000000, // +3 100000, // +4 // 65535 // 16 bit unsigned max 10000, // +5 1000, // +6 100, // +7 10, // +8 1, // +9 }; /*********************************************************************************/ /*! @fn @brief */ /*********************************************************************************/ static void xtoa(unsigned long x, const unsigned long *dp) { char c; unsigned long d; if(x) { while(x < *dp) ++dp; do { d = *dp++; c = '0'; while(x >= d) ++c, x -= d; printf_putc(c); } while(!(d & 1)); } else printf_putc('0'); } /*********************************************************************************/ /*! @fn @brief */ /*********************************************************************************/ static void puth(unsigned n) { static const char hex[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; printf_putc(hex[n & 15]); } /***********************************************************************************/ /*! @fn @brief */ /***********************************************************************************/ void printf(char *format, ...) { char c; int i; long n; va_list a; va_start(a, format); while(c = *format++) { if(c == '%') { switch(c = *format++) { case 's': // String printf_puts(va_arg(a, char*)); break; case 'c': // Char printf_putc(va_arg(a, char)); break; case 'i': // 16 bit Integer case 'u': // 16 bit Unsigned i = va_arg(a, int); if(c == 'i' && i < 0) i = -i, printf_putc('-'); xtoa((unsigned)i, dv + 5); break; case 'l': // 32 bit Long case 'n': // 32 bit uNsigned loNg n = va_arg(a, long); if(c == 'l' && n < 0) n = -n, printf_putc('-'); xtoa((unsigned long)n, dv); break; case 'x': // 16 bit heXadecimal i = va_arg(a, int); puth(i >> 12); puth(i >> 8); puth(i >> 4); puth(i); break; case 0: return; default: goto bad_fmt; } } else bad_fmt: printf_putc(c); } va_end(a); } /***********************************************************************************/ /*! @fn @brief */ /***********************************************************************************/ void printf_Test(void){ /* ================= Printf() for 2553 ================= There are 7 format specifiers: %c - Character %s - String %i - signed Integer (16 bit) %u - Unsigned integer (16 bit) %l - signed Long (32 bit) %n - uNsigned loNg (32 bit) %x - heXadecimal (16 bit) Field width, floating point and other standard printf() features are not supported. */ const char *s = "test"; const char c = 'X'; const int i = -12345; const unsigned u = 12345; const long int l = -1234567890; const long unsigned n = 1234567890; const unsigned x = 0xABCD ; //hex printf("%s", "\r\n*** printf() test ***\r\n"); printf("String %s\r\n", s); printf("Char %c\r\n", c); printf("Integer %i\r\n", i); printf("Unsigned %u\r\n", u); printf("Long %l\r\n", l); printf("uNsigned loNg %n\r\n", n); printf("heX %x\r\n", x); printf("multiple args %s %c %i %u %l %n %x\r\n", s, c, i, u, l, n, x); printf("\r\n*** Done ***\r\n"); // printf_Test result .... /* *** printf() test *** String test Char X Integer -12345 Unsigned 12345 Long -1234567890 uNsigned loNg 1234567890 heX ABCD multiple args test X -12345 12345 -1234567890 1234567890 ABCD *** Done *** */ } /*********************************************************************************/ /*! [Ring Buffer Functions] */ /*********************************************************************************/ /*********************************************************************************/ /*! @fn void ring_buffer_push_char(char c) @brief adds a char */ /*********************************************************************************/ void ring_buffer_push_char(char c) { // increase ring_buffer_write_pointer, check if at end of array if (++ring_buffer_write_pointer >= RING_BUFFER_SIZE) ring_buffer_write_pointer = 0; ring_buffer[ring_buffer_write_pointer] = c; ring_buffer_data_size++; } /*********************************************************************************/ /*! @fn int ring_buffer_full(void) @brief returns 1 if buffer is full, 0 if buffer is not full */ /*********************************************************************************/ int ring_buffer_full(void) { return ring_buffer_read_pointer == ring_buffer_write_pointer && ring_buffer_data_size == RING_BUFFER_SIZE; } /*********************************************************************************/ /*! @fn int ring_buffer_empty(void) @brief returns 1 if buffer is empty, 0 if buffer is not empty */ /*********************************************************************************/ int ring_buffer_empty(void) { return ring_buffer_read_pointer == ring_buffer_write_pointer && ring_buffer_data_size == 0; } /*********************************************************************************/ /*! @fn void ring_buffer_pull_char(void) @brief pull char from queue */ /*********************************************************************************/ unsigned char ring_buffer_pull_char(void) { char rx; // added - also above unsigned char if (++ring_buffer_read_pointer >= RING_BUFFER_SIZE) ring_buffer_read_pointer = 0; rx = ring_buffer[ring_buffer_read_pointer]; // added // enter space on place of read char so we can see it is removed ring_buffer[ring_buffer_read_pointer] = 0x20; ring_buffer_data_size--; return rx; // added } /*********************************************************************************/ /*! @fn void flush_ring_buffer(void) @brief flushes ring buffer */ /*********************************************************************************/ void flush_ring_buffer(void){ // make sure there are no random chars in array, all spaces int i; for (i = 0; i < RING_BUFFER_SIZE; i++) ring_buffer[i] = 0x20; // spaces } /*********************************************************************************/ /*! [Command Line Functions] */ /*********************************************************************************/ /*********************************************************************************/ /*! @fn void cmd_show_help(void) @brief show cmd line help menu */ /*********************************************************************************/ void cmd_show_help(void) { const char *m0 = "<<--COMMAND LINE MENU-->>"; const char *m1 = "[A] LP Red LED ON"; const char *m2 = "[b] LP Red LED OFF"; const char *m3 = "[C] LP Green LED ON"; const char *m4 = "[D] LP Green LED OFF"; const char *m5 = "[E] Command #5 Spare Text"; const char *m6 = "[F] Command #6 Spare Text"; const char *m7 = "[G] Command #7 Spare Text"; const char *m8 = "[?] Show Help"; const char *prompt = "Cmd >> "; printf("\r\n"); printf("\r\n"); printf("%s\r\n",m0); printf("\r\n"); printf("%s\r\n",m1); printf("%s\r\n",m2); printf("%s\r\n",m3); printf("%s\r\n",m4); printf("%s\r\n",m5); printf("%s\r\n",m6); printf("%s\r\n",m7); printf("%s\r\n",m8); printf("\r\n"); printf("%s",prompt); } /*********************************************************************************/ /*! @fn @brief */ /*********************************************************************************/ void poll_cmd(void) { while(1){ char x; if (ring_buffer_data_size > 0){ x = ring_buffer_pull_char(); uart_put_char(x); // return/echo cmd char to uart screen } switch (x){ case 'A': case 'a': _nop(); RED_LED_ON(); _nop(); cmd_show_help(); break; case 'B': case 'b': _nop(); RED_LED_OFF(); _nop(); cmd_show_help(); break; case 'C': case 'c': GRN_LED_ON(); cmd_show_help(); break; case 'D': case 'd': GRN_LED_OFF(); cmd_show_help(); break; case 'E': case 'e': cmd_show_help(); break; case 'F': case 'f': cmd_show_help(); break; case 'G': case 'g': cmd_show_help(); break; case '?': cmd_show_help(); break; //default: } // end of case x = 0x20; // clear case char _nop(); } // end of while } //================================================================================= //================================================================================= // The End
  6. Like
    dacoffey reacted to oPossum in Dallas/Maxim One Wire Library   
    Here is a basic library for 1-wire communication. It works with CPU frequency of 1 MHz or higher. Carefully crafted assembly code is used to allow operation over a wide CPU clock frequency range.
     
    There are only two functions. One for setup and the other for all communication tasks.
     

    // one_wire.h void one_wire_setup(volatile unsigned char *dir, volatile unsigned char *in, unsigned bitmask, unsigned mhz); int owex(int data, unsigned bits);
     
    The library is initialized by a call to one_wire_setup(). The arguments specify the I/O pin and clock frequency.
    An example for P1.4 at 16 MHz...
     
    one_wire_setup(&P1DIR, &P1IN, 0x10, 16);
     
    The setup function can be called repeatedly to allow communication on more than one I/O pin.
     
    The owex() [One Wire EXchange] function does bus reset, tx and rx.
     
    To reset the bus and detect if any devices are present, just call it with a bit count of zero....
     
    p = owex(0, 0);
     
    The returned value will be -1 (0xFFFF) if any devices are detected, or 0 if none are detected.
     
    To send data...
     
    owex(0xCC, 8); // Skip ROM command
     
    The returned value should match the data sent, if it does not then there is a bus problem.
     
    To receive data, use -1 (0xFFFF) for the tx data value...
     
    d = owex(-1, 8); // Get 8 bits
     
    1 to 16 bits can be sent/received at once.
     
    This is the core code...

    .def owex ; int owex(int data, unsigned bit_count) .def owdport .def owiport .def owbit .def owtiming .bss owdport, 2 ; Direction port .bss owiport, 2 ; Input port .bss owbit, 2 ; Port bitmask .bss owtiming, 0 ; Timing array .bss owda, 2 ; 28 Zero .bss owdb, 2 ; 33 .bss owdc, 2 ; 39 .bss owdd, 2 ; 7 One .bss owde, 2 ; 8 .bss owdf, 2 ; 85 .bss owdg, 2 ; 500 Reset .bss owdh, 2 ; 50 .bss owdi, 2 ; 450 owex ; tst R13 ; Reset? jeq owrst ; Yes... push R11 ; Save R11, R13 push R13 ; clr R13 ; Clear bit count ; owloop ; --- Tx/Rx bit loop rra R12 ; Get tx bit jc owone ; If one... ; ; - Send and verify zero mov &owda, R15 ; nop ; mov &owdport, R14 ; Bus low bis.b &owbit, 0(R14) ; ; call #owdelay ; Delay 28 us ; mov &owiport, R14 ; Sample bus mov.b @R14, R14 ; bit &owbit, R14 ; rrc R11 ; ; mov &owdb, R15 ; Delay 33 us call #owdelay ; ; mov &owdc, R15 ; mov &owdport, R14 ; Bus open bic.b &owbit, 0(R14) ; ; jmp ownext ; Delay 39 us ; owone ; - Send one and read bit mov &owdd, R15 ; tst R15 ; mov &owdport, R14 ; Bus low bis.b &owbit, 0(R14) ; ; jn owoneo ; Delay 7 us owdlyd ; sub #8, R15 ; nop ; jc owdlyd ; subc R15, PC ; nop ; nop ; nop ; owoneo ; bic.b &owbit, 0(R14) ; Bus open ; jc owones ; Delay 8 us mov &owde, R15 ; owdlye ; sub #8, R15 ; nop ; jc owdlye ; subc R15, PC ; nop ; nop ; nop ; owones ; mov &owiport, R14 ; Sample bus mov.b @R14, R14 ; bit &owbit, R14 ; rrc R11 ; ; mov &owdf, R15 ; Delay 85 us ownext ; call #owdelay ; ; - Next bit inc R13 ; Increment bit count cmp R13, 0(SP) ; Compare bit count jne owloop ; Loop if not done... owrxa ; - Align rx data cmp #16, R13 ; Rx data aligned? jeq owrex ; Yes.. rra R11 ; Shift in a zero bit inc R13 ; Inc bit count jmp owrxa ; Next bit... owrex ; mov R11, R12 ; Get rx data to R12 pop R13 ; Restore R11, R13 pop R11 ; ret ; Return ; ; owrst ; - Reset and presence detect mov &owdport, R14 ; Bus low bis.b &owbit, 0(R14) ; ; mov &owdg, R15 ; Delay 500 us call #owdelay ; ; bic.b &owbit, 0(R14) ; Bus open ; mov &owdh, R15 ; Delay 50 us call #owdelay ; ; mov &owiport, R14 ; Sample bus mov.b @R14, R14 ; bit &owbit, R14 ; subc R12, R12 ; ; mov &owdi, R15 ; Delay 450 us ;jmp owdelay ; and return ; owdelay ; sub #8, R15 ; nop ; jc owdelay ; subc R15, PC ; nop ; nop ; nop ; ret ; ; .end ;
     
    Demo program to read DS1820/1822 temperature sensor is included in zip file.
    one_wire.zip
  7. Like
    dacoffey reacted to mtlevine0 in LED Twitter Ticker   
    I've been working on a project using the launchpad with the msp430g2553 interfaced to a LED display. A Python script running on my PC fetches the most recent tweet of a specific twitter user and sends it to the launchpad via serial. Being my first time ever using Python I was impressed to find how easy it was to implement this. I plan on adding an unread email counter and weather ticker to the script in the future.
     
    Heres a quick video of it in action:

    http://www.youtube.com/watch?v=IDIMfBfikjU
    I tweeted "Hello 43oh.com" from my twitter account and of course twitter shortened it with their url shortener. Couldn't find an option to turn that feature off.
     
    Edit: I was able to get my hands on a nicer camera, so I replaced the video with a nicer looking one.
  8. Like
    dacoffey reacted to gwdeveloper in Bus Pirate, SUMP and the MSP430   
    To start off, this is not a tutorial but more of a quick how-to. The 1st post will be about using your Bus Pirate to "sniff" SPI data on your MSP430. Mostly, I'm posting this because I've never found clear instructions or examples on doing this but it's been important in solving a lot of programming issues. The Bus Pirate is the handiest tool on my bench -it's tiny and has a lot of functionality.
     
    Bus Pirate http://dangerousprototypes.com/docs/Bus_Pirate
     
    Hardware Connections
    Bus Pirate -> MSP430
    CS -> UCBxSTE (or your CS pin)
    CLK ->UCBxCLK ( or your SPI clock pin)
    MISO -> UCBxSOMI (or your SPI input pin)
    MOSI -> UCBxSIMO (or your SPI output pin)
    AUX -> SPI D/C or other Trigger source.
     
    Software
    Alternative Sump Logic Analyzer Client http://www.lxtreme.nl/ols/
    Labeled Client Project for MSP430 sump_no_signals.JPG[/attachment]
    Then, what I like to do, is create a logic trigger in my program. This is done, so I can determine exactly when I want to trigger the analyzer instead of relying on a clock source.
     
    This code can be placed in your main.c:

    // manual logic trigger for analyzer #define LOGIC_OUT P1OUT #define LOGIC_DIR P1DIR #define LOGIC_BIT BIT7 #define TRIGGER (LOGIC_OUT |= LOGIC_BIT)
    Here I used P1.7 on the MSP430F2274. Change the port and bit configuration to suit your hardware. This will be the pin we connect to the AUX pin of the Bus Pirate. Then you can place TRIGGER; anywhere you'd like to start analyzing your data.
     
    To being a capture, click on the 'Start Capturing' button. You'll be presented with a configuration window. Select the configuration for your hardware; Analyzer Port is the com port for the Bus Pirate. Leave the speed at 115200bps and for Device Type, select "Bus Pirate OLS mode". In the Acquisition tab, leave the default settings. Move to the Triggers tab; check the box to enable the trigger. For mode, select "Serial" and Channel to 0. The last step is select the Trigger Mask. We're using Channel 4 (AUX on the Bus Pirate), so put a check in the 5th box from the right.
     
    It should look like this:
    uart3.zipsump_no_annotations.JPG[/attachment]
    From here, select "Tools -> SPI Analyzer". The proper channel and mode settings were saved as part of the Labeled Client Project, so just press "Analyze". You will see all of the data that was transfer and at what times. Press close when you're done reading.
     
    The resulting window after Analyzing:
    [attachment=0]sump_annotations.JPG[/attachment]
    Here you can see that our Trigger was pulled high, CS was pulled low, no serial data was incoming, the clock is function properly and our outgoing datastream is "0xAE, 0x00, 0x10, 0x40, 0x00, 0x81, 0x8F....." (BTW, that's the init sequence for the OLED Booster Pack)
     
    To scan again, just press the "Repeat Capture" button. This also works for I2C, UART and other protocols (with different settings, of course).
  9. Like
    dacoffey reacted to touch in Reading a DHT11 Temperature and Humidity sensor   
    I picked up a few of these sensors awhile back and wanted to get some code working for them.. Finally got the sensor working.
     
    I'm using a MSP430G2553 clocked @ 8mhz, all of it is done in software, no timers, so if you want to change the clock speed, you will need to change the __delay_cycles and the counter that determines if a bit if 1 or 0 (t). I'll eventually update this to work at other frequencies without having to fool with this stuff.
     
    Sensor is hooked to P1.7 in this code, but can be any unused port on P1, could easily be changed to P2 if needed.
     
    ex output, temp is in c, humidity is in %.
    Temperature: 25
    Humidity: 32
     

    #include #include #define TIMEOUT 1000 int temp,humidity; char read(char pin); void UART_Print(char *string); int main( void ) { WDTCTL = WDTPW + WDTHOLD; BCSCTL1 = CALBC1_8MHZ; DCOCTL = CALDCO_8MHZ; P1SEL = BIT1 + BIT2; // P1.1 = RXD, P1.2=TXD P1SEL2 = BIT1 + BIT2; // P1.1 = RXD, P1.2=TXD UCA0CTL1 |= UCSSEL_2; // SMCLK UCA0BR0 = 0x41; // 8MHz 9600 UART UCA0BR1 = 0x03; // 8MHz 9600 UART UCA0MCTL = UCBRS0; UCA0CTL1 &= ~UCSWRST; IE2 |= UCA0RXIE; while(1){ if(read(BIT7)){ char temp2[20]; char humidity2[20]; sprintf(temp2, "Temperature: %d", temp); sprintf(humidity2, "Humidity: %d", humidity); UART_Print(temp2); UART_Print("\r"); UART_Print(humidity2); UART_Print("\r"); }else{ UART_Print("Error reading DHT11 sensor\r"); } //2 second delay __delay_cycles(36000000); } } char read(char pin) { // bit buffers & timeout char bitcount = 7; char byte = 0; char bits[5] = {0,0,0,0,0}; unsigned int timer; // request reading P1DIR |= pin; P1OUT &= ~pin; __delay_cycles(144000); //18ms delay @ 8mhz sysclk P1OUT |= pin; __delay_cycles(320); //40us delay @ 8mhz sysclk P1DIR &= ~pin; // wait for request reply timer = TIMEOUT; while(!(P1IN&pin)){ if (timer-- == 0){ return 0; } } timer = TIMEOUT; while(P1IN&pin){ if (timer-- == 0) { return 0;} } // start receiving 40 bits char i; for (i=0; i < 40; i++) { timer = TIMEOUT; while(!(P1IN&pin)){ if (timer-- == 0){ return 0; } } timer = TIMEOUT; char t = 0; while(P1IN&pin){ t++; if (timer-- == 0){ return 0; } } if (t > 40) bits[byte] |= (1 << bitcount); t = 0; if (bitcount == 0) { bitcount = 7; byte++; }else{ bitcount--; } } // checksum if((bits[0] + bits[2]) == bits[4]){ temp = bits[2]; humidity = bits[0]; return 1; }else{ return 0; } } void UART_Print(char *string) { while (*string) { while (!(IFG2&UCA0TXIFG)); UCA0TXBUF = *string++; } }
  10. Like
    dacoffey reacted to username in MSP430 PC GUI Eval Tool   
    Hey all,
     
    I was working on a GUI that would be able to control any and all functions on a particular MSP430 processor from a PC GUI. Only limitations a course would be P1.1 and P1.2 which are required for GUI communication. This is very very very much so a work in progress. Currently i'm writing it using WX Widgets libraries to simplify the GUI aspect of it. However, currently i'm not using a "form builder" so it is going to take a handy amount of time to write. Good c++ experience though....
     
    This GUI would be very handy to have from a hardware/software test debug standpoint. For example, say I wanted to test out some SPI sensor I purchased, I could use a GUI such as this to send custom SPI packets to the device i'm testing and read/observe results live. That as opposed to having to write a micro.c file to do the communication and re write it every time something doesn't work.
     
    Many thanks to rick and suggaraddict for assistance on c++ coding help
     
    GUI Download Rev 0.5 : https://github.com/NateZimmer/MSP430-Ev ... I_EVAL.exe (windows.exe, click "view raw" to download)
    (feedback on whether or not it works for you would be great. Gaurenteed to work with a FTDI RS232 -> USB. However, launchpad drivers suppperr flakey and crapey )
     
    Remember to flash https://github.com/NateZimmer/MSP430-Ev ... er/GUI.cpp to your MSP430G2553
     
    Source Code is now at https://github.com/NateZimmer/MSP430-Eval-Tool
     
    (your going to need to download and BUILD the wx libraries to get this to work)
     
    Main Connect tab: Implemented
     

     
    Digital Output tab: Implemented
     

     
    Digital Input tab: Implemented
     

     
    SPI Tab: Implemented but not fully tested
     

     
    Analog Input tab: In Progress
     
    Connection Issue Debug
    1. Make sure you got a Rev1.5 launchpad with a G2553 micro flashed with the proper code provided. Also, makesure your jumpers are set to hardware uart.
     
    2. If that doesn't work... sadly, the TI RS232 <-> USB sucks hardcore compared to FTDI that always works. Once a connection is established, it works fine. However, getting that first connection can be a super pain. If your having connection issues, open up a terminal program(such as putty), connect to the com port of your msp430, and press the "1" key and ONLY the 1 key. If your msp430 is working properly you should receive "PING" back. At that point, close the terminal program and open up my .exe program. At that point, it should connect fine.
  11. Like
    dacoffey reacted to username in MSP430 + PC For AR Drone Control   
    Hey all,
     
    My latest project features a G2553 in combination with a FTDI breakout board and a C++ GUI App written on the PC. Using these i'm able to control a AR drone sending Ethernet UDP commands from my PC. My next goal is to do all this at the embedded level and eliminate the need for the computer. Nevertheless, it was some great practice writing GUIs.
     
    Youtube Demo:
     


     
    Drone App Pic
     

     
    Will try to post alittle more info later if anyone has any interest.
     
    Thanks for looking!
    Nate
  12. Like
    dacoffey reacted to oPossum 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
  13. Like
    dacoffey reacted to cubeberg in Etch A Sketch   
    This is an LCD version of an Etch-A-Sketch. Made this for my daughter's 5th birthday.
     
    LCD is a 128*128 Powertip T6963c LCD
    5v for the LCD and LP is supplied by a 5v cell phone backup
    2x 100k linear pots used for control
    Negative contrast (-13v) is currently supplied by two 9v batteries - I'll be making one with a MC34063 later
    The shake detection was salvaged from a toy - no idea where to get them (I need to turn down the number of shakes needed)
    I used an old Floppy Drive cable to connect the LCD to an LP booster made on perfboard
     
    Many thanks to RobG for his assistance (see here for more information)
     


     
    Source is attached. This used every pin on the 2553, including XIN/XOUT. I have another of these for another project - I'll need to add an I/O expander to reduce the pin count.
     
    I'll post some pictures of the inside later
    EtchASketch_V2.zip
×
×
  • Create New...