Skip to content

Instantly share code, notes, and snippets.

@kbob
Last active May 30, 2019 18:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save kbob/6d886d63825c6ad0d29829e270f6ef9f to your computer and use it in GitHub Desktop.
Save kbob/6d886d63825c6ad0d29829e270f6ef9f to your computer and use it in GitHub Desktop.
// Ask Hackaday: How do you DIY a Top-Octave Generator?
// https://hackaday.com/2018/05/24/ask-hackaday-diy-top-octave-generator/?utm_source=feedburner
// Target Arduino Mega.
// N.B., Timer 1 has highest interrupt priority, so
// use it for the highest frequency oscillators.
// Note Comp Port/Pin Arduino Pin
// C OC1A PB5 pin 11
// B OC1B PB6 pin 12
// A# OC1C PB7 pin 13
// A OC3A PE3 pin 5
// G# OC3B PE4 pin 2
// G OC3C PE5 pin 3
// F# OC4A PH3 pin 6
// F OC4B PH4 pin 7
// E OC4C PH5 pin 8
// D# OC5A PL3 pin 46
// D OC5B PL4 pin 45
// C# OC5C PL5 pin 44
#define RND(a, b) (((a) + (b) / 2) / (b))
#define OCR1A_COUNT (RND(F_CPU, 8372))
#define OCR1B_COUNT (RND(F_CPU, 7902))
#define OCR1C_COUNT (RND(F_CPU, 7459))
#define OCR3A_COUNT (RND(F_CPU, 7040))
#define OCR3B_COUNT (RND(F_CPU, 6645))
#define OCR3C_COUNT (RND(F_CPU, 6272))
#define OCR4A_COUNT (RND(F_CPU, 5920))
#define OCR4B_COUNT (RND(F_CPU, 5588))
#define OCR4C_COUNT (RND(F_CPU, 5274))
#define OCR5A_COUNT (RND(F_CPU, 4978))
#define OCR5B_COUNT (RND(F_CPU, 4699))
#define OCR5C_COUNT (RND(F_CPU, 4435))
void setup()
{
// Start Timer/Counter 1.
TCCR1A = _BV(COM1A0) | _BV(COM1B0) | _BV(COM1C0);
TCCR1B = _BV(CS10);
TCCR1C = 0;
OCR1A = OCR1A_COUNT;
OCR1B = OCR1B_COUNT;
OCR1C = OCR1C_COUNT;
TIMSK1 = _BV(OCIE1C) | _BV(OCIE1B) | _BV(OCIE1A);
// Start Timer/Counter 3.
TCCR3A = _BV(COM3A0) | _BV(COM3B0) | _BV(COM3C0);
TCCR3B = _BV(CS30);
TCCR3C = 0;
OCR3A = OCR3A_COUNT;
OCR3B = OCR3B_COUNT;
OCR3C = OCR3C_COUNT;
TIMSK3 = _BV(OCIE3C) | _BV(OCIE3B) | _BV(OCIE3A);
// Start Timer/Counter 4.
TCCR4A = _BV(COM4A0) | _BV(COM4B0) | _BV(COM4C0);
TCCR4B = _BV(CS40);
TCCR4C = 0;
OCR4A = OCR4A_COUNT;
OCR4B = OCR4B_COUNT;
OCR4C = OCR4C_COUNT;
TIMSK4 = _BV(OCIE4C) | _BV(OCIE4B) | _BV(OCIE4A);
// Start Timer/Counter 5.
TCCR5A = _BV(COM5A0) | _BV(COM5B0) | _BV(COM5C0);
TCCR5B = _BV(CS50);
TCCR5C = 0;
OCR5A = OCR5A_COUNT;
OCR5B = OCR5B_COUNT;
OCR5C = OCR5C_COUNT;
TIMSK5 = _BV(OCIE5C) | _BV(OCIE5B) | _BV(OCIE5A);
// Enable output on pins.
DDRB |= _BV(DDB5);
DDRB |= _BV(DDB6);
DDRB |= _BV(DDB7);
DDRE |= _BV(DDE3);
DDRE |= _BV(DDE4);
DDRE |= _BV(DDE5);
DDRH |= _BV(DDH3);
DDRH |= _BV(DDH4);
DDRH |= _BV(DDH5);
DDRL |= _BV(DDL3);
DDRL |= _BV(DDL4);
DDRL |= _BV(DDL5);
// Disable millisecond timer.
TIMSK0 = 0;
}
void loop()
{
__asm__ ( "sleep" );
}
ISR(TIMER1_COMPA_vect)
{
OCR1A += OCR1A_COUNT;
}
ISR(TIMER1_COMPB_vect)
{
OCR1B += OCR1B_COUNT;
}
ISR(TIMER1_COMPC_vect)
{
OCR1C += OCR1C_COUNT;
}
ISR(TIMER3_COMPA_vect)
{
OCR3A += OCR3A_COUNT;
}
ISR(TIMER3_COMPB_vect)
{
OCR3B += OCR3B_COUNT;
}
ISR(TIMER3_COMPC_vect)
{
OCR3C += OCR3C_COUNT;
}
ISR(TIMER4_COMPA_vect)
{
OCR4A += OCR4A_COUNT;
}
ISR(TIMER4_COMPB_vect)
{
OCR4B += OCR4B_COUNT;
}
ISR(TIMER4_COMPC_vect)
{
OCR4C += OCR4C_COUNT;
}
ISR(TIMER5_COMPA_vect)
{
OCR5A += OCR5A_COUNT;
}
ISR(TIMER5_COMPB_vect)
{
OCR5B += OCR5B_COUNT;
}
ISR(TIMER5_COMPC_vect)
{
OCR5C += OCR5C_COUNT;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment