From 39e3c7b44734e066d7ab1518e5c42f59cbb7a1e7 Mon Sep 17 00:00:00 2001 From: Joachim Fenkes Date: Sun, 12 Aug 2012 23:24:58 +0200 Subject: [PATCH] cleanup, README, license for github --- LICENSE | 3 + README | 21 ++++++ avr/Makefile | 4 ++ avr/noiseplug.c | 111 ----------------------------- avr/noiseplug.s | 4 ++ avr/sound.c | 18 ----- avr/sound1.c | 180 ------------------------------------------------ avr/sound3.c | 35 ---------- noiseplug.nfo | 21 ++++++ win/main.cpp | 6 ++ 10 files changed, 59 insertions(+), 344 deletions(-) create mode 100644 LICENSE create mode 100644 README delete mode 100644 avr/noiseplug.c delete mode 100644 avr/sound.c delete mode 100644 avr/sound1.c delete mode 100644 avr/sound3.c create mode 100644 noiseplug.nfo diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0fc87d9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,3 @@ +This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License. +To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/3.0/ +or send a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA. diff --git a/README b/README new file mode 100644 index 0000000..136ba1f --- /dev/null +++ b/README @@ -0,0 +1,21 @@ +The Noiseplug + +An ATtiny9 microcontroller that plays a chiptune. +Because 32 bytes of RAM should be enough for everyone. + +There are two versions of the noiseplug program here: + win/ A win32/C version that I used to prototype the chiptune and the audio generation + avr/ The avr/asm version that makes up the ATtiny9 firmware + +Whenever I decided to change the algorithms to make them easier or smaller to code in asm, I first prototyped the change in the win32/C version to see if it would work. Thus, the C and asm versions are very much in sync with each other, so you can hold them side by side while you try and understand the uncommented gibberish I wrote ;) + +Also, I made a humongous amount of small commits so whenever something broke, I could go back to a known working state. It might be very interesting to check out the progression of changes, especially during the hot assembler coding phase at the hotel room between 11am and 6pm on Saturday. + +You will also see that during that last phase, for example, when I had the bass down pat, I put some more asm-related thought into the arpeggio part of the C prototype before implementing the arpeggio in asm. That way, I could then just write down the asm code line by line and it would work more or less on the first shot. I heartily recommend this approach to everyone going on a similar endeavour. + +If you want to try it on real hardware, just wire up pin 1 of an ATtiny9 (an ATtiny10 should also work) to the signal pin of an audio plug and connect the grounds together. The audio signal is generated by PWMing the supply voltage, so be sure your playback device can take 3V, or 5V if you power the uC from USB. + +Have fun with the source -- I had fun (well, most of the time ;) creating it! + +Signed + dojoe \ No newline at end of file diff --git a/avr/Makefile b/avr/Makefile index 705f557..6812951 100644 --- a/avr/Makefile +++ b/avr/Makefile @@ -1,3 +1,7 @@ +# This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License. +# To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/3.0/ +# or send a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA. + all: flash noiseplug.o: noiseplug.S diff --git a/avr/noiseplug.c b/avr/noiseplug.c deleted file mode 100644 index 97c4ead..0000000 --- a/avr/noiseplug.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * main.c - * - * Created on: 30.10.2011 - * Author: dojoe - */ - -#include -#include -#include -#include -#include -#include - -//register uint8_t int_ctr asm("r18"); -uint8_t int_ctr; - -#if defined(__AVR_ATmega32U4__) -ISR(TIMER0_OVF_vect) -#elif defined(__AVR_ATtiny9__) -ISR(TIM0_OVF_vect) -#else -#error "warghs" -#endif -{ - int_ctr = (int_ctr + 1) & 3; -} - -#define NOISEPLUG_BIATCH -#include "sound1.c" - -#if 0 -static inline uint8_t next_sample(const uint32_t t) -{ -// return t*(42&t>>10); -// return t*((42&t>>10)%14); -// return (t*5&t>>7)|(t*3&t>>10); -// return t*9&t>>4|t*5&t>>7|t*3&t/1024; -// return (t*9&t>>4|t*5&t>>7|t*3&t/1024)-1; -// return t>>4|t&((t>>5)/(t>>7-(t>>15)&-t>>7-(t>>15))); -// return (int)(t/1e7*t*t+t)%127|t>>4|t>>5|t%127+(t>>16)|t; - uint8_t a = t>>6&1?t>>5:-t>>4; - uint8_t b = t>>6^t>>8|t>>12|t&63; - - return random(); -// return ((t>>6^t>>8|t>>12|t&63)&127)+((t>>6&1?t>>6:-t>>5)&63); -// return t << 3; -} -#endif - -int main() -{ -#if defined(__AVR_ATmega32U4__) -#define SAMPLE_L OCR0A - clock_prescale_set(clock_div_2); - - DDRB = 1 << PB7 | 1 << PB2; // PB7 == OC0A - TCNT0 = 0; - OCR0A = 0; - TCCR0A = 3 << WGM00 | 2 << COM0A0; // Fast PWM mode, positive polarity - TCCR0B = 1 << CS00; // Select main clock, no prescaling - TIMSK0 = 1 << TOIE0; // enable overflow interrupt - TIFR0 = 1 << TOV0; // make sure it happens - - set_sleep_mode(SLEEP_MODE_IDLE); - sei(); -#elif defined(__AVR_ATtiny9__) -#define SAMPLE_L OCR0AL - - CCP = 0xD8; - CLKMSR = 0; - CCP = 0xD8; - CLKPSR = 0; - PUEB = 0; - DDRB = (1 << PB0) | (1 << PB2); - TCNT0 = 0; - OCR0A = 0; - TCCR0A = (1 << WGM00) | (2 << COM0A0); - TCCR0B = (1 << WGM02) | (1 << CS00); - TCCR0C = 0; - TIMSK0 = 1 << TOIE0; - - set_sleep_mode(SLEEP_MODE_IDLE); - sei(); - TIFR0 = 1 << TOV0; -#else -#error "not supported" -#endif - - uint8_t sample = 0; - -#ifdef __AVR_ATmega32U4__ - DDRE = 1 << PE6; - uint16_t t = 0; -#endif - - while (1) { - sleep_mode(); - if (int_ctr == 0) { - //PORTB = 1 << PB2; - SAMPLE_L = sample; - sample = next_sample(); - //PORTB = 0; - -#ifdef __AVR_ATmega32U4__ - PORTE = (t & 4096) ? 1 << PE6 : 0; - t++; -#endif - } - } -} diff --git a/avr/noiseplug.s b/avr/noiseplug.s index 2852e51..ee2a58a 100644 --- a/avr/noiseplug.s +++ b/avr/noiseplug.s @@ -1,3 +1,7 @@ +; This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License. +; To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/3.0/ +; or send a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA. + .global __vectors SREG = 0x3F diff --git a/avr/sound.c b/avr/sound.c deleted file mode 100644 index 481c1e7..0000000 --- a/avr/sound.c +++ /dev/null @@ -1,18 +0,0 @@ - - - - -int main(r) -{ - -unsigned short rnd = 13373; -while(1) -{ - unsigned char f1 = (rnd&(3<<13))>>13; - unsigned char f2 = (rnd&(3<<10))>>10; - rnd <<=1; - rnd |= f1^f2; - putchar(rnd); - -} -} diff --git a/avr/sound1.c b/avr/sound1.c deleted file mode 100644 index 1304007..0000000 --- a/avr/sound1.c +++ /dev/null @@ -1,180 +0,0 @@ -#include - -#ifndef PROGMEM -#define PROGMEM /* nix */ -#endif - -#define arpeggio_DELAY 128 - -#define BIT(x,n) (((x)&(1<<(n)))>>(n)) -#define SO(x) (sizeof((x))/sizeof(*(x))) - -#define A1 0 -#define As1 1 -#define B1 2 -#define C1 3 -#define Cs1 4 -#define D1 5 -#define Ds1 6 -#define E1 7 -#define F1 8 -#define Fs1 9 -#define G1 10 -#define Gs1 11 -#define A2 12 -#define Aa2 13 -#define B2 14 -#define C2 15 -#define Cs2 16 -#define D2 17 -#define Ds2 18 -#define E2 19 -#define F2 20 -#define Fs2 21 -#define G2 22 -#define Gs2 23 -#define HOLD 24 - -static const PROGMEM uint8_t sin[] = {0, 49, 97, 141, 180, 212, 235, 250, 254, 250, 235, 212, 180, 141, 97, 49 }; -static const PROGMEM uint8_t octave_delay[] = { 36, 34, 32, 31, 29, 27, 26, 24, 23, 22, 20, 19, 18, 17, 16, 15, 14, 14, 13, 12, 11, 11, 10, 10 }; -static const PROGMEM struct { uint8_t a; uint8_t b; } synth[] = { { 7, 6}, {7, 5}, {7,5}, {6,5} }; -static const PROGMEM uint8_t arpeggiobase[] = { 3, 4, 4, 5 }; -static const PROGMEM uint8_t bassdrum[] = { 1, 1, 1, 1 }; -static const PROGMEM uint8_t snare[] = { 1, 1, 1, 1 }; -static const PROGMEM uint8_t melody[] = -{ - D2, 0, D2, 0, 0, 0, 0, 0, D2, 0, - A1, 0, B1, 0, D2, 0, D2, 0, D2, 0 -}; - -static inline uint8_t next_note() -{ - - static uint8_t idx=0; - - const uint8_t v = melody[idx++]; - - if(idx == SO(melody)) - idx = 0; - - return v; -} - -static inline uint8_t next_rnd() -{ - static unsigned short rnd = 13373; - const uint8_t f1 = (rnd&(3<<13))>>13; - const uint8_t f2 = (rnd&(3<<10))>>10; - rnd <<=1; - rnd |= f1^f2; - - return sin[((uint8_t)rnd)%SO(sin)]; -} - -static inline uint8_t next_sin(const uint8_t step) -{ - static uint8_t sinoff=SO(sin)-1; - sinoff += step; - sinoff &= SO(sin) - 1; - return sin[sinoff]; -} - - -static inline uint8_t next_sample() -{ -static uint16_t t=0; - -static uint8_t t8=0; -static uint8_t barevent=0; -static uint8_t bars=0; - -static uint8_t pc = 0; -static uint8_t arpeggiocnt = 1; - -static uint8_t next_sin_time = 0; -static uint8_t current_tone = 0; -static uint8_t current_tone_base = 12; - -static unsigned short snaredelay; -static unsigned short bassdelay; - -static uint8_t synth1; -static uint8_t synth2; - -if(t%1024 == 0) -{ - // implicit rollover of t roughly every 2 seconds - if(t==0) t8 = 0; - else ++t8; - - // determine which note we're playing - barevent |= 8; - if(t8%2 == 0) barevent |= 4; - if(t8%4 == 0) barevent |= 2; - if(t8%8 == 0) barevent |= 1; -} -else barevent = 0; - -if(barevent & 8) -{ - current_tone = current_tone_base = next_note(); -} - -// increment bar counter -if(barevent & 1) ++bars; - -// increment pattern counter -if(bars % 8 == 0) -{ - ++pc; - pc %= SO(arpeggiobase); -} - -// increment arpeggio -if(t % arpeggio_DELAY == 0) -{ - // arpeggio - ++arpeggiocnt; - arpeggiocnt &= 3; - current_tone = current_tone_base + 4 * arpeggiocnt; -} - -// render synth - -synth1 = ((t&(t>>(synth[pc].a))) | (t&(t>>(synth[pc].b))) << 1); - -if(t == next_sin_time) -{ - next_sin_time += octave_delay[current_tone]; - synth2 = next_sin(5); -} - -// mix two synth lines -unsigned int mix = (synth1>>1) | (synth2>>1); - -// load or decrement snare delay -if(barevent & 8 && snare[pc]) snaredelay = 800; -else if(snaredelay > 0) --snaredelay; - -// add snare drum -if(snaredelay>0) mix = (next_rnd() & 7) << 3; - - -// load or decrement bass delay -if(barevent & 4 && bassdrum[pc]) bassdelay = 800; -else if(bassdelay > 0) --bassdelay; - -// add bass drum -if(bassdelay>0) mix = next_sin(1); - -++t; -// here comes the noize! -return mix; -} - -#ifndef NOISEPLUG_BIATCH -int main() -{ - while(1) putchar(next_sample()); -} -#endif diff --git a/avr/sound3.c b/avr/sound3.c deleted file mode 100644 index 320750f..0000000 --- a/avr/sound3.c +++ /dev/null @@ -1,35 +0,0 @@ - -#define SO(x) (sizeof((x))/sizeof(*(x))) - -static unsigned char sin[] = {0, 49, 97, 141, 180, 212, 235, 250, 254, 250, 235, 212, 180, 141, 97, 49 }; - -unsigned char getRand() -{ - static unsigned short rnd = 13373; - unsigned char f1 = (rnd&(3<<13))>>13; - unsigned char f2 = (rnd&(3<<10))>>10; - rnd <<=1; - rnd |= f1^f2; - return (unsigned char)(rnd&0x0f); -} - -static inline unsigned char rnd_adv() -{ - return sin[getRand()%SO(sin)]; -} - -static inline unsigned char sin_adv() -{ - static unsigned char sinoff=SO(sin)-1; - ++sinoff; - sinoff %= SO(sin); - return sin[sinoff]; -} - -int main() -{ - while(1) - { - putchar(sin_adv()); - } -} diff --git a/noiseplug.nfo b/noiseplug.nfo new file mode 100644 index 0000000..914e39f --- /dev/null +++ b/noiseplug.nfo @@ -0,0 +1,21 @@ + dojoe / shack + + presents + + THE NOISEPLUG! + +Two minutes of audio from 1k of +Flash and 32 Bytes of RAM. + +Brofists and Ponies to + lft for the obvious inspiration =) + smrrd for the camera work + psykon for last-minute video editing <3 + Evoke organizing for a great party! + YOU for showing interest in this. + +To play along at home: Take an ATtiny9, +connect pin 1 to an audio input, +flash noiseplug.hex. Have fun! + +http://shackspace.de/ diff --git a/win/main.cpp b/win/main.cpp index d3d411f..a8291b6 100644 --- a/win/main.cpp +++ b/win/main.cpp @@ -1,3 +1,9 @@ +/* +This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License. +To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/3.0/ +or send a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA. +*/ + #include #include #include