Last active
May 27, 2018 10:38
-
-
Save cactrot/451621c3b25c52284ab95e4c813f25a8 to your computer and use it in GitHub Desktop.
Attempt at an octave generator for AVR
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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