Attempt at an octave generator for AVR
//https://hackaday.com/2018/05/24/ask-hackaday-diy-top-octave-generator/ | |
// I thought it would be interesting to see if some kind of time/space trade off could be done with this problem. | |
// It compiles but you probably need an ATMEGA1284 or better to run since it needs a little over 8k ram | |
// It should run in constant time. | |
// Don't have anything to test this on. | |
void setup() { | |
// put your setup code here, to run once: | |
} | |
// repl.it testing | |
/* | |
#include <stdio.h> | |
*/ | |
// bit mask for each note | |
const uint16_t note1 = 1<<0; | |
const uint16_t note2 = 1<<1; | |
const uint16_t note3 = 1<<2; | |
const uint16_t note4 = 1<<3; | |
const uint16_t note5 = 1<<4; | |
const uint16_t note6 = 1<<5; | |
const uint16_t note7 = 1<<6; | |
const uint16_t note8 = 1<<7; | |
const uint16_t note9 = 1<<8; | |
const uint16_t note10 = 1<<9; | |
const uint16_t note11 = 1<<10; | |
const uint16_t note12 = 1<<11; | |
// calculate the number of counts between pin toggles | |
const uint32_t clk = 2000000; | |
const uint16_t note1_period = clk/478; | |
const uint16_t note2_period = clk/451; | |
const uint16_t note3_period = clk/426; | |
const uint16_t note4_period = clk/402; | |
const uint16_t note5_period = clk/379; | |
const uint16_t note6_period = clk/358; | |
const uint16_t note7_period = clk/338; | |
const uint16_t note8_period = clk/319; | |
const uint16_t note9_period = clk/301; | |
const uint16_t note10_period = clk/284; | |
const uint16_t note11_period = clk/268; | |
const uint16_t note12_period = clk/253; | |
//const uint16_t note13_period = clk/239; | |
//Round up to the next highest power of 2 | |
uint16_t next_pow2( unsigned int v) { // compute the next highest power of 2 of 32-bit v | |
v--; | |
v |= v >> 1; | |
v |= v >> 2; | |
v |= v >> 4; | |
v |= v >> 8; | |
//v |= v >> 16; | |
v++; | |
return v; | |
} | |
// repl.it testing | |
/* | |
uint8_t PORTD = 0xFF; | |
uint8_t PORTB = 0xFF; | |
*/ | |
void loop() { | |
// lowest note sets the max period | |
const uint16_t scroll_length = next_pow2(note12_period)-1; | |
// circular buffer to store the toggle markers | |
//uint16_t scroll[scroll_length] = {0}; | |
uint16_t scroll[scroll_length]; | |
for( uint16_t i = 0 ; i < scroll_length ; i++ ) | |
{ | |
scroll[i] = 0; | |
} | |
// set starting index | |
uint16_t index = 0; | |
// set starting toggle markers | |
scroll[index] = 0xFFFF; | |
while(1) { | |
// fetch state | |
uint16_t state = scroll[index]; | |
// update port pins | |
PORTD ^= (state>>0)&0xFF; | |
PORTB ^= (state>>8)&0xFF; | |
// repl.it testing | |
/* | |
printf( "INDEX %d ", index ); | |
printf( "PORTD %X ", PORTD ); | |
printf( "PORTB %X\n", PORTB ); | |
printf( "BUFFER LENGTH %d ", scroll_length ); | |
printf( "STATE %X ", state ); | |
printf( "NEXT1 %d ", (index+note1_period)&scroll_length ); | |
printf( "NEXT2 %d\n", (index+note2_period)&scroll_length ); | |
*/ | |
// isolate each notes current toggle marker and | |
// insert it into the position in the future it next occurs | |
scroll[(index+note1_period)&scroll_length] |= state & note1; | |
scroll[(index+note2_period)&scroll_length] |= state & note2; | |
scroll[(index+note3_period)&scroll_length] |= state & note3; | |
scroll[(index+note4_period)&scroll_length] |= state & note4; | |
scroll[(index+note5_period)&scroll_length] |= state & note5; | |
scroll[(index+note6_period)&scroll_length] |= state & note6; | |
scroll[(index+note7_period)&scroll_length] |= state & note7; | |
scroll[(index+note8_period)&scroll_length] |= state & note8; | |
scroll[(index+note9_period)&scroll_length] |= state & note9; | |
scroll[(index+note10_period)&scroll_length] |= state & note10; | |
scroll[(index+note11_period)&scroll_length] |= state & note11; | |
scroll[(index+note12_period)&scroll_length] |= state & note12; | |
// clear handled bits and move to the next index | |
scroll[index++] = 0; | |
// wrap around at end of buffer | |
index &= scroll_length; | |
} | |
//return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment