Jump to content
43oh

Rickta59

Members
  • Content Count

    1,135
  • Joined

  • Last visited

  • Days Won

    71

Reputation Activity

  1. Like
    Rickta59 reacted to oPossum in Launchpad video oscilloscope   
    15.7 ksps WOW!
    16.6 ms sweep Amazing!
    Special limited time offer - only $4.30!
    Order now. Operators are standing by.
     


     

    .cdecls C, LIST, "msp430g2231.h" .text .global _main .bss sync_state, 2 .bss sync_lines, 2 .bss video_state, 2 .bss vid_line, 2 _main ; mov #WDTPW | WDTHOLD, &WDTCTL ; No watchdog ; mov #XT2OFF + 15, &BCSCTL1 ; DCO 16 Mhz mov #0x86, &DCOCTL ; ; mov #0x0280, SP ; Stack pointer ; mov.b #0xF0, &P1DIR ; I/O assignment mov.b #0x50, &P1SEL ; Enable Timer A output, SMCLK output clr.b &P1REN ; clr.b &P1OUT ; ; mov #0x0002, &ADC10AE0 ; Analog in on P1.1 (A1) mov #0x1000, &ADC10CTL1 ; Select A1 ; Configure ADC mov #ADC10SHT_0 | ADC10SR | ADC10ON | ENC, &ADC10CTL0 ; call #video_init ; Begin video ; jmp $ ; ; video_init ; --- Initialize Video Generation --- clr &sync_state ; Init state machine mov #1, sync_lines ; clr &video_state ; mov #1016, &TACCR0 ; Setup Timer A period for 63.5 us mov #75, &TACCR1 ; Setup Timer A compare for video sync mov #0x0210, &TACTL ; Timer A config: SMCLK, count up mov #0x0060, &TACCTL1 ; Setup Timer A set/reset output mode bis #0x0010, &TACCTL0 ; Enable PWM interupt eint ; Enable interupts ret ; ; video_isr ; --- Video ISR --- dec &sync_lines ; Decrement sync lines jne vid_state ; Skip sync if not zero... add &sync_state, PC ; Jump to sync handler... ; - Field 1/3 jmp vid_eq ; Pre Equalizing jmp vid_vsync ; Vertical Sync jmp vid_eq ; Post Equalizing jmp vid_vbi ; VBI jmp vid_active ; Active Video jmp vid_half ; Video half line ; - Field 2/4 jmp vid_eq ; Pre Equalizing jmp vid_vsync ; Vertical Sync jmp vid_eq ; Post Equalizing jmp vid_half ; Video half line jmp vid_vbi ; VBI jmp vid_active ; Active Video clr &sync_state ; Reset sync state ;jmp vid_eq ; Same as first state ; vid_eq ; Equalizing pulses - 6 half lines mov #508, &TACCR0 ; Half line mov #38, &TACCR1 ; Equalizing pulse duration mov #6, &sync_lines ; 6 half lines clr &video_state ; No video generation during sync incd &sync_state ; Next state reti ; ; vid_vsync ; Vertical sync - 6 half lines mov #508 - 75, &TACCR1 ; Sync pulse duration mov #6, &sync_lines ; 6 half lines incd &sync_state ; Next state reti ; ; vid_half ; Video half line - 1 half line mov #508, &TACCR0 ; Half line mov #75, &TACCR1 ; Sync pulse duration mov #1, &sync_lines ; 1 half line incd &sync_state ; Next state clr &video_state ; No video generation during half line and sync reti ; ; vid_vbi ; Vertical blanking interval - 11 lines mov #1016, &TACCR0 ; Full line mov #75, &TACCR1 ; Sync pulse duration mov #11, &sync_lines ; 11 lines incd &sync_state ; Next state reti ; ; vid_active ; Active video - 242 lines mov #242, &sync_lines ; 242 lines incd &sync_state ; Next state mov #2, &video_state ; Generate video clr &vid_line ; Clear video line count jmp vid_field ; Generate video... ; vid_blank_9 ; 9 blank lines mov #9, &sync_lines ; incd &sync_state ; clr &video_state ; reti ; ; vid_state ; -- Active Video Generation add &video_state, PC ; reti ; No active video ;jmp vid_field ; Field ; vid_field ; push R12 ; ; mov &TAR, R12 ; cmp #160, R12 ; jlo $ - 8 ; and #7, R12 ; rla R12 ; add R12, PC ; nop ; nop ; nop ; nop ; nop ; nop ; nop ; ; mov &ADC10MEM, R12 ; Get ADC results bis #ADC10SC, &ADC10CTL0 ; Start new conversion ; cmp #750, R12 ; Limit upper ADC value jlo inrange ; mov #750 - 2, R12 ; ; inrange sub #4, R12 ; Subtract four w/ four cycles per iteration nop ; jc $ - 4 ; inv R12 ; Negate the remainder rla R12 ; Multiply by two add R12, PC ; One cycle granularity computed jump nop ; nop ; nop ; ; bis.b #0x80, &P1OUT ; bic.b #0x80, &P1OUT ; ; pop R12 ; ; reti ; ; ; Interrupt Vectors .sect ".reset" ; .short _main ; .sect ".int09" ; TACCR0 CCIFG .short video_isr ; ; .end ;
  2. Like
    Rickta59 reacted to gordon in Makefile for MSPGCC   
    Rickta59 says this might be of interest to others, so here's the Makefile I've been using for MSPGCC.
     

    TARGETMCU ?= msp430g2211 CROSS := msp430- CC := $(CROSS)gcc CXX := $(CROSS)g++ OBJDUMP := $(CROSS)objdump SIZE := $(CROSS)size LD := $(CC) MSPDEBUG := mspdebug LDFLAGS := -mmcu=$(TARGETMCU) CFLAGS := -Os -Wall -W -Wextra -Werror -g -mmcu=$(TARGETMCU) ifneq ($(WITH_CXX),) CC := $(CXX) LD := $(CC) endif ifneq ($(DEBUG),) ifeq ($(WITH_CXX),) CFLAGS += -Wstrict-prototypes -Wmissing-prototypes -Wbad-function-cast CFLAGS += -Werror-implicit-function-declaration -Wdeclaration-after-statement CFLAGS += -Wnested-externs -Wold-style-definition CFLAGS += -finline-functions endif CFLAGS += -Wmissing-declarations -Winit-self -Winline -Wredundant-decls CFLAGS += -Wshadow -Wpointer-arith -Wcast-qual -Wsign-compare -Wformat=2 CFLAGS += -Wfloat-equal -Wmissing-field-initializers CFLAGS += -Wmissing-include-dirs -Wswitch-default -Wpacked CFLAGS += -Wpacked -Wlarger-than-65500 -Wunknown-pragmas CFLAGS += -Wmissing-format-attribute -Wmissing-noreturn CFLAGS += -Wstrict-aliasing=2 -Wswitch-enum -Wundef -Wunreachable-code CFLAGS += -Wunsafe-loop-optimizations -Wwrite-strings -Wcast-align CFLAGS += -Wformat-nonliteral -Wformat-security -Waggregate-return CFLAGS += -fno-common -Wp,-D_FORTIFY_SOURCE=2 endif SRCS := main.c PROG := $(firstword $(SRCS:.c=)) OBJS := $(SRCS:.c=.o) all: $(PROG).elf $(PROG).lst $(PROG).elf: $(OBJS) $(LD) $(LDFLAGS) -o $(PROG).elf $(OBJS) %.o: %.c $(CC) $(CFLAGS) -c $< %.lst: %.elf $(OBJDUMP) -DS $< > $@ $(SIZE) $< clean: -rm -f $(PROG).elf $(PROG).lst $(OBJS) install: $(PROG).elf $(MSPDEBUG) -n rf2500 "prog $(PROG).elf"
     
    I don't know what half of the CFLAGs mean anymore (some of them most likely don't even have any real meaning in the MSP430 context), I have collected them during the years, the result is considerably anal about code quality, though.
     
    roxfan notes,
     
    Well, I got used to objdump's output, that's about it.
     
    It's GNU make, don't even try with others, really. Also don't forget to expand spaces to tabs.
  3. Like
    Rickta59 reacted to oPossum in Game of Life with G2211   
    // main.c #include "msp430g2211.h" #include "string.h" void video_init(void); unsigned pix[14], nxt[14]; unsigned get_pix(int x, int y) { if(x < 0 || x > 15 || y < 0 || y > 13) return 0; return (pix[y] >> x) & 1; } void main(void) { int x, y, n; WDTCTL = WDTPW + WDTHOLD; // No watchdog BCSCTL1 = XT2OFF + 15; // DCO 16 Mhz DCOCTL = 0x86; // // P1DIR = 0xF2; // I/O assignment P1REN = 0x0D; // Pull up resistor P1OUT = 0x0F; // P1SEL = 0x50; // Enable Timer A output, SMCLK output video_init(); // Begin video generation // Initial GOL field pix[0] = pix[2] = pix[4] = pix[6] = pix[8] = pix[10] = pix[12] = 0x5555; pix[1] = pix[3] = pix[5] = pix[7] = pix[9] = pix[11] = pix[13] = 0xAAAA; pix[0] = 0x0000; pix[1] = 0x000E; pix[2] = 0x0000; pix[3] = 0; memcpy(nxt, pix, sizeof(nxt)); for(; { for(y = 0; y < 14; ++y) { for(x = 0; x < 16; ++x) { n = get_pix(x - 1, y - 1) + get_pix(x , y - 1) + get_pix(x + 1, y - 1) + get_pix(x - 1, y ) + /* me */ get_pix(x + 1, y ) + get_pix(x - 1, y + 1) + get_pix(x , y + 1) + get_pix(x + 1, y + 1); if(get_pix(x, y)) { if(n < 2 || n > 3) nxt[y] &= ~(1 << x); } else { if(n == 3) nxt[y] |= (1 << x); } } } __delay_cycles(5000000); memcpy(pix, nxt, sizeof(pix)); } }

    ; video.asm .cdecls C, LIST, "msp430g2211.h" .text .global video_init .global pix .bss sync_state, 2 .bss sync_lines, 2 .bss video_state, 2 .bss vid_line, 2 video_init ; --- Initialize Video Generation --- clr &sync_state ; Init state machine mov #1, sync_lines ; clr &video_state ; mov #1016, &TACCR0 ; Setup Timer A period for 63.5 us mov #75, &TACCR1 ; Setup Timer A compare for video sync mov #0x0210, &TACTL ; Timer A config: SMCLK, count up mov #0x0060, &TACCTL1 ; Setup Timer A set/reset output mode bis #0x0010, &TACCTL0 ; Enable PWM interupt eint ; Enable interupts ret ; ; video_isr ; --- Video ISR --- dec &sync_lines ; Decrement sync lines jne vid_state ; Skip sync if not zero... add &sync_state, PC ; Jump to sync handler... ; - Field 1/3 jmp vid_eq ; Pre Equalizing jmp vid_vsync ; Vertical Sync jmp vid_eq ; Post Equalizing jmp vid_vbi ; VBI jmp vid_blank_9 ; 9 blank lines jmp vid_active ; Active Video jmp vid_blank_9 ; 9 blank lines jmp vid_half ; Video half line ; - Field 2/4 jmp vid_eq ; Pre Equalizing jmp vid_vsync ; Vertical Sync jmp vid_eq ; Post Equalizing jmp vid_half ; Video half line jmp vid_vbi ; VBI jmp vid_blank_9 ; 9 blank lines jmp vid_active ; Active Video jmp vid_blank_9l ; 9 blank lines vid_state ; -- Active Video Generation add &video_state, PC ; reti ; No active video jmp vid_field ; Field ; vid_eq ; Equalizing pulses - 6 half lines mov #508, &TACCR0 ; Half line mov #38, &TACCR1 ; Equalizing pulse duration mov #6, &sync_lines ; 6 half lines clr &video_state ; No video generation during sync incd &sync_state ; Next state reti ; ; vid_vsync ; Vertical sync - 6 half lines mov #508 - 75, &TACCR1 ; Sync pulse duration mov #6, &sync_lines ; 6 half lines incd &sync_state ; Next state reti ; ; vid_half ; Video half line - 1 half line mov #508, &TACCR0 ; Half line mov #75, &TACCR1 ; Sync pulse duration mov #1, &sync_lines ; 1 half line incd &sync_state ; Next state clr &video_state ; No video generation during half line and sync reti ; ; vid_vbi ; Vertical blanking interval - 11 lines mov #1016, &TACCR0 ; Full line mov #75, &TACCR1 ; Sync pulse duration mov #11, &sync_lines ; 11 lines incd &sync_state ; Next state reti ; ; vid_active ; Active video - 224 lines mov #224, &sync_lines ; 224 lines incd &sync_state ; Next state mov #2, &video_state ; Genearte video clr &vid_line ; Clear video line count jmp vid_field ; Generate video... ; vid_blank_9 ; 9 blank lines mov #9, &sync_lines ; incd &sync_state ; clr &video_state ; reti ; ; vid_blank_9l ; 9 blank lines (last in field) mov #9, &sync_lines ; clr &sync_state ; clr &video_state ; reti ; ; vid_field ; push R10 ; push R12 ; push R14 ; ; mov &TAR, R10 ; cmp #176, R10 ; jlo $ - 8 ; and #7, R10 ; rla R10 ; add R10, PC ; nop ; nop ; nop ; nop ; nop ; nop ; nop ; ; mov &vid_line, R12 ; inc &vid_line ; rra R12 ; rra R12 ; rra R12 ; ;bic #1, R12 ; add #pix, R12 ; mov @R12, R12 ; mov #16, R14 ; pixloop rlc R12 ; jc pixon ; bic.b #0x80, &P1OUT ; jmp nexpix ; pixon bis.b #0x80, &P1OUT ; jmp nexpix ; nexpix mov #10, R10 ; dec R10 ; jne $ - 2 ; dec R14 ; jne pixloop ; nop ; nop ; nop ; bic.b #0x80, &P1OUT ; ; pop R14 ; pop R12 ; pop R10 ; ; reti ; ; ; Interrupt Vectors .sect ".int09" ; TACCR0 CCIFG .short video_isr ; ; .end ;

    I can explain the video code if anyone is interested. It is very flexible and does proper interlaced video and sync (equalization and serration).
  4. Like
    Rickta59 reacted to oPossum in MIDI implementation   
    Here is an extended version of the Fraunchpad synth MIDI parser. This handles all MIDI messages. It uses tables and a state machine for decode and dispatch. A channel bitmask is used to allow one or more channels to be handled.
     

    // MIDI message handler function typedef typedef void(*pfnMIDI)(unsigned cmd, unsigned d1, unsigned d2); // Dummy function for unhandled and undefined MIDI messages static void midiNone(unsigned cmd, unsigned d1, unsigned d2) {} static void midiNoteOff(unsigned cmd, unsigned d1, unsigned d2) { } static void midiNoteOn(unsigned cmd, unsigned d1, unsigned d2) { if(d2 == 0) { midiNoteOff(cmd, d1, 0); return; } } static const pfnMIDI mf[24] = { // --- Array of MIDI function pointers // - System Common midiNone, // F0 Sysex begin midiNone, // F1 Quarter frame midiNone, // F2 Song position midiNone, // F3 Song select midiNone, // F4 Undefined midiNone, // F5 Undefined midiNone, // F6 Tune request midiNone, // F7 Sysex end // - Voice midiNoteOff, // 8x Note off midiNoteOn, // 9x Note on midiNone, // Ax Aftertouch midiNone, // Bx Controller midiNone, // Cx Program change midiNone, // Dx Channel aftertouch midiNone, // Ex Pitch bend midiNone, // Sysex data (system common) // - System Real Time midiNone, // F8 Clock midiNone, // F9 Tick midiNone, // FA Start midiNone, // FB Continue midiNone, // FC Stop midiNone, // FD Undefined midiNone, // FE Active sense midiNone // FF Reset }; static void midi(unsigned c) // --- MIDI Parser --- { // // Initial state for message // F0 F1 F2 F3 F3 F5 F6 F7 8x 9x Ax Bx Cx Dx Ex static const unsigned mis[15] = { 4, 5, 6, 5, 0, 0, 0, 0, 2, 2, 2, 2, 1, 1, 2 }; static unsigned state = 0; // static unsigned rs = 0; // static unsigned d1 = 0; // static unsigned channel; // static unsigned channel_mask = 0x0001; // Channel(s) to respond to // if(c & 0x80) { // First octet of sequence channel = c & 0x0F; // Extract channel from first octet if(c <= 0xEF) { // --- Handle Voice messages 0x80 -> 0xEF --- if(channel_mask & (1 << channel)) { // Check if on our channel(s) rs = c; // Save first octet (running status) state = mis[rs >> 4]; // Set initial state for message type } else { // state = 0; // Not for us, discard } // } else if(c <= 0xF7) { // --- Handle System Common messages 0xF0 -> 0xF7 --- rs = c; // Save command octet state = mis[channel]; // Set inital state for message type if(state < 5) // Sysex (state 4) is handled immediately and has state change mf[channel](c, 0, 0); // Handle one octet messages immediately } else { // mf[channel + 8](c, 0, 0); // --- Handle System Real Time messages 0xF8 -> 0xFF (one octet) --- channel = rs & 0x0F; // Do not reset running status, or change state } // } else { // --- State machine for second and following octets --- switch(state) { // case 0: // - Discard break; // case 1: // - Second and final octet (voice messages) mf[rs >> 4](rs, c, 0); // break; // case 3: // - Third and final octet (voice messages) mf[rs >> 4](rs, d1, c); // state = 2; // break; // case 5: // - Second and final octet (system common message) mf[channel](rs, c, 0); // state = 0; // No running status for system messages break; // case 7: // - Third and final octet (system common message) mf[channel](rs, d1, c); // state = 0; // No running status for system messages break; // case 4: // - Sysex data mf[15](rs, c, 0); // break; // case 2: // - Second octet of three case 6: // d1 = c; // ++state; // break; // } // } // }
     
    Compact version of the parser without all those silly comments. (code is the same, just reformatted)

    void parse_midi(unsigned c) { static const unsigned mis[15] = { 4, 5, 6, 5, 0, 0, 0, 0, 2, 2, 2, 2, 1, 1, 2 }; static unsigned state = 0, rs, d1, channel; static unsigned channel_mask = 0x0001; if(c & 0x80) { channel = c & 0x0F; if(c <= 0xEF) { if(channel_mask & (1 << channel)) { rs = c; state = mis[rs >> 4]; } else state = 0; } else if(c <= 0xF7) { rs = c; state = mis[channel]; if(state < 5) mf[channel](c, 0, 0); } else { mf[channel + 8](c, 0, 0); channel = rs & 0x0F; } } else switch(state) { case 1: mf[rs >> 4](rs, c, 0); break; case 3: mf[rs >> 4](rs, d1, c); state = 2; break; case 5: mf[channel](rs, c, 0); state = 0; break; case 7: mf[channel](rs, d1, c); state = 0; break; case 4: mf[15](rs, c, 0); break; case 2: case 6: d1 = c; ++state; break; } }
  5. Like
    Rickta59 reacted to oPossum in Fraunchpad poly synth   
    16 voices of 16 bit x 257 interpolated wavetable - derived from this code for the Launchpad.
    PWM output, but could easily be adapted to use IIC DAC.
     
    This is preliminary and eXperimental. The CPU core seems to be running slower than it should and I don't yet know why. Right now it is limited to 9 voices. The 9600 bps UART on the dev board was used for this demo, but standard MIDI can also be used - just change the bit rate divisor and wire up the usual opto circuit for MIDI.
     
    This is part of a larger project I am working on.
     


     

    //main.c #include "msp430fr5739.h" void synth_init(void); void set_note(int, int, int); static int assign[16]; void note_on(int n, int v) { int i; for(i = 0; i < 16; ++i) { if(assign[i] == -1) { assign[i] = n; set_note(i, n, v); break; } } } void note_off(int n) { int i; for(i = 0; i < 16; ++i) { if(assign[i] == n) { assign[i] = -1; set_note(i, -1, 0); break; } } } void midi_ex(unsigned a, unsigned b, unsigned c) { ++PJOUT; switch(a & 0xF0) { case 0x90: // Note on if(c) { note_on(b, c); break; } // fall thru case 0x80: // Note off note_off(; break; /* case 0xA0: // Note aftertouch break; case 0xB0: // Controller break; case 0xC0: // Program change break; case 0xD0: // Channel aftertouch break; case 0xE0: // Pitch bend break; case 0xF0: // Sysex / Meta break; */ } } void midi(unsigned c) { static const unsigned ps[8] = { 2, 2, 2, 2, 1, 1, 2, 4 }; static unsigned state = 0; static unsigned rs = 0; static unsigned d1 = 0; if(c & 0x80) { // First octect of sequence rs = c; state = ps[(rs >> 4) & 7]; } else { switch(state) { case 0: // Discard break; case 1: // Second and final octet midi_ex(rs, c, 0); break; case 2: // Second octet of three d1 = c; ++state; break; case 3: // Third and final octet midi_ex(rs, d1, c); state = 2; break; //case 4: // Sysex data // break; } } } void main(void) { unsigned n; WDTCTL = WDTPW + WDTHOLD; CSCTL0 = 0xA500; // Unlock clock registers CSCTL1 = DCORSEL | DCOFSEL1 | DCOFSEL0; // 24 MHz CSCTL2 = 0x0333; // Use DCO clock for ACLK, SMCLK and MCLK CSCTL3 = 0x0000; // Set all clock dividers to 1 //CSCTL4 = //CSCTL5 = P1DIR = 0x01; // PWM audio out P1REN = 0x00; // P1OUT = 0x00; // P1SEL0 = 0x01; // Enable Timer A output P1SEL1 = 0x00; // P2DIR = 0x00; // P2REN = 0x00; // P2OUT = 0x00; // P2SEL0 = 0x00; // P2SEL1 = 0x03; // Enable UART UCA0 P3DIR = 0x10; // P3REN = 0x00; // P3OUT = 0x00; // P3SEL0 = 0x10; // SMCLK output P3SEL1 = 0x10; // SMCLK output P4DIR = 0x00; // P4REN = 0x00; // P4OUT = 0x00; // P4SEL0 = 0x00; // P4SEL1 = 0x00; // PJDIR = 0x0F; // 4 LEDs PJREN = 0x00; // PJOUT = 0x0F; // PJSEL0 = 0x00; // PJSEL1 = 0x00; // UCA0CTLW0 = 0x0080; // UCA0BRW = 24000000 / 9600; // Fraunchpad UART //UCA0BRW = 24000000 / 31250; // Standard MIDI bit rate synth_init(); //set_note(0, 69, 700); // 440 Hz test for(n = 0; n < 16; ++n) assign[n] = -1; for(; { if(UCA0IFG & 1) { UCA0IFG &= ~1; n = UCA0RXBUF; midi(n); } } }
     

    ;synth.asm .cdecls C, LIST, "msp430fr5739.h" smplrt .equ 32000 ; Sample rate .text .global set_tick .global get_tick .global synth_init .global set_note .bss tick, 2 .bss pwm_out, 2 .bss phase_inc, 6 * 16 ; Phase increment LSW/MSW (from note table) ; Level .bss phase_acc, 4 * 16 ; Phase accumulator LSW/MSW set_tick mov R12, &tick reta get_tick mov &tick, R12 reta synth_init mov #0x0210, &TA0CTL ; Timer A config: SMCLK, count up mov #750, &TA0CCR0 ; Setup Timer A period for 32000 sps mov #375, &TA0CCR1 ; Setup Timer A compare mov #0x00E0, &TA0CCTL1 ; Setup Timer A reset/set output mode ; mov #phase_inc, R12 ; Clear all phase inc and accum mov #5 * 16, R14 ; Word count clr 0(R12) ; Clear word incd R12 ; Next word dec R14 ; Dec word count jne $ - 8 ; Loop until all words done... ; eint ; Enable interupts bis #0x0010, &TA0CCTL0 ; Enable PWM interupt ; reta ; ; synth_isr ; mov &pwm_out, &TA0CCR1 ; Output sample ; push R4 ; Wavetable pointer push R5 ; Phase increment / level pointer push R6 ; Phase accumulator pointer push R7 ; Voice count push R8 ; Wave sample pointer / next sample push R9 ; Wave sample push R10 ; Voice mix accumulator MSW push R11 ; Voice mix accumulator LSW ; mov #sine, R4 ; Get wavetable pointer mov #phase_inc, R5 ; Setup phase increment pointer mov #phase_acc, R6 ; Setup phase accumulator pointer mov #16, R7 ; Setup voice count mov #9, R7 ; clr R10 ; Clear voice mix clr R11 ; voice_loop ; mov @R6+, &MPYS32L ; Get phase acc LSW (fraction) to multiplier clr &MPYS32H ; mov @R6+, R8 ; Get phase acc MSW (wave table index) mov.b R8, R8 ; Clear MSB (use mask for smaller / larger tables) add R4, R8 ; Add wavetable pointer mov @R8+, R9 ; Get wave sample mov @R8, R8 ; Get next wave sample sub R9, R8 ; Calc delta mov R8, &OP2L ; Multiply by delta subc R8, R8 ; Sign extend delta mov R8, &OP2H ; add @R5+, -4(R6) ; Update phase acc addc @R5+, -2(R6) ; add &RES1, R9 ; Add interpolation to sample mov R9, &MPYS ; Multiply by voice level mov @R5+, &OP2L ; add &RES0, R11 ; Update mix addc &RES1, R10 ; dec R7 ; Dec voice count jne voice_loop ; Next voice... ; add #375, R10 ; Bias to center of PWM range mov R10, &pwm_out ; ; dec &tick ; jc $ + 6 ; clr &tick ; ; pop R11 ; pop R10 ; pop R9 ; pop R8 ; pop R7 ; pop R6 ; pop R5 ; pop R4 ; reti ; ; set_note ; push R14 ; Save level mov R12, R14 ; Voice * 6 add R14, R12 ; (+1 = *2) add R14, R12 ; (+1 = *3) rla R12 ; (*2 = *6) add #phase_inc, R12 ; Add phase inc pointer cmp #128, R13 ; Out of range note values are note off jhs note_off ; clr R14 ; Clear octave count tst_note ; cmp #116, R13 ; Within note table? jge get_pi ; Yes... inc R14 ; Inc octave count add #12, R13 ; Add octave to note jmp tst_note ; Check again... get_pi ; Get phase increment sub #116, R13 ; Adjust for first note in table rla R13 ; MIDI note * 4 rla R13 ; add #notes, R13 ; Add note table pointer mov @R13+, R15 ; Get LSW mov @R13, R13 ; Get MSW tst R14 ; Shifting required? jeq set_phase ; No... shift_phase ; rra R13 ; Shift phase inc rrc R15 ; dec R14 ; Dec octave count jne shift_phase ; Repeat until zero... set_phase ; mov R15, 0(R12) ; Set phase inc mov R13, 2(R12) ; pop 4(R12) ; Set voice level reta ; Return ; note_off ; incd SP ; Discard level clr 0(R12) ; Clear phase inc clr 2(R12) ; .if 0 ; Note: Abrupt return to zero causes poping clr 4(R12) ; Clear level add #phase_acc - phase_inc, R12 ; Phase accum pointer clr 0(R12) ; Clear phase accum clr 2(R12) ; .endif ; reta ; Return ; ; notes ; MIDI Note Frequency .if smplrt == 32000 ; 32000 sps .long 3483828 ; 116 G#8 6644.87457275391 .long 3690988 ; 117 A8 7040.00091552734 .long 3910465 ; 118 A#8 7458.62007141113 .long 4142993 ; 119 B8 7902.13203430176 .long 4389349 ; 120 C9 8372.01881408691 .long 4650353 ; 121 C#9 8869.84443664551 .long 4926877 ; 122 D9 9397.27210998535 .long 5219845 ; 123 D#9 9956.06422424316 .long 5530233 ; 124 E9 10548.0823516846 .long 5859077 ; 125 F9 11175.3025054932 .long 6207476 ; 126 F#9 11839.8208618164 .long 6576592 ; 127 G9 12543.8537597656 .endif ; ; .if smplrt == 48000 ; 48000 sps .long 2322552 ; 116 G#8 6644.87457275391 .long 2460658 ; 117 A8 7039.99900817871 .long 2606977 ; 118 A#8 7458.62102508545 .long 2761996 ; 119 B8 7902.13394165039 .long 2926232 ; 120 C9 8372.01690673828 .long 3100235 ; 121 C#9 8869.84348297119 .long 3284585 ; 122 D9 9397.27306365967 .long 3479896 ; 123 D#9 9956.06231689453 .long 3686822 ; 124 E9 10548.0823516846 .long 3906052 ; 125 F9 11175.3044128418 .long 4138318 ; 126 F#9 11839.8227691650 .long 4384395 ; 127 G9 12543.8547134399 .endif ; sine .int 0 .int 804 .int 1608 .int 2410 .int 3212 .int 4011 .int 4808 .int 5602 .int 6393 .int 7179 .int 7962 .int 8739 .int 9512 .int 10278 .int 11039 .int 11793 .int 12539 .int 13279 .int 14010 .int 14732 .int 15446 .int 16151 .int 16846 .int 17530 .int 18204 .int 18868 .int 19519 .int 20159 .int 20787 .int 21403 .int 22005 .int 22594 .int 23170 .int 23731 .int 24279 .int 24811 .int 25329 .int 25832 .int 26319 .int 26790 .int 27245 .int 27683 .int 28105 .int 28510 .int 28898 .int 29268 .int 29621 .int 29956 .int 30273 .int 30571 .int 30852 .int 31113 .int 31356 .int 31580 .int 31785 .int 31971 .int 32137 .int 32285 .int 32412 .int 32521 .int 32609 .int 32678 .int 32728 .int 32757 .int 32767 .int 32757 .int 32728 .int 32678 .int 32609 .int 32521 .int 32412 .int 32285 .int 32137 .int 31971 .int 31785 .int 31580 .int 31356 .int 31113 .int 30852 .int 30571 .int 30273 .int 29956 .int 29621 .int 29268 .int 28898 .int 28510 .int 28105 .int 27683 .int 27245 .int 26790 .int 26319 .int 25832 .int 25329 .int 24811 .int 24279 .int 23731 .int 23170 .int 22594 .int 22005 .int 21403 .int 20787 .int 20159 .int 19519 .int 18868 .int 18204 .int 17530 .int 16846 .int 16151 .int 15446 .int 14732 .int 14010 .int 13279 .int 12539 .int 11793 .int 11039 .int 10278 .int 9512 .int 8739 .int 7962 .int 7179 .int 6393 .int 5602 .int 4808 .int 4011 .int 3212 .int 2410 .int 1608 .int 804 .int 0 .int -804 .int -1608 .int -2410 .int -3212 .int -4011 .int -4808 .int -5602 .int -6393 .int -7179 .int -7962 .int -8739 .int -9512 .int -10278 .int -11039 .int -11793 .int -12539 .int -13279 .int -14010 .int -14732 .int -15446 .int -16151 .int -16846 .int -17530 .int -18204 .int -18868 .int -19519 .int -20159 .int -20787 .int -21403 .int -22005 .int -22594 .int -23170 .int -23731 .int -24279 .int -24811 .int -25329 .int -25832 .int -26319 .int -26790 .int -27245 .int -27683 .int -28105 .int -28510 .int -28898 .int -29268 .int -29621 .int -29956 .int -30273 .int -30571 .int -30852 .int -31113 .int -31356 .int -31580 .int -31785 .int -31971 .int -32137 .int -32285 .int -32412 .int -32521 .int -32609 .int -32678 .int -32728 .int -32757 .int -32767 .int -32757 .int -32728 .int -32678 .int -32609 .int -32521 .int -32412 .int -32285 .int -32137 .int -31971 .int -31785 .int -31580 .int -31356 .int -31113 .int -30852 .int -30571 .int -30273 .int -29956 .int -29621 .int -29268 .int -28898 .int -28510 .int -28105 .int -27683 .int -27245 .int -26790 .int -26319 .int -25832 .int -25329 .int -24811 .int -24279 .int -23731 .int -23170 .int -22594 .int -22005 .int -21403 .int -20787 .int -20159 .int -19519 .int -18868 .int -18204 .int -17530 .int -16846 .int -16151 .int -15446 .int -14732 .int -14010 .int -13279 .int -12539 .int -11793 .int -11039 .int -10278 .int -9512 .int -8739 .int -7962 .int -7179 .int -6393 .int -5602 .int -4808 .int -4011 .int -3212 .int -2410 .int -1608 .int -804 .int 0 ; Interrupt Vectors .sect ".int53" ; TA0CCR0 CCIFG0 .short synth_isr ; ; .end ;
  6. Like
    Rickta59 reacted to rockets4kids in Using the Launchpad with a Breadboard   
    This has been mentioned a few times before but as not too many people know about it I thought I would bring it up again with my particular spin on things.
     
    It is a little known fact that the Launchpad can easily program external chips. In fact, I only programmed a chip in the Launchpad socket itself just a few times before connecting it to an external breadboard.
     
    A picture is worth a thousand words, so here are some of my Launchpad-breadboard setup:
     
    http://imgur.com/a/UA46s#Qmjp7
     

    Very high resolution versions of the image are available through the "Image Options" menu.
     
    Physically, the breadboard is taped (double-sided foam tape) to a piece of scrap plastic. The Launchpad is held in place with a rubber band -- the ones that hold broccoli are perfect.
     
    I didn't have any "proper" connectors, so I simply trimmed (cut and sanded) one of the 10-pin female connectors that comes with the Launchpad. I also didn't have any heat-shrink small enough, so I just "potted" the solder connections with epoxy. It's not pretty, but it works just fine.
     
    To understand what is going on here, it is best to look at the schematic and PCB layout that is included in the Launchpad User's Guide:
     
    http://focus.ti.com/lit/ug/slau318/slau318.pdf
     
    It is important to note that the "Emulation" side is completely separate from the "EXP-MSP430G2" or "target" side. You can actually (physically) cut the board along the dashed line if you want. Aside from power and ground, all of the signals cross the dashed line via the jumper pins. If you remove the jumper pins, you have access to all of the signals required to program an external chip.
     
    It may not be clear in the picture, but the jumpers are hanging off one pin on the target side -- that is the easiest way to keep from losing them when the external programming header is connected.
     
    Many people also seem to be confused about the minimal support circuitry required for the MSP430, so that is definitely worth going over. The schematic in slau318 is nicely split on multiple pages to show G2/target side of things on a single page. This is essentially what you will be building on the breadboard.
     
    Obviously the chip requires power and ground, and these are provided via the Launchpad. The power supply must be properly decoupled for proper operation. This involves a 10 uF cap (electrolytic or tantalum) somewhere on the breadboard and a 0.1 uF (a cheap ceramic is just fine) as close to the MSP430 as possible.
     
    The RST line must be held high with a 47 k resistor. If you wish to reset the chip, just apply a jumper from RST to ground. You could use a switch, but a simple wire works just fine when needed.
     
    I have a watch crystal on XIN-XOUT, but this is not necessary. My xtal requires two 22 pF caps for proper loading, but I have not used these, instead enabling the internal 14 pF caps on the MSP430. The xtal seems to oscillate just fine with the improper loading, but I am certain that it effects the frequency. I don't have a frequency counter, so I don't know how far off it really is. The important thing is that oscillator does not seem to fault even when I touch it with the case ungrounded.
     
    If you don't want to use an xtal, you can use the pins as GPIOs.
     
    It is important to note that the chip is programmed over the TEST/RST lines, *not* the TX/RX serial lines. If you do not need serial communication, TX/RX do not need to be connected to the launchpad, and the pins can be used as GPIOs. Even more important to note is that the TX/RX lines used by the chips with a hardware UART (The 2xx3 chips) are *reversed* from the pins used for software serial! The breadboard in the photograph is populated with a 2553, so TX from the 2553 goes to RX on the jumper block and vice-versa.
     
    The only real "application circuit" here is the LED/resistor on P1.0 -- which happens to match LED1 on the Launchpad.
     
    As you can see, this leaves quite a fair bit of board space to experiment with, even with a small 400 pin breadboard.
     
    These little breadboards can be had for just a little more than two bucks when you get 10 of them, and it's really nice to be able to leave multiple small circuits all wired up at the same time. It's also useful to wire up each board as a discrete function, just like a "shield" on an Arduino. For example, you can wire a 2x16 LCD display for 2-pin serial display, and then easily connect that among multiple other boards.
     
    Hopefully this will be helpful to others just getting started!
  7. Like
    Rickta59 got a reaction from zeke in FRAM Experimenter's Board coupon code 50% off   
  8. Like
    Rickta59 reacted to bluehash in FRAM Experimenter's Board coupon code 50% off   
    Just got this email from our TI representative:
    (Thanks TI!)
     
  9. Like
    Rickta59 got a reaction from bluehash in DTMF-Controlled Garage Door Opener [GDO]   
    First, let me say "Great Job"!
     
     
    I found this site today http://www.asciiflow.com
    might fit the bill for doing simple circuits like the TI examples
     
     
  10. Like
    Rickta59 got a reaction from xpg in DTMF-Controlled Garage Door Opener [GDO]   
    First, let me say "Great Job"!
     
     
    I found this site today http://www.asciiflow.com
    might fit the bill for doing simple circuits like the TI examples
     
     
  11. Like
    Rickta59 got a reaction from RobG in DTMF-Controlled Garage Door Opener [GDO]   
    First, let me say "Great Job"!
     
     
    I found this site today http://www.asciiflow.com
    might fit the bill for doing simple circuits like the TI examples
     
     
  12. Like
    Rickta59 reacted to V0JT4 in Slot Cars Lap Counter/Timer   
    Here is my first project with LaunchPad - Slot Cars Lap Counter/Timer. I wanted to build the lap counter for quite a long time, originally from BCD counter ICs and 7 segment LED display. Some time passed and my friend told me about LaunchPad, it looked like a great opportunity to start with MCUs and make some old ideas reality.


    Main idea was to use character LCD instead of 7seg LED as it gives you much more space to display stuff and I had one lying (from old computer connected to LPT with LCDSmartie). I used great RobG's project and slightly modified it to my needs. As I usually build only two lane circuits, I used custom characters feature of HD44780 to display large digits.

    Car is detected by magnetic Reed switch (extracted from old keyboard) placed under each lane. I needed to use capacitor parallel to switch, otherwise many false interrupts were generated (one car triggering both lanes,...). TimerA is used to track time with interrupt generated 100 times per second. Long and short button press is distinguish by WDT in timer mode with accumulator variable and threshold. Buzzer is connected to TimerA output 1 in PWM mode.

    The construction was fairly simple. I used hot melt glue to attach Reed switch under each lane. You just have to be very careful bending the Reed switch contacts, it's very fragile piece of glass and mine are maybe 30 years old, extracted from computer keyboard.

    Software implements 3 modes, standard N lap race, time attack limited by N laps and free practice with no time or lap limit. You can see it in action in video posted below. It's possible to pause/resume race (short press) and restart race (long press). Buzzer signals start, end and resume of race. To change race mode just hit reset button. I wasn't able to fit in 2K limit by 200B, so I had to use MSP430G2553 I received from great TI sample program. I think without large digits it would easily fit MSP430G2211, maybe even in 4 lane modification.



    EDIT: Good news everyone! I have a new code version, now with possibility to enable big digits or 4 lanes. Without big digits it fits in 2K FLASH devices supplied with LaunchPad in both 2 and 4 lanes modes. In 4 lanes mode buzzer needs to be placed on P2.6 (XIN).
    #include <msp430g2553.h> #include "lcd.h" //#define LANE_4 // uncomment to enable 4 lane mode #ifdef BIG_DIGITS // big digits enabled in lcd.h #undef LANE_4 // are incompatible with 4 lanes #endif // Type definition for simplicity typedef unsigned char u8; typedef char s8; typedef unsigned int u16; typedef int s16; // Pin allocation #define BUTTON BIT3 #define SENS0 BIT4 #define SENS1 BIT5 #define BUZZER BIT6 #ifdef LANE_4 #define SENS2 BIT6 #define SENS3 BIT7 #endif #define LONG_PRESS 10 // N x 30 ms #define MIN_LAP_TIME 100 // N x 1/100 s #ifdef LANE_4 // lane count adjustment #define LANES 4 static const u8 SENS[] = {SENS0, SENS1, SENS2, SENS3}; #else #define LANES 2 static const u8 SENS[] = {SENS0, SENS1}; #endif u8 hold = 0; // Long button press counter u8 lap[LANES]; // Lap number u16 time[LANES]; // Lap time in 1/100 s u16 best[LANES]; // Best Lap time u8 race; // Car did not finish race u8 raceLaps = 0; // Number of laps of race #ifdef BIG_DIGITS u8 bufferT[] = {0, 0, ' ', 0x07, 0x07}; // Number to display top part u8 bufferB[] = {0, 0, '.', 0x06, 0x06}; // Number to display bottom part #else u8 bufferT[] = {0, 0, '.', '0', '0'}; // Number to display #endif #define BEST_MARK 0x8000 // best updated flag, needs redraw #define LAP_MARK 0x80 // lap updated flag, needs redraw // Application states #define STATE_MAIN 0x00 #define STATE_SETUP1 0x10 #define STATE_SETUP2 0x20 #define STATE_READY 0x30 #define STATE_START 0x40 #define STATE_PAUSE 0x50 #define STATE_RACE 0x60 #define STATE_FINISH 0x70 #define STATE_END 0x80 #define WIN1_MASK 0x03 // Race result bits u8 state = STATE_MAIN; // Race modes #define MODE_RACE 0x01 // first to finish wins #define MODE_TIME 0x02 // best lap time wins #define MODE_PRAC 0x03 // infinite practice with best time tracking u8 mode = MODE_RACE; // Race initial screen #ifdef BIG_DIGITS static const char CScreen[] = {'L', ' ', 0x07, 0x07, ' ', 'T', ' ', 0x07, 0x07, ' ', 0x07, 0x07, ' ', 'B', ' ', '_', '_', ' ', '_', '_', 'P', ' ', 0x07, 0x07, ' ', 'M', ' ', 0x07, 0x07, ' ', 0x07, 0x07, ' ', 'S', ' ', '_', '_', ' ', '_', '_', 'A', ' ', 0x06, 0x06, ' ', 'I', ' ', 0x06, 0x06, '.', 0x06, 0x06, ' ', 'E', ' ', ' ', ' ', '.', ' ', ' ', 'S', ' ', 0x06, 0x06, ' ', 'E', ' ', 0x06, 0x06, '.', 0x06, 0x06, ' ', 'T', ' ', ' ', ' ', '.', ' ', ' '}; #else #ifdef LANE_4 static const char CScreen[] = {'L', ' ', '0', '0', ' ', 'T', ' ', '0', '0', '.', '0', '0', ' ', 'B', ' ', '-', '-', '.', '-', '-', 'P', ' ', '0', '0', ' ', 'M', ' ', '0', '0', '.', '0', '0', ' ', 'S', ' ', '-', '-', '.', '-', '-', 'A', ' ', '0', '0', ' ', 'I', ' ', '0', '0', ' ', '0', '0', ' ', 'E', ' ', '-', '-', '.', '-', '-', 'S', ' ', '0', '0', ' ', 'E', ' ', '0', '0', ' ', '0', '0', ' ', 'T', ' ', '-', '-', '.', '-', '-'}; #else static const char CScreen[] = {'L', ' ', '0', '0', ' ', 'T', ' ', '0', '0', '.', '0', '0', ' ', 'B', ' ', '-', '-', '.', '-', '-', 'P', ' ', ' ', ' ', ' ', 'M', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'S', ' ', ' ', ' ', ' ', ' ', ' ', 'A', ' ', '0', '0', ' ', 'I', ' ', '0', '0', '.', '0', '0', ' ', 'E', ' ', '-', '-', '.', '-', '-', 'S', ' ', ' ', ' ', ' ', 'E', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'T', ' ', ' ', ' ', ' ', ' ', ' '}; #endif /* LANE_4 */ #endif /* BIG_DIGITS */ void longDelay(void); void initData(void); void buttonShort(void); void buttonLong(void); void tostr(u16 i); void printL(u8 r, u8 c); void printT(u8 r, u8 c); void newLap(u8 id); // handles all race LCD updates to avoid char placement errors void main(void) { // try to set DCO to 1 MHz if (CALBC1_1MHZ != 0xFF || CALDCO_1MHZ != 0xFF) { BCSCTL1 = CALBC1_1MHZ; // Set range DCOCTL = CALDCO_1MHZ; // Set DCO step + modulation } // initialize peripheries // watchdog WDTCTL = WDTPW | WDTHOLD | WDTTMSEL | WDTCNTCL; // Stop+Clear+TimerMode WDT IE1 = WDTIE; // WDT IE // gpio P1 #ifdef LANE_4 P1OUT = SENS0 | SENS1 | SENS2 | SENS3; // pullup P1REN = SENS0 | SENS1 | SENS2 | SENS3; // internal resistor P1IES = BUTTON | SENS0 | SENS1 | SENS2 | SENS3; // Hi/lo edge #else P1OUT = SENS0 | SENS1; // pullup P1REN = SENS0 | SENS1; // internal resistor P1IES = BUTTON | SENS0 | SENS1; // Hi/lo edge #endif P1IFG = 0; // IFG cleared P1IE = BUTTON; // BUTTON interrupt enabled // timerA CCR0 = 9994 - 1; // 1/100s, DCO 1MHz calibration = 244x4096 TACTL = TASSEL_2 + MC_1; // SMCLK, upmode //buzzer #ifdef LANE_4 P2DIR = BUZZER; // P2.6 in 4 lane mode P2SEL = BUZZER; // BUZZER TimeA output #else P1DIR = BUZZER; // P1.6 in 4 lane mode P1SEL = BUZZER; // BUZZER TimeA output #endif CCTL1 = OUTMOD_7; // CCR1 reset/set CCR1 = 0; // Buzzer off // lcd lcdInit(); _enable_interrupts(); // global interupt enable // Setup initial screen lcdString("Select Mode: Time Attack ~ Lap Race Practice"); initData(); while (1) { u8 id; // print updated values for (id = 0; id < LANES; ++id) { if (P1IE & SENS[id]) { // hold after lap tostr(time[id]); // print time printT(id, 7); } if (best[id] & BEST_MARK) { best[id] &= ~BEST_MARK; tostr(best[id]); // print best printT(id, 15); } if (lap[id] & LAP_MARK) { lap[id] &= ~LAP_MARK; tostr(lap[id]); // print lap count printL(id, 2); } } if (state == STATE_READY) { // draw init race screen lcdCommand(LCD_SETDDRAMADDR); lcdDataArray(CScreen, 80); } if (state == STATE_START) { // Sound countdown CCR0 = 4000; // higher frequency for (id = 8; id > 1; id--) { // 3 short+1 long CCR1 ^= 2000; longDelay(); if (id & 1)longDelay(); } longDelay(); CCR1 = 0; CCR0 = 9994 - 1; // resume 1/100s state = STATE_RACE; CCTL0 = CCIE; // start time counting #ifdef LANE_4 P1IFG &= ~(SENS0 | SENS1 | SENS2 | SENS3); P1IE |= SENS0 | SENS1 | SENS2 | SENS3; #else P1IFG &= ~(SENS0 | SENS1); P1IE |= SENS0 | SENS1; #endif } // race ended if ((state & ~WIN1_MASK) == STATE_FINISH) { #ifdef BIG_DIGITS lcdJump((state & WIN1_MASK) << 1, 1); // mark winner on LCD #else lcdJump(state & WIN1_MASK, 1); // mark winner on LCD #endif lcdData(0xFF); CCR1 = 4997; // short beep longDelay(); CCR1 = 0; state = STATE_END; } } } // Delay ~0.2s void longDelay(void) { _delay_cycles(190000); } // Set initial values void initData(void) { u8 id; for (id = 0; id < LANES; ++id) { best[id] = 9999; lap[id] = 0; time[id] = 0; } #ifdef LANE_4 race = SENS0 | SENS1 | SENS2 | SENS3; #else race = SENS0 | SENS1; #endif } // Short button press void buttonShort(void) { switch (state) { case STATE_MAIN: lcdJump(mode, 0); lcdData(' '); switch (mode) { // change race mode case MODE_RACE: mode = MODE_TIME; break; case MODE_TIME: mode = MODE_PRAC; break; case MODE_PRAC: mode = MODE_RACE; break; default: break; } lcdJump(mode, 0); lcdData(0x7E); break; case STATE_SETUP1: raceLaps++; // increase 1st digit if (raceLaps == 10) // overflow raceLaps = 0; LPRINT: tostr(raceLaps); // update LCD #ifdef BIG_DIGITS printL(1, 10); #else printL(2, 10); #endif break; case STATE_SETUP2: raceLaps += 10; // increase 2nd digit if (raceLaps >= 100) // overflow raceLaps -= 100; goto LPRINT; //break; case STATE_RACE: // pause race state = STATE_PAUSE; CCTL0 = 0; #ifdef LANE_4 P1IE &= ~(SENS0 | SENS1 | SENS2 | SENS3); #else P1IE &= ~(SENS0 | SENS1); #endif break; case STATE_READY: // start race case STATE_PAUSE: // resume race state = STATE_START; break; default: break; } } // Long button press void buttonLong() { switch (state) { case STATE_MAIN: // confirm race mode if (mode == MODE_PRAC) { // start practice raceLaps = 127; goto CPRINT; } state = STATE_SETUP1; lcdClear(); lcdString("Set number of laps:"); lcdJump(1, 11); lcdData('_'); #ifdef BIG_DIGITS printL(1, 10); #else printL(2, 10); #endif break; case STATE_SETUP1: // confirm 1st digit state = STATE_SETUP2; lcdJump(1, 11); lcdData(' '); lcdJump(1, 10); lcdData('_'); break; case STATE_PAUSE: // restart race case STATE_RACE: case STATE_END: CCTL0 &= ~CCIE; #ifdef LANE_4 P1IE &= ~(SENS0 | SENS1 | SENS2 | SENS3); #else P1IE &= ~(SENS0 | SENS1); #endif case STATE_SETUP2: // confirm 2nd digit and prepare race CPRINT : state = STATE_READY; raceLaps |= LAP_MARK; // for easier lap[id] comparison in newLap initData(); break; default: break; } } // Print 2 digit number (lap count) void printL(u8 r, u8 c) { #ifdef BIG_DIGITS r <<= 1; lcdJump(r + 1, c); lcdData(bufferB[3]); lcdData(bufferB[4]); #endif lcdJump(r, c); lcdData(bufferT[3]); lcdData(bufferT[4]); } // Print 2.2 digit number (time/best) void printT(u8 r, u8 c) { #ifdef BIG_DIGITS r <<= 1; lcdJump(r + 1, c); lcdDataArray(bufferB, 5); #endif lcdJump(r, c); lcdDataArray(bufferT, 5); } // Convert Interger to 2.2 or 2 digit 2 line size String void tostr(u16 i) { bufferT[4] = i % 10; i /= 10; bufferT[3] = i % 10; i /= 10; bufferT[1] = i % 10; i /= 10; bufferT[0] = i % 10; #ifdef BIG_DIGITS bufferB[4] = numB[bufferT[4]]; bufferT[4] = numT[bufferT[4]]; bufferB[3] = numB[bufferT[3]]; bufferT[3] = numT[bufferT[3]]; bufferB[1] = numB[bufferT[1]]; bufferT[1] = numT[bufferT[1]]; bufferB[0] = numB[bufferT[0]]; bufferT[0] = numT[bufferT[0]]; #else bufferT[4] += '0'; bufferT[3] += '0'; bufferT[1] += '0'; bufferT[0] += '0'; #endif } // New lap service routine void newLap(u8 id) { lap[id]++; // increment lap counter if (lap[id] == 100) lap[id] = 0; // 2 digit overflow lap[id] |= LAP_MARK; // mark for LCD update if (time[id] < best[id]) { // test best lap time best[id] = time[id] | BEST_MARK; // mark for LCD update } time[id] = 0; // reset time counter if (state >= STATE_FINISH) { race &= ~SENS[id]; // race mode looser finish } if (lap[id] == raceLaps) { race &= ~SENS[id]; if (mode == MODE_RACE && state == STATE_RACE) { state = STATE_FINISH | id; // race mode winner finish } else if (mode == MODE_TIME) { if (++state == (STATE_RACE + LANES)) { // time mode all finished u8 bestId = 0; for (id = 1; id < LANES; ++id) { // find best time if (best[id] < best[bestId]) bestId = id; } state = STATE_FINISH | bestId; } } } } // Timer A0 interrupt service routine #ifdef TIMER0_A0_VECTOR #pragma vector=TIMER0_A0_VECTOR #else #pragma vector=TIMERA0_VECTOR #endif __interrupt void Timer_A(void) { u8 id; for (id = 0; id < LANES; ++id) { if (race & SENS[id]) { time[id]++; // increment time counter if (time[id] == MIN_LAP_TIME) { P1IFG &= ~SENS[id]; // SENS IFG cleared P1IE |= SENS[id]; // SENS interrupt enabled } else if (time[0] == 10000) time[id] = 0; // 4 digit overflow } } } // Watchdog Timer interrupt service routine #pragma vector=WDT_VECTOR __interrupt void watchdog_timer(void) { if (hold == LONG_PRESS) { buttonLong(); } else if (P1IN & BUTTON) { buttonShort(); } else { // Button still pressed hold++; return; } P1IE |= BUTTON; // BUTTON interrupt enabled WDTCTL = WDTPW | WDTHOLD | WDTTMSEL | WDTCNTCL; // Stop+Clear+TimerMode WDT hold = 0; } // Port 1 interrupt service routine #pragma vector=PORT1_VECTOR __interrupt void Port_1(void) { u8 id; u8 x = P1IFG & P1IE; // Mask enabled intrrupt flags // BUTTON if (x & BUTTON) { P1IE &= ~BUTTON; // BUTTON interrupt disabled P1IFG &= ~BUTTON; // BUTTON IFG cleared WDTCTL = WDTPW | WDTTMSEL; // Start+TimerMode WDT } else { // SENS for (id = 0; id < LANES; ++id) { if (x & SENS[id]) { P1IE &= ~SENS[id]; // SENS interrupt disabled P1IFG &= ~SENS[id]; // SENS IFG cleared newLap(id); return; } } P1IFG = 0; } }
    Final version code:
    EDIT: Now with possibility to disable large digits (comment #define BIG_DIGITS in lcd.h) so it can fit in 2K FLASH devices.
    EDIT2: Deprecated, replaced by new 2/4 lane version
    #include <msp430g2553.h> #include "lcd.h" // Pin allocation #define BUTTON BIT3 #define SENS0 BIT4 #define SENS1 BIT5 #define BUZZER BIT6 #define LONG_PRESS 10 // N x 30 ms #define MIN_LAP_TIME 100 // N x 1/100 s // Type definition for simplicity typedef unsigned char u8; typedef char s8; typedef unsigned int u16; typedef int s16; u8 hold = 0; // Long button press counter u8 lap[2]; // Lap number u16 time[2]; // Lap time in 1/100 s u16 best[2]; // Best Lap time u8 race[2]; // Car did not finish race u8 raceLaps = 0; // Number of laps of race #ifdef BIG_DIGITS u8 bufferT[] = {0, 0, ' ', 0x07, 0x07}; // Number to display top part u8 bufferB[] = {0, 0, '.', 0x06, 0x06}; // Number to display bottom part #else u8 bufferT[] = {0, 0, '.', '0', '0'}; // Number to display #endif #define BEST_MARK 0x8000 // best updated flag, needs redraw #define LAP_MARK 0x80 // lap updated flag, needs redraw // Application states #define STATE_MAIN 0x00 #define STATE_SETUP1 0x10 #define STATE_SETUP2 0x20 #define STATE_PAUSE 0x30 #define STATE_START 0x40 #define STATE_RACE 0x50 #define STATE_FINISH 0x60 #define STATE_END 0x70 #define WIN1_MARK 0x02 // Race result bit, set if car 1 wins u8 state = STATE_MAIN; // Race modes #define MODE_RACE 0x01 // first to finish wins #define MODE_TIME 0x02 // best lap time wins #define MODE_PRAC 0x03 // infinite practice with best time tracking u8 mode = MODE_RACE; // Race initial screen #ifdef BIG_DIGITS static const char CScreen[] = {'L', ' ', 0x07, 0x07, ' ', 'T', ' ', 0x07, 0x07, ' ', 0x07, 0x07, ' ', 'B', ' ', '_', '_', ' ', '_', '_', 'P', ' ', 0x07, 0x07, ' ', 'M', ' ', 0x07, 0x07, ' ', 0x07, 0x07, ' ', 'S', ' ', '_', '_', ' ', '_', '_', 'A', ' ', 0x06, 0x06, ' ', 'I', ' ', 0x06, 0x06, '.', 0x06, 0x06, ' ', 'E', ' ', ' ', ' ', '.', ' ', ' ', 'S', ' ', 0x06, 0x06, ' ', 'E', ' ', 0x06, 0x06, '.', 0x06, 0x06, ' ', 'T', ' ', ' ', ' ', '.', ' ', ' '}; #else static const char CScreen[] = {'L', ' ', '0', '0', ' ', 'T', ' ', '0', '0', '.', '0', '0', ' ', 'B', ' ', '-', '-', '.', '-', '-', 'P', ' ', '0', '0', ' ', 'M', ' ', '0', '0', '.', '0', '0', ' ', 'S', ' ', '-', '-', '.', '-', '-', 'A', ' ', ' ', ' ', ' ', 'I', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'E', ' ', ' ', ' ', ' ', ' ', ' ', 'S', ' ', ' ', ' ', ' ', 'E', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'T', ' ', ' ', ' ', ' ', ' ', ' '}; #endif void longDelay(void); void initData(void); void buttonShort(void); void buttonLong(void); void tostr(u16 i); void printL(u8 r, u8 c); void printT(u8 r, u8 c); void newLap(u8 id); // handles all race LCD updates to avoid char placement errors void main(void) { // try to set DCO to 1 MHz if (CALBC1_1MHZ != 0xFF || CALDCO_1MHZ != 0xFF) { BCSCTL1 = CALBC1_1MHZ; // Set range DCOCTL = CALDCO_1MHZ; // Set DCO step + modulation } // initialize peripheries // watchdog WDTCTL = WDTPW | WDTHOLD | WDTTMSEL | WDTCNTCL; // Stop+Clear+TimerMode WDT IE1 = WDTIE; // WDT IE // gpio P1 P1OUT = SENS0 | SENS1; // pullup P1REN = SENS0 | SENS1; // internal resistor P1IES = BUTTON | SENS0 | SENS1; // Hi/lo edge P1IFG = 0; // IFG cleared P1IE = BUTTON; // BUTTON interrupt enabled // timerA CCR0 = 9994 - 1; // 1/100s, DCO 1MHz calibration = 244x4096 TACTL = TASSEL_2 + MC_1; // SMCLK, upmode //buzzer P1DIR = BUZZER; P1SEL = BUZZER; // BUZZER TimeA output CCTL1 = OUTMOD_7; // CCR1 reset/set CCR1 = 0; // Buzzer off // lcd lcdInit(); _enable_interrupts(); // global interupt enable // Setup initial screen lcdString("Select Mode: Time Attack ~ Lap Race Practice"); initData(); while (1) { u8 id = 0; if (P1IE & SENS0) { // hold after lap tostr(time[0]); // print time printT(0, 7); } if (P1IE & SENS1) { // hold after lap tostr(time[1]); // print time printT(2, 7); } // print updated values REPEAT: if (best[id] & BEST_MARK) { best[id] &= ~BEST_MARK; tostr(best[id]); // print time printT(id << 1, 15); } if (lap[id] & LAP_MARK) { lap[id] &= ~LAP_MARK; tostr(lap[id]); // print lap count printL(id << 1, 2); } id = !id; // to update both cars 0/1 if (id) goto REPEAT; if (state == STATE_START) { // Sound countdown CCR0 = 4000; // higher frequency for (id = 8; id > 1; id--) { // 3 short+1 long CCR1 ^= 2000; longDelay(); if (id & 1)longDelay(); } longDelay(); CCR1 = 0; CCR0 = 9994 - 1; // resume 1/100s state = STATE_RACE; CCTL0 = CCIE; // start time counting P1IFG &= ~(SENS0 | SENS1); P1IE |= SENS0 | SENS1; } // race ended if ((state & ~WIN1_MARK) == STATE_FINISH) { lcdJump(state & WIN1_MARK, 1); // mark winner in LCD lcdData(0xFF); CCR1 = 4997; // short beep longDelay(); CCR1 = 0; state = STATE_END; } longDelay(); } } // Delay ~0.2s void longDelay(void) { _delay_cycles(190000); } // Set initial values void initData(void) { best[0] = 9999; best[1] = 9999; lap[0] = 0; lap[1] = 0; time[0] = 0; time[1] = 0; race[0] = 1; race[1] = 1; } // Short button press void buttonShort(void) { switch (state) { case STATE_MAIN: lcdJump(mode, 0); lcdData(' '); switch (mode) { // change race mode case MODE_RACE: mode = MODE_TIME; break; case MODE_TIME: mode = MODE_PRAC; break; case MODE_PRAC: mode = MODE_RACE; break; default: break; } lcdJump(mode, 0); lcdData(0x7E); break; case STATE_SETUP1: raceLaps++; // increase 1st digit if (raceLaps == 10) // overflow raceLaps = 0; LPRINT: tostr(raceLaps); // update LCD printL(1, 10); break; case STATE_SETUP2: raceLaps += 10; // increase 2nd digit if (raceLaps >= 100) // overflow raceLaps -= 100; goto LPRINT; //break; case STATE_RACE: // pause race state = STATE_PAUSE; CCTL0 = 0; P1IE &= ~(SENS0 | SENS1); break; case STATE_PAUSE: // resume race state = STATE_START; break; default: break; } } // Long button press void buttonLong() { switch (state) { case STATE_MAIN: // confirm race mode lcdClear(); if (mode == MODE_PRAC) { // start practice raceLaps = 127; goto CPRINT; } state = STATE_SETUP1; lcdString("Set number of laps:"); printL(1, 10); lcdJump(3, 11); lcdData(0x2D); break; case STATE_SETUP1: // confirm 1st digit state = STATE_SETUP2; lcdJump(3, 11); lcdData(' '); lcdJump(3, 10); lcdData(0x2D); break; case STATE_PAUSE: // restart race case STATE_RACE: case STATE_END: CCTL0 &= ~CCIE; P1IE &= ~(SENS0 | SENS1); case STATE_SETUP2: // confirm 2nd digit and prepare race CPRINT : state = STATE_PAUSE; initData(); lcdCommand(LCD_SETDDRAMADDR); lcdDataArray(CScreen, 80); break; default: break; } } // Print 2 digit number (lap count) void printL(u8 r, u8 c) { lcdJump(r, c); lcdData(bufferT[3]); lcdData(bufferT[4]); #ifdef BIG_DIGITS lcdJump(r + 1, c); lcdData(bufferB[3]); lcdData(bufferB[4]); #endif } // Print 2.2 digit number (time/best) void printT(u8 r, u8 c) { lcdJump(r, c); lcdDataArray(bufferT, 5); #ifdef BIG_DIGITS lcdJump(r + 1, c); lcdDataArray(bufferB, 5); #endif } // Convert Interger to 2.2 or 2 digit 2 line size String void tostr(u16 i) { bufferT[4] = i % 10; i /= 10; bufferT[3] = i % 10; i /= 10; bufferT[1] = i % 10; i /= 10; bufferT[0] = i % 10; #ifdef BIG_DIGITS bufferB[4] = numB[bufferT[4]]; bufferT[4] = numT[bufferT[4]]; bufferB[3] = numB[bufferT[3]]; bufferT[3] = numT[bufferT[3]]; bufferB[1] = numB[bufferT[1]]; bufferT[1] = numT[bufferT[1]]; bufferB[0] = numB[bufferT[0]]; bufferT[0] = numT[bufferT[0]]; #else bufferT[4] += '0'; bufferT[3] += '0'; bufferT[1] += '0'; bufferT[0] += '0'; #endif } // New lap service routine void newLap(u8 id) { lap[id]++; // increment lap counter if (lap[id] == 100) lap[id] = 0; // 2 digit overflow if (time[id] best[id] = time[id] | BEST_MARK; // mark for LCD update } time[id] = 0; // reset time counter if (mode == MODE_RACE && (race[0] ^ race[1])) { race[id] = 0; // race mode looser finish } if (lap[id] == raceLaps) { race[id] = 0; if (mode == MODE_RACE && (race[0] ^ race[1])) { state = STATE_FINISH; // race mode winner finish if (id) state |= WIN1_MARK; } else if (mode == MODE_TIME && !(race[0] | race[1])) { state = STATE_FINISH; // time mode both finished if (best[0] > best[1]) { // time mode select winner state |= WIN1_MARK; } } } lap[id] |= LAP_MARK; // mark for LCD update } // Timer A0 interrupt service routine #ifdef TIMER0_A0_VECTOR #pragma vector=TIMER0_A0_VECTOR #else #pragma vector=TIMERA0_VECTOR #endif __interrupt void Timer_A(void) { if (race[0]) { time[0]++; // increment time counter if (time[0] == MIN_LAP_TIME) { P1IFG &= ~SENS0; // SENS1 IFG cleared P1IE |= SENS0; // SENS1 interrupt enabled } else if (time[0] == 10000) time[0] = 0; // 4 digit overflow } if (race[1]) { time[1]++; // increment time counter if (time[1] == MIN_LAP_TIME) { P1IFG &= ~SENS1; // SENS2 IFG cleared P1IE |= SENS1; // SENS1 interrupt enabled } else if (time[1] == 10000) time[1] = 0; // 4 digit overflow } } // Watchdog Timer interrupt service routine #pragma vector=WDT_VECTOR __interrupt void watchdog_timer(void) { if (hold == LONG_PRESS) { buttonLong(); } else if (P1IN & BUTTON) { buttonShort(); } else { // Button still pressed hold++; return; } P1IE |= BUTTON; // BUTTON interrupt enabled WDTCTL = WDTPW | WDTHOLD | WDTTMSEL | WDTCNTCL; // Stop+Clear+TimerMode WDT hold = 0; } // Port 1 interrupt service routine #pragma vector=PORT1_VECTOR __interrupt void Port_1(void) { u8 x = P1IFG & P1IE; // Mask enabled intrrupt flags // BUTTON if (x & BUTTON) { P1IE &= ~BUTTON; // BUTTON interrupt disabled P1IFG &= ~BUTTON; // BUTTON IFG cleared WDTCTL = WDTPW | WDTTMSEL; // Start+TimerMode WDT }// SENS1 else if (x & SENS0) { P1IE &= ~SENS0; // SENS1 interrupt disabled P1IFG &= ~SENS0; // SENS1 IFG cleared newLap(0); }// SENS2 else if (x & SENS1) { P1IE &= ~SENS1; // SENS2 interrupt disabled P1IFG &= ~SENS1; // SENS2 IFG cleared newLap(1); } else P1IFG = 0; }  


    Modified RobG's LCD display code with large digits:
    lcd.h
    // Pin allocation, modify to connected pins! #define LCD_D BIT2 #define LCD_C BIT1 #define LCD_E BIT0 #define BIG_DIGITS // uncomment to enable two line digits, takes ~100B #ifdef BIG_DIGITS // Dual Line digits 0-9 // Top part static const char numT[] = {0x07,0x00,0x01,0x01,0x06,0x03,0x03,0x01,0x05,0x07}; // Bottom part static const char numB[] = {0x06,0x00,0x04,0x02,0x00,0x02,0x05,0x00,0x05,0x02}; #endif void lcdInit(void); void lcdString(const char text[]); void lcdDataArray(const char data[], char length); void lcdClear(); void lcdJump(char row, char colum); void lcdSend(char data, char registerSelect); #define lcdData(data) lcdSend(data, 1) #define lcdCommand(command) lcdSend(command, 0) // commands #define LCD_CLEARDISPLAY 0x01 #define LCD_RETURNHOME 0x02 #define LCD_ENTRYMODESET 0x04 #define LCD_DISPLAYCONTROL 0x08 #define LCD_CURSORSHIFT 0x10 #define LCD_FUNCTIONSET 0x20 #define LCD_SETCGRAMADDR 0x40 #define LCD_SETDDRAMADDR 0x80 // flags for display entry mode #define LCD_ENTRYRIGHT 0x00 #define LCD_ENTRYLEFT 0x02 #define LCD_ENTRYSHIFTINCREMENT 0x01 #define LCD_ENTRYSHIFTDECREMENT 0x00 // flags for display on/off control #define LCD_DISPLAYON 0x04 #define LCD_DISPLAYOFF 0x00 #define LCD_CURSORON 0x02 #define LCD_CURSOROFF 0x00 #define LCD_BLINKON 0x01 #define LCD_BLINKOFF 0x00 // flags for display/cursor shift #define LCD_DISPLAYMOVE 0x08 #define LCD_CURSORMOVE 0x00 #define LCD_MOVERIGHT 0x04 #define LCD_MOVELEFT 0x00 // flags for function set #define LCD_8BITMODE 0x10 #define LCD_4BITMODE 0x00 #define LCD_2LINE 0x08 #define LCD_1LINE 0x00 #define LCD_5x10DOTS 0x04 #define LCD_5x8DOTS 0x00  

    lcd.c
    #include "msp430g2553.h" #include "lcd.h" // Starts of lines for 4x20 LCD static const char Line[] = {0, 0x40, 20, 0x40 + 20}; #ifdef BIG_DIGITS // Definition of custom chars for dual line digits static const char NUMdata[] = {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1f, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1f, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1f, 0x1f, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1f, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1f, 0x1f, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x1f, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x1f, 0x1f, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}; #endif void lcdInit(void) { _delay_cycles(100000); // initialize pins P1OUT &= ~(LCD_C | LCD_D); P1OUT |= LCD_E; P1DIR |= LCD_E | LCD_C | LCD_D; // initialize display lcdCommand(LCD_FUNCTIONSET | LCD_8BITMODE | LCD_2LINE | LCD_5x8DOTS); lcdCommand(LCD_DISPLAYCONTROL | LCD_DISPLAYON); lcdClear(); #ifdef BIG_DIGITS lcdCommand(LCD_ENTRYMODESET | LCD_ENTRYLEFT); // define 8 custom characters lcdCommand(LCD_SETCGRAMADDR); lcdDataArray(NUMdata, 64); // go to first position lcdCommand(LCD_SETDDRAMADDR); #endif } // Display String ended by 0x00 void lcdString(const char text[]) { int i; for (i = 0; text[i] != 0; i++) { lcdData(text[i]); } } // Send byte array void lcdDataArray(const char data[], char length) { char i; for (i = 0; i < length; i++) { lcdData(data[i]); } } // Bitbang one LDE instruction/data void lcdSend(char data, char registerSelect) { char i; for (i = 0; i < 8; i++) { (data & BIT0) ? (P1OUT |= LCD_D) : (P1OUT &= ~LCD_D); data >>= 1; P1OUT |= LCD_C; P1OUT &= ~LCD_C; } registerSelect ? (P1OUT |= LCD_D) : (P1OUT &= ~LCD_D); P1OUT &= ~LCD_E; P1OUT |= LCD_E; } // Clear display and go to first position void lcdClear() { lcdCommand(LCD_CLEARDISPLAY); _delay_cycles(2000); } // Go to defined position void lcdJump(char row, char colum) { lcdCommand(LCD_SETDDRAMADDR + Line[row] + colum); }  
     




    http://www.youtube.com/watch?v=Fwz0Ui2cySw

    http://www.youtube.com/watch?v=YNLD608ZsAQ


    [id]){>[id]){>
  13. Like
    Rickta59 reacted to B.Noll in ADC10 TestCode   
    While searching an ADC samplecode for the g2231 I found one that made use of the floating point lib to get an accurate reading of the ADC return value. As the g2231 is a 2k chip that is a silly thing to do.
     
    The goal for the code was to get an accuracy that is similar to a 4 digit DMM. Ok, let's think about this. When using the internal reference (2.5V) the resolution we can get is 2.5V / 1024 = 0.002441 Volt. We can see that the last digit will jump because 10 BIT is not enough. Ok, let's try the 2nd reference with 1.5V / 1024 = 0.001468. Not to bad but still not good enough. Also I'de like to have a range from 0-2.5 V.
     
    By testing the code I mentioned before a constant had been used to make the reading look accurate, however, as there was only one constant in use to correct the ADC the result was quite poor compared to a DMM. As we all know in real life there is no perfect ADC and if we only have the linear errors in mind we will find at least an offset and a gain error.
     
    So the problem to solve looked like:
    - avoid floating point
    - get the accuracy of floating point
    - correct the ADC errors
    - get more then 10 BIT out of the g2231
     
    The following code will do what we need and the codesize is only 576 Byte. I used a well know oversampling technique to get 12 BIT out of the ADC and calculate all corrections by fixed point arithmetic. Instead of calculating on a base by 10 I used base 2 instead as this will allow us to get the result by a simple shift operation. Once the code was working I could still see some jumps in the last digit caused by a ripple of arround 4 mVolt caused by the poor USB powersource of the Launchpad. So I have added also a low pass filter in Software to get rid of the remaining noise.
     
    The ADC result will be displayed @ the MSP430 USB Application COM Port. I have used the Soft. Uart code by NJC but slightly modified it to have a putChar function.
     
    To adjust your ADC and get the RawValues (AdcRawHigh, AdcRawLow) for the calculation of the constants use
    "return (AvgSum >> 8);" instead of the original return statement "return AdcVal;" and ignore the decimal point. In function "AdcValOut" use "while (m != 4)" to display all digits of the RawValues.
    So here we are, let me share this code snippet with you. Please try out the code and let me know your findings.
     
    Have fun,
     
    Bernd
    g2231AdcTestCode.c
  14. Like
    Rickta59 reacted to pheo in Hardware UART Skeleton in C   
    My first forum post, i'd like to help out anyone trying to use the USCI module for hardware UART.
     
    First, some background:
    I'm running the Launchpad with a msp430g2553. This chip is very full featured, comes in PDIP-20 compatible with the Launchpad, and if you're lucky, TI will send you a sample. See the datasheet:
    http://focus.ti.com/docs/prod/folders/print/msp430g2553.html
     
    I'm running uniarch msp430-gcc-4.5.2, which is the awesome alpha release.
    For a nice how-to-compile link, try:
    http://sourceforge.net/apps/mediawiki/mspgcc/index.php?title=Devel:UniarchGit
    This worked well for me on Fedora, as does the new gcc.
    Check out the bleeding edge mspdebug from git for full debugger support as well:
    http://mspdebug.sourceforge.net
    With the right devel packages, this guy works like a charm with the g2553.
     
    Well, the g2553 has the TX/RX pins for the USCI module flipped from the Launchpad TX/RX headers!
    So how can that be fixed? I didn't have any tools or hardware to correct the problem. Just some wire and a soldering pencil.
    Why not just the hardware from the Launchpad? It has extra jumpers for the LED's and a strip of male pin headers. (i used the female headers). See the attached image.
     
    I plan on using HW UART to act a transceiver. For my next project, i'd like to be able to send/receive data to/from the Launchpad so that it can use it in a second stage of sending/receiving. Since i've gotten the code for the first stage working, i think the place i am at could serve as a big leg up to anyone working on a project that needs to be "remote controlled" in a complex way.
     
    Now for the code:
    The flow of the program is as follows
    1. Setup the button on the launchpad. i do this, because otherwise the LP will start spewing characters over serial and this breaks my ttyACM0. Im not sure why, but the driver doesn't seem to like
    2. After the button is pressed, setup the USCI module.
    I'm using 32.768 kHz ACLK as the clock source, UART mode, at 9600 baud
    3. Spew out the alphabet in a loop.
    3.1. During the main loop, the receive interrupt will write down what it got into a variable, conveniently named 'variable'.
     
    Hopefully this will help someone out.
    There's a lot more to be done. This is just a nice guidepost on the way.
     
    Cheers
     
    EDIT: Found a bug

    Makefile.txt
    main.c
  15. Like
    Rickta59 got a reaction from YanuarPrijadi in Interface 23K256 SPI RAM with USI SPI   
    I came across the Microchip 23K256 Serial RAM device a while back. It seems to fit the bill
    when you need more RAM but don't want to spend a lot of money to get it. These chips are
    inexpensive, (about $1,50 at time of this post 06/05/2011) and hold 32K worth of data. You access
    the memory using SPI. You can even put multiple 23K256 devices on your SPI bus and get
    even more buffer space.
     
    The arduino world already has a couple of libraries to access these devices. I adapted
    one of these to work with both CCS and the uniarch compiler.
     
    I used GRACE to help me configure the msp430g2452 USI in SPI Mode 1. This code might be
    also be useful as a starting point for any SPI Mode 1 device. This code is written for the USI
    device. It would be nice to have a USCI version that would work with the g2553 chip.
     
    Typical use for this device might be to buffer UART received data that is larger than the 128 bytes
    of SRAM available on the smaller G series chips.
     
    You might want to verify the pin setup, I think I have it correct, however you should always verify.
    One interesting item of note is my use of one of the GPIO pins to power the device. You may or
    may not want to use that in your setup. According to the datasheet the 23K256 uses somewhere
    between 2-10mA of power based on how fast you interface with it. I think the G series should
    handle that but I'm not 100% sure. Please comment if you know.
     
    https://gist.github.com/1009412
     

    /** * testspi23K256.c - Interface Microchip 23K256 Serial RAM chip with MSP430G2452 USI SPI * * This code snippet show you how to configure the USI SPI in SPI Mode 1 to communicate with * the 23K256 chip at 4MHz. It takes about 98uSecs to write a single byte and 32K takes * about 100ms. * * msp430g2452 - http://focus.ti.com/docs/prod/folders/print/msp430g2452.html * 23K256 - http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en539039 * * Pin Connections: * * MSP430 SCLK P1.5 -> PIN 6(SCK) 23K256 * MSP430 MISO P1.7 -> PIN 2(SO) 23K256 * MSP430 MOSI P1.6 -> PIN 5(SI) 23K256 * MSP430 GPIO P1.1 -> PIN 1(CS) 23K256 * MSP430 GPIO P1.4 -> PIN 8(VCC) 23K256 * * 23K256 PIN 7 Pullup resistor * 23K256 PIN 8 Pulldown resistor * * Linux build: * * $ msp430-gcc -mmcu=msp430g2452 -O3 -g -Wall -I. -c testspi23K256.c * $ msp430-gcc -mmcu=msp430g2452 -O3 -g -Wall -I. -o ./testspi23K256.elf ./testspi23K256.o -Wl,-Map,./testspi23K256.map * $ msp430-objdump -Sww ./testspi23K256.elf >./testspi23K256.lss * $ msp430-size ./testspi23K256.elf * $ mspdebug -q --force-reset rf2500 "erase" "prog ./testspi23K256.elf" * * This code was inspired from this code: * * http://sourceforge.net/projects/mysudoku/files/ * http://hackaday.com/2009/03/02/parts-32kb-spi-sram-memory-23k256/ * */ #include #include enum { POWER_PIN = BIT4, // we power the 23K256 chip from one of our GPIO pins SS_PIN = BIT1, // CS , active low DEBUG_PIN = BIT0, // toggle on and off marking time to write DUMMY_BYTE = 0xFF // byte we send when we just want to read slave data }; static inline uint8_t RWData(volatile uint8_t value); void loop(); #define powerOn P1OUT |= POWER_PIN #define powerOff P1OUT &= ~POWER_PIN #define ssSelect P1OUT &= ~SS_PIN #define ssDeselect P1OUT |= SS_PIN #define delay_1ms __delay_cycles(16000) #define SR_WRITE_STATUS 0x01 #define SR_WRITE 0x02 #define SR_READ 0x03 #define SR_READ_STATUS 0x05 // 23K256 Serial Ram functions uint8_t SR_getMode(void) { ssSelect; RWData(SR_READ_STATUS); // 0x05 uint8_t mode = RWData(DUMMY_BYTE); ssDeselect; return mode; } void SR_setMode(uint8_t mode) { ssSelect; RWData(SR_WRITE_STATUS); // 0x01 RWData(mode); ssDeselect; } static inline void SR_writestream(uint16_t addr) { ssDeselect; // deselect if we are active ssSelect; RWData(0x02); RWData(addr >> 8); RWData(addr); } static inline void SR_readstream(uint16_t addr) { ssDeselect; ssSelect; RWData(0x03); RWData(addr >> 8); RWData(addr); } static inline uint8_t RWData(volatile uint8_t value) { USISRL = value; USICNT = 8; // initialize bit count, start transfer/read __delay_cycles(0); while (!(USIIFG & USICTL1)) ; // wait for SPI flag to trip return USISRL; } /** * main */ int main() { // kill the watchdog timer WDTCTL = WDTPW + WDTHOLD; // configure DCO clock to 16MHz BCSCTL2 = SELM_0 + DIVM_0 + DIVS_0; if (CALBC1_16MHZ != 0xFF) { DCOCTL = 0x00; BCSCTL1 = CALBC1_16MHZ; DCOCTL = CALDCO_16MHZ; } BCSCTL1 |= XT2OFF + DIVA_0; BCSCTL3 = XT2S_0 + LFXT1S_2 + XCAP_1; // configure GPIO P1OUT = POWER_PIN; P1DIR = SS_PIN + POWER_PIN + DEBUG_PIN; // configure USI - SPI Mode 1 @ 4MHz, clocked off SMCLK USICTL0 |= USISWRST; USICTL0 = USIPE7 + USIPE6 + USIPE5 + USIMST + USIOE + USISWRST; USICTL1 |= USICKPH; USICKCTL = USIDIV_1 + USISSEL_2; /* Enable USI */ USICTL0 &= ~USISWRST; __enable_interrupt(); // Set global interrupt enable // toggle the power for the 23K256 powerOff; delay_1ms; powerOn; ssDeselect; delay_1ms; while (1) { uint8_t chipMode; // make sure there is a 23K256 chip and that // is wired properly and in sequential mode chipMode = SR_getMode(); if (chipMode != 0x41) { SR_setMode(0x41); } else { while (1) { loop(); } } } } #define BYTES_TO_STREAM 32768 // should be less <= 32768 #define PATTERN_BYTE_VALUE 0x55 /** * loop - write a test pattern and read it back */ void loop() { volatile uint16_t i; volatile uint8_t storedValue = 0; P1OUT |= DEBUG_PIN; // mark start of write for measurement with oscope SR_writestream(0); // start writing at address 0 for (i = 0; i < BYTES_TO_STREAM; ++i) { RWData(PATTERN_BYTE_VALUE); } P1OUT &= ~DEBUG_PIN; // mark end of write for measurement with oscope // verify the bytes we wrote were stored and retreived properly SR_readstream(0); // start reading at address 0 for (i = 0; i < BYTES_TO_STREAM; ++i) { storedValue = RWData(DUMMY_BYTE); // verify our test pattern if (storedValue != PATTERN_BYTE_VALUE) { // if values aren't the same an error occurred, // turn off all leds, then sit and spin P1OUT &= ~BIT6; P1OUT &= ~DEBUG_PIN; while (1) { ; } } } }
  16. Like
    Rickta59 reacted to zeke in Any Entrepreneurs hanging out here?   
    I was wondering if any Entrepreneurs / Small Business Owners hang out here?
     
    If so, tell me what you think of Rob Walling's article The Micropreneur's Manifesto.
     
    I read it tonight and thought it had a lot of interesting points. I'm personally trying to make #5 happen right now. I guess I'm reacting to all of this Maker Revolution happening around us.
  17. Like
    Rickta59 got a reaction from nuetron in Interface 23K256 SPI RAM with USI SPI   
    I came across the Microchip 23K256 Serial RAM device a while back. It seems to fit the bill
    when you need more RAM but don't want to spend a lot of money to get it. These chips are
    inexpensive, (about $1,50 at time of this post 06/05/2011) and hold 32K worth of data. You access
    the memory using SPI. You can even put multiple 23K256 devices on your SPI bus and get
    even more buffer space.
     
    The arduino world already has a couple of libraries to access these devices. I adapted
    one of these to work with both CCS and the uniarch compiler.
     
    I used GRACE to help me configure the msp430g2452 USI in SPI Mode 1. This code might be
    also be useful as a starting point for any SPI Mode 1 device. This code is written for the USI
    device. It would be nice to have a USCI version that would work with the g2553 chip.
     
    Typical use for this device might be to buffer UART received data that is larger than the 128 bytes
    of SRAM available on the smaller G series chips.
     
    You might want to verify the pin setup, I think I have it correct, however you should always verify.
    One interesting item of note is my use of one of the GPIO pins to power the device. You may or
    may not want to use that in your setup. According to the datasheet the 23K256 uses somewhere
    between 2-10mA of power based on how fast you interface with it. I think the G series should
    handle that but I'm not 100% sure. Please comment if you know.
     
    https://gist.github.com/1009412
     

    /** * testspi23K256.c - Interface Microchip 23K256 Serial RAM chip with MSP430G2452 USI SPI * * This code snippet show you how to configure the USI SPI in SPI Mode 1 to communicate with * the 23K256 chip at 4MHz. It takes about 98uSecs to write a single byte and 32K takes * about 100ms. * * msp430g2452 - http://focus.ti.com/docs/prod/folders/print/msp430g2452.html * 23K256 - http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en539039 * * Pin Connections: * * MSP430 SCLK P1.5 -> PIN 6(SCK) 23K256 * MSP430 MISO P1.7 -> PIN 2(SO) 23K256 * MSP430 MOSI P1.6 -> PIN 5(SI) 23K256 * MSP430 GPIO P1.1 -> PIN 1(CS) 23K256 * MSP430 GPIO P1.4 -> PIN 8(VCC) 23K256 * * 23K256 PIN 7 Pullup resistor * 23K256 PIN 8 Pulldown resistor * * Linux build: * * $ msp430-gcc -mmcu=msp430g2452 -O3 -g -Wall -I. -c testspi23K256.c * $ msp430-gcc -mmcu=msp430g2452 -O3 -g -Wall -I. -o ./testspi23K256.elf ./testspi23K256.o -Wl,-Map,./testspi23K256.map * $ msp430-objdump -Sww ./testspi23K256.elf >./testspi23K256.lss * $ msp430-size ./testspi23K256.elf * $ mspdebug -q --force-reset rf2500 "erase" "prog ./testspi23K256.elf" * * This code was inspired from this code: * * http://sourceforge.net/projects/mysudoku/files/ * http://hackaday.com/2009/03/02/parts-32kb-spi-sram-memory-23k256/ * */ #include #include enum { POWER_PIN = BIT4, // we power the 23K256 chip from one of our GPIO pins SS_PIN = BIT1, // CS , active low DEBUG_PIN = BIT0, // toggle on and off marking time to write DUMMY_BYTE = 0xFF // byte we send when we just want to read slave data }; static inline uint8_t RWData(volatile uint8_t value); void loop(); #define powerOn P1OUT |= POWER_PIN #define powerOff P1OUT &= ~POWER_PIN #define ssSelect P1OUT &= ~SS_PIN #define ssDeselect P1OUT |= SS_PIN #define delay_1ms __delay_cycles(16000) #define SR_WRITE_STATUS 0x01 #define SR_WRITE 0x02 #define SR_READ 0x03 #define SR_READ_STATUS 0x05 // 23K256 Serial Ram functions uint8_t SR_getMode(void) { ssSelect; RWData(SR_READ_STATUS); // 0x05 uint8_t mode = RWData(DUMMY_BYTE); ssDeselect; return mode; } void SR_setMode(uint8_t mode) { ssSelect; RWData(SR_WRITE_STATUS); // 0x01 RWData(mode); ssDeselect; } static inline void SR_writestream(uint16_t addr) { ssDeselect; // deselect if we are active ssSelect; RWData(0x02); RWData(addr >> 8); RWData(addr); } static inline void SR_readstream(uint16_t addr) { ssDeselect; ssSelect; RWData(0x03); RWData(addr >> 8); RWData(addr); } static inline uint8_t RWData(volatile uint8_t value) { USISRL = value; USICNT = 8; // initialize bit count, start transfer/read __delay_cycles(0); while (!(USIIFG & USICTL1)) ; // wait for SPI flag to trip return USISRL; } /** * main */ int main() { // kill the watchdog timer WDTCTL = WDTPW + WDTHOLD; // configure DCO clock to 16MHz BCSCTL2 = SELM_0 + DIVM_0 + DIVS_0; if (CALBC1_16MHZ != 0xFF) { DCOCTL = 0x00; BCSCTL1 = CALBC1_16MHZ; DCOCTL = CALDCO_16MHZ; } BCSCTL1 |= XT2OFF + DIVA_0; BCSCTL3 = XT2S_0 + LFXT1S_2 + XCAP_1; // configure GPIO P1OUT = POWER_PIN; P1DIR = SS_PIN + POWER_PIN + DEBUG_PIN; // configure USI - SPI Mode 1 @ 4MHz, clocked off SMCLK USICTL0 |= USISWRST; USICTL0 = USIPE7 + USIPE6 + USIPE5 + USIMST + USIOE + USISWRST; USICTL1 |= USICKPH; USICKCTL = USIDIV_1 + USISSEL_2; /* Enable USI */ USICTL0 &= ~USISWRST; __enable_interrupt(); // Set global interrupt enable // toggle the power for the 23K256 powerOff; delay_1ms; powerOn; ssDeselect; delay_1ms; while (1) { uint8_t chipMode; // make sure there is a 23K256 chip and that // is wired properly and in sequential mode chipMode = SR_getMode(); if (chipMode != 0x41) { SR_setMode(0x41); } else { while (1) { loop(); } } } } #define BYTES_TO_STREAM 32768 // should be less <= 32768 #define PATTERN_BYTE_VALUE 0x55 /** * loop - write a test pattern and read it back */ void loop() { volatile uint16_t i; volatile uint8_t storedValue = 0; P1OUT |= DEBUG_PIN; // mark start of write for measurement with oscope SR_writestream(0); // start writing at address 0 for (i = 0; i < BYTES_TO_STREAM; ++i) { RWData(PATTERN_BYTE_VALUE); } P1OUT &= ~DEBUG_PIN; // mark end of write for measurement with oscope // verify the bytes we wrote were stored and retreived properly SR_readstream(0); // start reading at address 0 for (i = 0; i < BYTES_TO_STREAM; ++i) { storedValue = RWData(DUMMY_BYTE); // verify our test pattern if (storedValue != PATTERN_BYTE_VALUE) { // if values aren't the same an error occurred, // turn off all leds, then sit and spin P1OUT &= ~BIT6; P1OUT &= ~DEBUG_PIN; while (1) { ; } } } }
  18. Like
    Rickta59 got a reaction from cubeberg in Interface 23K256 SPI RAM with USI SPI   
    I came across the Microchip 23K256 Serial RAM device a while back. It seems to fit the bill
    when you need more RAM but don't want to spend a lot of money to get it. These chips are
    inexpensive, (about $1,50 at time of this post 06/05/2011) and hold 32K worth of data. You access
    the memory using SPI. You can even put multiple 23K256 devices on your SPI bus and get
    even more buffer space.
     
    The arduino world already has a couple of libraries to access these devices. I adapted
    one of these to work with both CCS and the uniarch compiler.
     
    I used GRACE to help me configure the msp430g2452 USI in SPI Mode 1. This code might be
    also be useful as a starting point for any SPI Mode 1 device. This code is written for the USI
    device. It would be nice to have a USCI version that would work with the g2553 chip.
     
    Typical use for this device might be to buffer UART received data that is larger than the 128 bytes
    of SRAM available on the smaller G series chips.
     
    You might want to verify the pin setup, I think I have it correct, however you should always verify.
    One interesting item of note is my use of one of the GPIO pins to power the device. You may or
    may not want to use that in your setup. According to the datasheet the 23K256 uses somewhere
    between 2-10mA of power based on how fast you interface with it. I think the G series should
    handle that but I'm not 100% sure. Please comment if you know.
     
    https://gist.github.com/1009412
     

    /** * testspi23K256.c - Interface Microchip 23K256 Serial RAM chip with MSP430G2452 USI SPI * * This code snippet show you how to configure the USI SPI in SPI Mode 1 to communicate with * the 23K256 chip at 4MHz. It takes about 98uSecs to write a single byte and 32K takes * about 100ms. * * msp430g2452 - http://focus.ti.com/docs/prod/folders/print/msp430g2452.html * 23K256 - http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en539039 * * Pin Connections: * * MSP430 SCLK P1.5 -> PIN 6(SCK) 23K256 * MSP430 MISO P1.7 -> PIN 2(SO) 23K256 * MSP430 MOSI P1.6 -> PIN 5(SI) 23K256 * MSP430 GPIO P1.1 -> PIN 1(CS) 23K256 * MSP430 GPIO P1.4 -> PIN 8(VCC) 23K256 * * 23K256 PIN 7 Pullup resistor * 23K256 PIN 8 Pulldown resistor * * Linux build: * * $ msp430-gcc -mmcu=msp430g2452 -O3 -g -Wall -I. -c testspi23K256.c * $ msp430-gcc -mmcu=msp430g2452 -O3 -g -Wall -I. -o ./testspi23K256.elf ./testspi23K256.o -Wl,-Map,./testspi23K256.map * $ msp430-objdump -Sww ./testspi23K256.elf >./testspi23K256.lss * $ msp430-size ./testspi23K256.elf * $ mspdebug -q --force-reset rf2500 "erase" "prog ./testspi23K256.elf" * * This code was inspired from this code: * * http://sourceforge.net/projects/mysudoku/files/ * http://hackaday.com/2009/03/02/parts-32kb-spi-sram-memory-23k256/ * */ #include #include enum { POWER_PIN = BIT4, // we power the 23K256 chip from one of our GPIO pins SS_PIN = BIT1, // CS , active low DEBUG_PIN = BIT0, // toggle on and off marking time to write DUMMY_BYTE = 0xFF // byte we send when we just want to read slave data }; static inline uint8_t RWData(volatile uint8_t value); void loop(); #define powerOn P1OUT |= POWER_PIN #define powerOff P1OUT &= ~POWER_PIN #define ssSelect P1OUT &= ~SS_PIN #define ssDeselect P1OUT |= SS_PIN #define delay_1ms __delay_cycles(16000) #define SR_WRITE_STATUS 0x01 #define SR_WRITE 0x02 #define SR_READ 0x03 #define SR_READ_STATUS 0x05 // 23K256 Serial Ram functions uint8_t SR_getMode(void) { ssSelect; RWData(SR_READ_STATUS); // 0x05 uint8_t mode = RWData(DUMMY_BYTE); ssDeselect; return mode; } void SR_setMode(uint8_t mode) { ssSelect; RWData(SR_WRITE_STATUS); // 0x01 RWData(mode); ssDeselect; } static inline void SR_writestream(uint16_t addr) { ssDeselect; // deselect if we are active ssSelect; RWData(0x02); RWData(addr >> 8); RWData(addr); } static inline void SR_readstream(uint16_t addr) { ssDeselect; ssSelect; RWData(0x03); RWData(addr >> 8); RWData(addr); } static inline uint8_t RWData(volatile uint8_t value) { USISRL = value; USICNT = 8; // initialize bit count, start transfer/read __delay_cycles(0); while (!(USIIFG & USICTL1)) ; // wait for SPI flag to trip return USISRL; } /** * main */ int main() { // kill the watchdog timer WDTCTL = WDTPW + WDTHOLD; // configure DCO clock to 16MHz BCSCTL2 = SELM_0 + DIVM_0 + DIVS_0; if (CALBC1_16MHZ != 0xFF) { DCOCTL = 0x00; BCSCTL1 = CALBC1_16MHZ; DCOCTL = CALDCO_16MHZ; } BCSCTL1 |= XT2OFF + DIVA_0; BCSCTL3 = XT2S_0 + LFXT1S_2 + XCAP_1; // configure GPIO P1OUT = POWER_PIN; P1DIR = SS_PIN + POWER_PIN + DEBUG_PIN; // configure USI - SPI Mode 1 @ 4MHz, clocked off SMCLK USICTL0 |= USISWRST; USICTL0 = USIPE7 + USIPE6 + USIPE5 + USIMST + USIOE + USISWRST; USICTL1 |= USICKPH; USICKCTL = USIDIV_1 + USISSEL_2; /* Enable USI */ USICTL0 &= ~USISWRST; __enable_interrupt(); // Set global interrupt enable // toggle the power for the 23K256 powerOff; delay_1ms; powerOn; ssDeselect; delay_1ms; while (1) { uint8_t chipMode; // make sure there is a 23K256 chip and that // is wired properly and in sequential mode chipMode = SR_getMode(); if (chipMode != 0x41) { SR_setMode(0x41); } else { while (1) { loop(); } } } } #define BYTES_TO_STREAM 32768 // should be less <= 32768 #define PATTERN_BYTE_VALUE 0x55 /** * loop - write a test pattern and read it back */ void loop() { volatile uint16_t i; volatile uint8_t storedValue = 0; P1OUT |= DEBUG_PIN; // mark start of write for measurement with oscope SR_writestream(0); // start writing at address 0 for (i = 0; i < BYTES_TO_STREAM; ++i) { RWData(PATTERN_BYTE_VALUE); } P1OUT &= ~DEBUG_PIN; // mark end of write for measurement with oscope // verify the bytes we wrote were stored and retreived properly SR_readstream(0); // start reading at address 0 for (i = 0; i < BYTES_TO_STREAM; ++i) { storedValue = RWData(DUMMY_BYTE); // verify our test pattern if (storedValue != PATTERN_BYTE_VALUE) { // if values aren't the same an error occurred, // turn off all leds, then sit and spin P1OUT &= ~BIT6; P1OUT &= ~DEBUG_PIN; while (1) { ; } } } }
  19. Like
    Rickta59 reacted to fj604 in Disconnect LED2 to use I2C on Launchpad   
    The SCK line for on MSP430G2231 is the same as P1.6, which is connected to LED2 on the Launchpad. SCK is supposed to be pulled up for I2C to work, therefore you will have to disconnect the jumper J5 - 1.
     
    If you do not, LED2 will glow a faint green as it is would be connected to VCC through a pullup, and I2C will not work at all.
     
    This took me a while to figure - I thought I'd share.
  20. Like
    Rickta59 reacted to SugarAddict in Layout collection   
    So here is the laziest thing ever...
     
    http://www.bluedragonfire.com/ee/Layouts/layouts.html
     
    But there's some layouts for ya.
  21. Like
    Rickta59 reacted to NatureTM in Value Line series easy DCO setting library   
    Here's an existing TI lib I modified to work with the Value Line series and CCS.
     
    Since the G series doesn't come with factory-calibrated DCO settings, I wanted an easy way to set the MCLK to 16MHz or some other arbitrary frequency. A TI library existed for setting the DCO using an external watch crystal as a reference, however it didn't work with the G series. It just took some minor editing.
    I think this should be nice for Launchpad owners especially, since the kit comes with an external crystal and a 16MHz rated chip.
     
    DCO Library: http://naturetm.com/files/Launchpad%20setDCO%20lib.rar
  22. Like
    Rickta59 reacted to zeke in Circuit Diagram Website   
    I regularly watch the RSS feed from this website: Electronic Circuit Diagram.
     
    There's some pretty interesting circuits there.
     
    I thought you all might like to follow it too.
  23. Like
    Rickta59 reacted to rockets4kids in MSP430 LaunchPad Book?   
    A definite second (or third or fourth) For the Davies book, but you are not sure about dropping the $40, be sure to watch the Launchpad Videos and then read through this tutorial:
     
    http://www.glitovsky.com/Tutorialv0_3.pdf
     
    That, combined with resources on the net, might just be enough to get you going.
  24. Like
    Rickta59 reacted to rockets4kids in MSPGCC support for newer Value Line parts?   
    There is a new development tree of mspgcc known as "Uniarch" whose goal is to reduce the effort required to add support for new chips. Apparently, adding support for new chips was a lot of work in current/previous versions. In any case, the first alpha release of Uniarch came out several weeks ago, and support for the complete set of Value Line chips was added earlier this week.
     
    There are no packages available, and you are going to need to pull the sources from git and compile it on your own, but fortunately it compiles quite easily under Linux and OS/X. I have not yet heard any reports one way or another from anyone who has attempted to compile it under mingw or cygwin.
     
    If you go this route, be aware that you are also going to need to pull the latest mspdebug sources from the git repository in order to program the new chips, and the gdb included with Uniarch is known to be broken. You should be able to use your existing gdb binary with the new toolchain.
     
    For details, check the past month's archives on mspgcc-users.
  25. Like
    Rickta59 got a reaction from bluehash in Monitoring temperatures up to ~500 degrees with the MSP430   
    I think the print head in the reprap 3d printer gets close to 450F. They use a thermistor and firmware to measure the temperature. I'm not sure what the upper range is for the thermistor I think around 250C. It might be just the ticket, they are inexpensive. You can find more info at http://reprap.org/wiki/Thermistor That page discusses the different ones they have used and some calculators.
     
    -rick
×
×
  • Create New...