#include // -- The following values apply for a f/256 prescaler: // clock frequency = 16 MHz // scaled frequency = 62.5 kHz // scaled period = 16 us #define WIDTH 62 // 1 ms pulse width typedef struct impulse { int interval; // periods until next timer compare int intensity; // potmeter wiper setting (0-128) int repeat; // repeat count }; impulse pattern[] = { { 300, 64, 3}, { 150, 0, 1}, { 100, 16, 3}, { 150, 32, 6}, { 150, 0, 1}, { 450, 96, 2}, { 900, 128, 1} }; int npattern = sizeof(pattern)/sizeof(impulse); // -- SPI (mcp4131 digital potentiometer) byte address = 0x00; // address on chip int CS = 4; // chip select // -- write to mcp4131 digital potentiometer int digitalPotWrite(int value) { digitalWrite(CS, LOW); SPI.transfer(address); SPI.transfer(value); digitalWrite(CS, HIGH); } void setup() { // -- SPI setup pinMode (CS, OUTPUT); SPI.begin(); // -- timer1 setup cli(); // disable interrupts TCCR1A = 0; // stop timer as initialized ... TCCR1B = 0; // ... by Arduino IDE PORTB &= 0b11111011; // set pin 10 (OC1B) to zero DDRB |= 0b00000100; // set pin 10 (OC1B) as output TCCR1A |= 0b00100000; // clear OC1B on compare, set at bottom TCCR1A |= 0b00000011; // fast PWM TCCR1B = 4; // f/256 prescaler TCCR1B |= (1 << WGM12); // clear timer on compare match TCCR1B |= (1 << WGM13); // fast PWM TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt TIMSK1 |= (1 << OCIE1B); // enable timer compare interrupt TCNT1 = 0; // clear counter 1 OCR1A = WIDTH+1; // arbitrary first period OCR1B = OCR1A-WIDTH; // before reset sei(); // enable interrupts } // -- timer1 interrupts ISR(TIMER1_COMPB_vect) { static int seqno=0; static int interval, intensity=0, repeat=0; impulse pulse; // -- digital potentiometer digitalPotWrite(intensity); if (repeat==0) { pulse = pattern[seqno]; repeat = pulse.repeat; interval = pulse.interval; intensity = pulse.intensity; seqno = (++seqno)%npattern; } repeat--; // timer1 // -- these settings are effective after the next timer // -- compare interrupt. (double buffered registers) OCR1A = interval; OCR1B = OCR1A-WIDTH; } ISR(TIMER1_COMPA_vect) { digitalPotWrite(0); } void loop() { }