Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


Everything posted by NatureTM

  1. solved in IRC :-) thanks Rickta59! In usiTx(), replace "while(USICNT & 0x1F);" with "while(!(USIIFG & USICTL1));" Rickta found this in some example code. The only conclusion I can draw is that reading the USICNT interferes with its countdown. Any thoughts?
  2. Hey guys, I've got a problem with the USI I'm having trouble solving myself. When I send data out through the USI, I am getting extra clocks out. I.E. I set the usicnt to 10, the data shifts out normal, but after 10 bits of data out, the clock output continues to send a couple extra pulses. The number of extra pulses seems to vary between +1 through +4. Here's the code: the commented out stuff is mostly things I've tried to solve the issue. #include "msp430g2231.h" #include #define PIN_CS_0 BIT4 #define COLUMNS 32 #define HT1632_CMD_SYSDIS 0x00 /* CMD= 0000-0000-x Turn off oscil */ #define HT1632_CMD_SYSON 0x01 /* CMD= 0000-0001-x Enable system oscil */ #define HT1632_CMD_LEDOFF 0x02 /* CMD= 0000-0010-x LED duty cycle gen off */ #define HT1632_CMD_LEDON 0x03 /* CMD= 0000-0011-x LEDs ON */ #define HT1632_CMD_BLOFF 0x08 /* CMD= 0000-1000-x Blink OFF */ #define HT1632_CMD_BLON 0x09 /* CMD= 0000-1001-x Blink On */ #define HT1632_CMD_SLVMD 0x10 /* CMD= 0001-00xx-x Slave Mode */ #define HT1632_CMD_MSTMD 0x14 /* CMD= 0001-01xx-x Master Mode */ #define HT1632_CMD_RCCLK 0x18 /* CMD= 0001-10xx-x Use on-chip clock */ #define HT1632_CMD_EXTCLK 0x1C /* CMD= 0001-11xx-x Use external clock */ #define HT1632_CMD_COMS00 0x20 /* CMD= 0010-ABxx-x commons options */ #define HT1632_CMD_COMS01 0x24 /* CMD= 0010-ABxx-x commons options */ #define HT1632_CMD_COMS10 0x28 /* CMD= 0010-ABxx-x commons options */ #define HT1632_CMD_COMS11 0x2C //P-MOS OUTPUT AND 16COMMON OPTION /* CMD= 0010-ABxx-x commons options */ #define HT1632_CMD_PWM 0xA0 /* CMD= 101x-PPPP-x PWM duty cycle */ char image[COLUMNS]; void usiTx(char nBits, unsigned int data); void sendCommand(char csPin, char command); void drawScreen(char csPin, char * image); void checkerTest(); void main(){ unsigned int i; char data = 0xFF; DCOCTL = CALDCO_1MHZ; BCSCTL1 = CALBC1_1MHZ; // P1OUT |= 0xFF; // P1DIR |= 0xFF; P1DIR |= PIN_CS_0; WDTCTL = WDTPW + WDTHOLD; // Stop WDT USICTL0 |= USIPE6 + USIPE5; // enable USI data and clock output to port // USICTL0 |= USILSB; // output LSB first USICTL0 |= USIMST; // master mode (generate data clock) USICTL0 |= USIOE; // enable data output USICKCTL |= USISSEL_2; // clock the USI from SMCLK USICKCTL |= USIDIV_6; USICKCTL |= USICKPL; // data clock polarity switch USICNT |= USI16B; // enable transfer of > 8 bits USICTL0 &= ~USISWRST; // let the USI run drawScreen(PIN_CS_0, image); checkerTest(); sendCommand(PIN_CS_0, HT1632_CMD_SYSDIS); //sendOptionCommand(HT1632_CMD_MSTMD); sendCommand(PIN_CS_0, HT1632_CMD_SYSON); sendCommand(PIN_CS_0, HT1632_CMD_COMS10); sendCommand(PIN_CS_0, HT1632_CMD_LEDON); sendCommand(PIN_CS_0, HT1632_CMD_BLOFF); sendCommand(PIN_CS_0, HT1632_CMD_PWM+5); while(1){ drawScreen(PIN_CS_0, image); for(i = 0; i < 20000; i++); } } void usiTx(char nBits, unsigned int data){ // USICTL0 |= USISWRST; USISR = data; USICNT = (nBits | USI16B); // USICTL0 &= ~USISWRST; // let the USI run while(USICNT & 0x1F); // while(!USIIFG); } void sendCommand(char csPin, char command){ unsigned int txData = 0x8000; P1OUT &= ~csPin; USICTL0 &= ~USILSB; // output MSB first txData |= ((unsigned int)command << 5); usiTx(12, txData); // ???????? // while(USICNT & 0x1F); P1OUT |= csPin; } void drawScreen(char csPin, char * image){ char i; P1OUT &= ~csPin; USICTL0 |= USILSB; // output LSB first usiTx(10, 0x0005); for(i = 0; i < COLUMNS; i++){ usiTx(8, *image); image++; } // while(USICNT & 0x001F); P1OUT |= csPin; } void checkerTest(){ char i; for(i = 0; i < COLUMNS; i++){ image[i] = 0xAA >> (i % 2); } } Here it is in a text file which might be easier to read: http://naturetm.com/files/main.c.txt Here's a screenshot of my logic analyzer GUI. Ignore the duplicate lines. I just have them hooked up to be sure my 3.3 to 5 level shifter is working. This is output of the drawScreen() function. http://naturetm.com/files/logic_analyzer_ss.jpg Thanks to anyone who takes a look!
  3. That's cool! I don't know anything about amateur radio, so all I'm familiar with are old videos of people tapping on a switch.
  4. Update: This is still a work in progress, but I feel like showing some changes I've made. I wanted to make the synth polyphonic and try using a DAC, while keeping the code small enough to still fit on a G2231. For the DAC, I chose the MCP4725. I picked this one because it was the cheapest DAC-on-a-breakout from SparkFun. http://www.sparkfun.com/products/8736 I used some TI I2C example code to communicate with it. Since the I2C communications are using the USI, I needed a different way to get the serial MIDI data from the MIDI controller. I set up TimerA in capture mode, and triggered it on both rising and falling edges in the midi data. From that I could see how long the MIDI line was in a given state and thus how many 0's or 1's I got. (TimerA ticks in state / TimerA ticks per bit = number of bits.) My previous code using the USI was a mess, so I was happy to try something different. For the synth part, I have a function that takes the frequency and position within the wave, and returns an amplitude. To mix for polyphony, I just average the amplitudes of several of the waves and send the average to the DAC. The synth sounds pretty cruddy. There's several reasons for this, but it mostly boils down to a need for more free CPU time. A faster chip or more efficient code would help. I have ideas for the latter, but I may just take a completely different approach for the synth altogether. I think I'll start concentrating more on the actual sound, and less on seeing what I can squeeze from the chip. There are functions for square, triangle, and sawtooth waves, however all but square are too computationally expensive for polyphony. Here's the code -- you might want to copy/paste it into a bigger window (I really need to learn how to make a library): #include "msp430g2231.h" #include #define MCLK_FREQUENCY 16000000 #define MIDI_FREQUENCY 31250 #define PIN_MIDI_DATA BIT2 #define PIN_SPEAKER BIT4 #define MIDI_CHANNEL 0 // MIDI is 1-indexed so setting this to 0 is midi channel 1 #define MAX_POLYPHONY 7 #define WDT_DIVIDER 64 #define SCALE_SIZE 12 #define number_of_bytes 2 const unsigned long WDT_FREQUENCY = MCLK_FREQUENCY / WDT_DIVIDER; const unsigned int synthNotes[sCALE_SIZE] = {9956, 10548, 11175, 11840, 12544, 13290, 14080, 14917, 7902, 8372, 8869, 9397}; const unsigned int TICKS_PER_BIT = MCLK_FREQUENCY / MIDI_FREQUENCY; unsigned int wdtCounter = 0; char MST_Data[number_of_bytes] = {0x00, 0x00}; char SLV_Addr = 0xC0; char byteCount, Transmit = 0; volatile char I2C_State = 0; char newVelocity; char newNote; int noteIndex = 0; unsigned int wdtPeriodNotes[MAX_POLYPHONY]; unsigned int tNotes[MAX_POLYPHONY] = {0}; char notes[MAX_POLYPHONY] = {0}; char velocities[MAX_POLYPHONY] = {0}; bool midiRXBitState = true; char partialMidiData = 0xFF; bool haveNewMidiByte = false; char newMidiByte; void waitForMidiLoop(); void handleNoteOn(); void handleNoteOff(); void updateWaveTimes(); void synthProcess(); void mixToOutputArray(); void handleNoteEvent(); void shiftLeft(char index); void updateSynth(bool on); char getNoteIndex(char note); void addBits(unsigned int stateCount, bool state); void updateADC(void); void Setup_USI_Master_TX (void); void main(){ DCOCTL = CALDCO_16MHZ; BCSCTL1 = CALBC1_16MHZ; WDTCTL = WDTPW + WDTTMSEL + WDTIS1 + WDTIS0; IE1 |= WDTIE; TACTL |= TASSEL_2; // TACLK = SMCLK P1SEL |= PIN_MIDI_DATA; // Timer A compare input TACCTL1 |= CCIE + CAP + CM_3; // enable capture and interrupt on rising and falling edge TACCTL0 |= CCIE; // enable timeout interrupt TACCR0 = 9 * TICKS_PER_BIT; // should never have more than 8 bits P1OUT |= 0xC0; P1REN |= 0xC0; P1DIR = BIT0 + PIN_SPEAKER + BIT6 + BIT7; I2C_State = 0; // wasn't init'ing properly??? TACTL |= MC_1; // start Timer A _EINT(); // enable interrupts while(1){ waitForMidiLoop(); if(newMidiByte == (0x90 | MIDI_CHANNEL)){ haveNewMidiByte = false; handleNoteOn(); P1OUT ^= BIT0; } else if(newMidiByte == (0x80 | MIDI_CHANNEL)){ haveNewMidiByte = false; handleNoteOff(); } else haveNewMidiByte = false; } } void waitForMidiLoop(){ while(!haveNewMidiByte){ synthProcess(); } } // ################################################## // ################# Synth Stuff #################### void synthProcess(){ if(noteIndex){ updateWaveTimes(); if(haveNewMidiByte) return; mixToOutputArray(); if(haveNewMidiByte) return; // if(!I2C_State){ updateADC(); // } } } // basicly tracks our position within the waveform void updateWaveTimes(){ static unsigned int lastWdt = 0; char iNote; if(lastWdt != wdtCounter){ unsigned int wdtDelta = wdtCounter - lastWdt; lastWdt = wdtCounter; for(iNote = 0; iNote < noteIndex; iNote++){ tNotes[iNote] += wdtDelta; if(tNotes[iNote] >= wdtPeriodNotes[iNote]){ tNotes[iNote] = tNotes[iNote] - wdtPeriodNotes[iNote]; } } } } unsigned int triangle(unsigned int position, unsigned int wavelength){ unsigned int halfWavelength = wavelength / 2; if(position <= halfWavelength) return 0x0FFF * (unsigned long)position / halfWavelength; else return 0x0FFF - (0x0FFF * (unsigned long)(position - halfWavelength) / halfWavelength); } unsigned int sawtooth(unsigned int position, unsigned int wavelength){ return (unsigned long)position * 0x0FFF / wavelength; } // use this one for velocity sensitivity //unsigned int square(unsigned int position, unsigned int wavelength, char velocity){ // if(position > wavelength >> 1) // return 0x001F * velocity; // else // return 0; //} unsigned int square(unsigned int position, unsigned int wavelength){ if(position > wavelength >> 1) return 0x0FFF; else return 0; } // A fast but lo-fi digital mixer. void mixToOutputArray(){ char iSum; unsigned int sum = 0; for(iSum = 0; iSum < noteIndex; iSum++) sum += square(tNotes[iSum], wdtPeriodNotes[iSum]); // using waveforms other than square takes extra cpu time and can lead to unexpected results, // but they're there to mess with. (you may miss midi events and get crudd(y/ier) sound) // sum += triangle(tNotes[iSum], wdtPeriodNotes[iSum]); // sum += sawtooth(tNotes[iSum], wdtPeriodNotes[iSum]); // use this one for velocity sensitivity // sum += square(tNotes[iSum], wdtPeriodNotes[iSum], velocities[iSum]); // Hack to keep the volume more level if(noteIndex == 1) sum /= 2; else sum /= noteIndex; MST_Data[0] = 0x000F & (sum >> 8); MST_Data[1] = 0x00FF & sum; } unsigned int midiNoteToWdtPeriod(char midiNote){ return (WDT_FREQUENCY / (synthNotes[midiNote % 12] >> ((127 - midiNote) / 12))); } #pragma vector=WDT_VECTOR __interrupt void watchdog_timer(void){ wdtCounter++; } // ############################################### // ################# MIDI stuff ################## void handleNoteOn(){ do{ waitForMidiLoop(); if(newMidiByte & 0x80) break; newNote = newMidiByte; haveNewMidiByte = false; waitForMidiLoop(); if(newMidiByte & 0x80) break; newVelocity = newMidiByte; haveNewMidiByte = false; handleNoteEvent(); }while(1); } void handleNoteOff(){ do{ waitForMidiLoop(); if(newMidiByte & 0x80) break; newNote = newMidiByte; haveNewMidiByte = false; newVelocity = 0; handleNoteEvent(); }while(1); } void handleNoteEvent(){ if(newVelocity != 0){ // add a new note when the poly cache is full, replacing the oldest if(MAX_POLYPHONY == noteIndex){ shiftLeft(0); notes[MAX_POLYPHONY - 1] = newNote; velocities[MAX_POLYPHONY - 1] = newVelocity; wdtPeriodNotes[MAX_POLYPHONY - 1] = midiNoteToWdtPeriod(newNote); } // add a new note else{ notes[noteIndex] = newNote; velocities[noteIndex] = newVelocity; wdtPeriodNotes[noteIndex] = midiNoteToWdtPeriod(newNote); noteIndex++; } } else if(getNoteIndex(newNote) < MAX_POLYPHONY){ shiftLeft(getNoteIndex(newNote)); noteIndex -= 2; if(noteIndex >= 0){ noteIndex++; } else{ noteIndex = 0; // set DC offset to zero when no notes MST_Data[0] = 0; MST_Data[1] = 0; updateADC(); } } } // Shift all notes to the right of index left by one, // overwriting index and freeing a spot at the end of // the array void shiftLeft(char index){ int i; for(i = index; i < MAX_POLYPHONY - 1; i++){ notes[i] = notes[i + 1]; velocities[i] = velocities[i + 1]; wdtPeriodNotes[i] = wdtPeriodNotes[i + 1]; } } char getNoteIndex(char note){ int i; for(i = 0; i < MAX_POLYPHONY; i++) if(notes[i] == note) return i; return MAX_POLYPHONY + 1; } // add a new bit to the incomplete midi data variable void shiftInMSB(bool state){ if(state){ partialMidiData >>= 1; partialMidiData |= BIT7; } else{ partialMidiData >>= 1; } } // add the new midi data to the incomplete midi data variable void addBits(unsigned int stateCount, bool state){ while(stateCount > TICKS_PER_BIT / 2){ if(!(partialMidiData & BIT0)){ // are we shifting out the start bit? // if(haveNewMidiByte) // while(1); // catch when we miss midi data (for debugging) shiftInMSB(state); newMidiByte = partialMidiData; // if((newMidiByte != 0xFE) && (newMidiByte != 0xFF)) if(newMidiByte != 0xFE) haveNewMidiByte = true; partialMidiData = 0xFF; } else shiftInMSB(state); stateCount -= TICKS_PER_BIT; } } // CCR1 capture interrupt. Triggers on both edges, adds fresh midi data #pragma vector=TIMERA1_VECTOR __interrupt void CCR1_interrupt(void){ TAR = 0; TACCTL0 &= ~CCIFG; unsigned int tEdge = TACCR1; midiRXBitState = PIN_MIDI_DATA & P1IN; TAIV = 0; addBits(tEdge, !midiRXBitState); } // Like a timeout to add midi data if there's new data, but no edge in too long #pragma vector=TIMERA0_VECTOR __interrupt void CCR0_interrupt(void){ // don't add data if no partial data received, unless the new is all 0's if((partialMidiData != 0xFF) || !midiRXBitState) addBits(9 * TICKS_PER_BIT, midiRXBitState); // in case we captured an edge during this ISR, don't re-add these bits // in the CCR1 ISR TACCR1 = 0; } // ############################################################ // ###################### I2C ADC Stuff ####################### void updateADC(void){ Setup_USI_Master_TX(); USICTL1 |= USIIFG; // Set flag and start communication } void Data_TX (void){ USISRL = MST_Data[byteCount]; // Load data byte USICNT |= 0x08; // Bit counter = 8, start TX I2C_State = 10; // next state: receive data (N)Ack byteCount++; } void Setup_USI_Master_TX (void) { _DINT(); byteCount = 0; Transmit = 1; USICTL0 = USIPE6+USIPE7+USIMST+USISWRST; // Port & USI mode setup USICTL1 = USII2C+USIIE; // Enable I2C mode & USI interrupt USICKCTL = USIDIV_3+USISSEL_2+USICKPL; // USI clk: SCL = SMCLK/128 USICNT |= USIIFGCC; // Disable automatic clear control USICTL0 &= ~USISWRST; // Enable USI USICTL1 &= ~USIIFG; // Clear pending flag _EINT(); } // I2C handler for ADC adapted from TI example code. This runs pretty quick, // so hopefully it doen't clash with Midi input interrupts. #pragma vector = USI_VECTOR __interrupt void USI_TXRX (void) { switch(__even_in_range(I2C_State,14)) { case 0: // Generate Start Condition & send address to slave byteCount = 0; USISRL = 0x00; // Generate Start Condition... USICTL0 |= USIGE+USIOE; USICTL0 &= ~USIGE; USISRL = SLV_Addr; USICNT = (USICNT & 0xE0) + 0x08; // Bit counter = 8, TX Address I2C_State = 2; // next state: rcv address (N)Ack break; case 2: // Receive Address Ack/Nack bit USICTL0 &= ~USIOE; // SDA = input USICNT |= 0x01; // Bit counter=1, receive (N)Ack bit I2C_State = 4; // Go to next state: check (N)Ack break; case 4: // Process Address Ack/Nack & handle data TX USICTL0 |= USIOE; // SDA = output if (USISRL & 0x01) // If Nack received... { // Send stop... USISRL = 0x00; USICNT |= 0x01; // Bit counter=1, SCL high, SDA low I2C_State = 14; // Go to next state: generate Stop } else { // Ack received, TX data to slave... USISRL = MST_Data[byteCount]; // Load data byte USICNT |= 0x08; // Bit counter = 8, start TX I2C_State = 10; // next state: receive data (N)Ack byteCount++; } break; case 10: // Receive Data Ack/Nack bit USICTL0 &= ~USIOE; // SDA = input USICNT |= 0x01; // Bit counter = 1, receive (N)Ack bit I2C_State = 12; // Go to next state: check (N)Ack break; case 12: // Process Data Ack/Nack & send Stop USICTL0 |= USIOE; if (byteCount == number_of_bytes){// If last byte USISRL = 0x00; I2C_State = 14; // Go to next state: generate Stop USICNT |= 0x01; } // set count=1 to trigger next state else{ Data_TX(); // TX byte } break; case 14:// Generate Stop Condition USISRL = 0x0FF; // USISRL = 1 to release SDA USICTL0 |= USIGE; // Transparent latch enabled USICTL0 &= ~(USIGE+USIOE); // Latch/SDA output disabled I2C_State = 0; // Reset state machine for next xmt break; } USICTL1 &= ~USIIFG; // Clear pending flag } I was planning on entering this in the POTM, but it sounds so bad! My cats start meowing and scratching at the door when I play it! I think I will enter the original version, however. NOTE: There should be about a 190K resistor between the DAC and the amp in the schematic. Not entirely necessary, but will scale the DAC output down to something more reasonable for the LM386
  5. This is great! For some reason, I was under the false impression that Launchpad didn't have serial communications through USB. I feel like a kid with a new toy! Thanks! P.S. Just a heads up, I initially plugged the LP into a USB hub and the echo didn't work. Connecting directly to my box fixed the issue.
  6. +1 on random errors where I have to unplug/replug the launchpad into usb to upload/debug. At first I thought it might be related to in-circuit programming quirks, but I've since had it happen with a launchpad by itself. It's not a huge deal, just a common annoyance.
  7. NatureTM


    I guess you're right. I've been doing stuff with sound/ultrasound recently so it seems significant for me at the time, but I guess in most applications, PWM at a high enough frequency is good enough.
  8. NatureTM


    Excited! Feature highlights: 20PDIP for Launchpad 4 factory calibrated dco presets Two 16-Bit Timer_A With Three Capture/Compare Registers Up to 24 Touch-Sense-Enabled I/O Pins (but 16 on the PDIP) USCI instead of USI 16K flash on the G25xx series 512B RAM on the G25xx/G24xx Comparator ADC10 I'm most excited about the USCI. Wish there was a DAC. Is there a reason it's so rare to see in-package DAC's with microcontrollers?
  9. I'm assuming you don't have an interrupt service routine coded. Since you have the ADC interrupt enabled, when the ADC finishes, the cpu will exit LPM0 and the program will jump to where the ADC10 ISR should be. If there's nothing there, you'll get unexpected behavior. You could either put something in the interrupt vector, or don't enable the interrupt. Also, for "k = (ADC10MEM / 1024) * 8;" the ADC1MEM / 1024 is integer division, and the result is rounded down to the nearest whole number. The result of ADC1MEM / 1024 will always be between 0 and 1, but rounded down, so always 0. You can use algebra to change the code so it will work: "k = (ADC10MEM * 8) / 1024;" That answer will still be rounded down, but at least give a result from 0 to 8. "k = (char)((ADC10MEM / (float)1024) * 8 + 0.5);" will round appropriately, but will be slower. I've got some example code for the ADC10 I'll just copy over from my blog: #include "msp430g2231.h" #define ANALOG_PIN 1 unsigned int analogRead(){ ADC10CTL0 |= ADC10SC; while(ADC10CTL1 & ADC10BUSY); return ADC10MEM; } void analogPinSelect(unsigned int pin){ if(pin < 8){ ADC10CTL0 &= ~ENC; ADC10CTL1 = pin << 12; ADC10CTL0 = ADC10ON + ENC + ADC10SHT_0; } } void main(void){ unsigned int analogValue; DCOCTL = CALDCO_1MHZ; BCSCTL1 = CALBC1_1MHZ; WDTCTL = WDTPW + WDTHOLD; // read adc repeatedly analogPinSelect(ANALOG_PIN); while(1){ analogValue = analogRead(); } } You should be able to work off that example and get what you need.
  10. Apparently the acquisition will amount to TI controlling 17% of the analog market. Unless there's quite a few chips that are exclusive to TI and National, it should be cool for now. It does look like National is pretty profitable and would be much more so if TI were to take over administrative operations: TI National SG&A % of revenue 10.9 19.3 http://www.ti.com/corp/docs/investor/compinfo/ti-national-ir-presentation.pdf Despite what TI says, I doubt they will want to continue producing the National chips for too long. I would imagine they must be cannibalizing themselves on products for which both companies have an offering. Edit: Replaced "NXP" with "National." Thanks Zeke, I think I read misread NSC as NXP in that doc and just went with it.
  11. I released my first Android app about a week ago (3/26/11). It was a first project for getting my feet wet, but it turned out fairly well. I could probably help out on the Android end. Here's my app: https://market.android.com/details?id=com.halenka.lock&feature=search_result It took me awhile to make. I didn't have much experience with graphic design or gui coding. I think I'm up for a new challenge.
  12. Argh! You got me! I even thanked you. I take that back!
  13. Hey SugarAddict, what I told you on IRC last night was completely wrong. I was confused and talking about how the MSP430 reset pin is wired. Sorry!
  14. I just saw the article. Nice! Funny how when the author of the article makes a mistake on HaD, the audience loses all focus on the project. It seems like HaD readers really have the "kick 'em while they're down" spirit. I'd hate to write for HaD.
  15. I liked that you picked a relatively complex project. Good work!
  16. Hi TopHat! I'm trying to decide if a countdown to a 50'th birthday is something fun for, or a way to torture, your uncle. The fact that the LCD fits so nice is a good tidbit of information.
  17. Just the launchpad. Speaker negative to LP ground, and speaker positive to Timer A CCR1 output pin.
  18. Hey thanks doc, but I already bought the RFID keychanins from Parallax's site.
  19. Really nice. I bookmarked your page for when I'm ready to start tinkering with my evalbot. Thanks!
  20. I've got a couple snippets that are similar to arduino functions. I just assumed this stuff was already out there. Here's what I have for millis and delayMillis: #include "msp430g2231.h" #define MCLK_FREQUENCY 1000000 #define WDT_DIVIDER 512 const unsigned long WDT_FREQUENCY = MCLK_FREQUENCY / WDT_DIVIDER; volatile unsigned long wdtCounter = 0; unsigned long millis(){ return wdtCounter / ((float)WDT_FREQUENCY / 1000); } void delayMillis(unsigned long milliseconds){ // todo: handle rollover unsigned long wakeTime = wdtCounter + (milliseconds * WDT_FREQUENCY / 1000); while(wdtCounter < wakeTime); } void main(void){ DCOCTL = CALDCO_1MHZ; BCSCTL1 = CALBC1_1MHZ; WDTCTL = WDTPW + WDTTMSEL + WDTIS1; IE1 |= WDTIE; _BIS_SR(GIE); // toggle pin every second P1DIR |= BIT0; while(1){ P1OUT ^= BIT0; delayMillis(1000); } } #pragma vector=WDT_VECTOR __interrupt void watchdog_timer(void){ wdtCounter++; } And here's what I have for analogRead: #include "msp430g2231.h" #define ANALOG_PIN 4 unsigned int analogRead(){ ADC10CTL0 |= ADC10SC; while(ADC10CTL1 & ADC10BUSY); return ADC10MEM; } void analogPinSelect(unsigned int pin){ if(pin < 8){ ADC10CTL0 &= ~ENC; ADC10CTL1 = pin << 12; ADC10CTL0 = ADC10ON + ENC + ADC10SHT_0; } } void main(void){ unsigned int analogValue; DCOCTL = CALDCO_1MHZ; BCSCTL1 = CALBC1_1MHZ; WDTCTL = WDTPW + WDTHOLD; // read adc repeatedly analogPinSelect(ANALOG_PIN); while(1){ analogValue = analogRead(); } }
  21. This is my hobby! What I need is exercise. :-) I've been telling my girlfriend to distract me more!
  22. Could you have several preset time constants coded and use a switch to toggle between them at the beginning of, or during runtime? You could also turn a knob connected to a potentiometer and change the timing during runtime with that. I don't mean to sidestep your question, but the method you're suggesting just seems overly complicated and unusual, and I don't see it being the best solution except in some rare and very specific cases. You may very well be dealing with one such case, but I feel like I should mention some more common and possibly more practical solutions.
  23. My girlfriend and I both have flash cartridges for our DS'es. Discovering that wifi ftp server for the DS was really useful when I was trying to do some development on the DS. It's amazing how many games fit on an sd card. I didn't realize they sold them on DX. I probably could have saved a bunch of money. Speaking of DX, they always have very cheap high-(milli)wattage laser pointers, but they don't ship to the US. Does anyone know a source with comparable prices?
  24. Nah, I was just going to see when they came and left the litter box and send it to twitter. Maybe have some special messages if they're in there for awhile. It's just a goofy project to give myself a little entertainment.
  • Create New...