From 9bbd50c4f52889501cacc5b319a7ff5af776aeef Mon Sep 17 00:00:00 2001 From: Jonathan Wyss Date: Tue, 27 Feb 2024 12:42:35 +0100 Subject: [PATCH] First commit --- avr_adc.c | 52 ++++ avr_adc.h | 1 + avr_adc.o | Bin 0 -> 724 bytes fix_fft.c | 269 ++++++++++++++++++ fix_fft.h | 38 +++ fix_fft.o | Bin 0 -> 2804 bytes light_ws2812_AVR/Examples/Chained_writes.c | 52 ++++ light_ws2812_AVR/Examples/RGBW_blinky.c | 45 +++ light_ws2812_AVR/Examples/RGB_blinky.c | 38 +++ light_ws2812_AVR/Examples/Rainbow.c | 84 ++++++ light_ws2812_AVR/Light_WS2812/light_ws2812.c | 218 ++++++++++++++ light_ws2812_AVR/Light_WS2812/light_ws2812.h | 98 +++++++ light_ws2812_AVR/Light_WS2812/light_ws2812.o | Bin 0 -> 2620 bytes light_ws2812_AVR/Light_WS2812/ws2812_config.h | 34 +++ light_ws2812_AVR/Makefile | 40 +++ .../Objects/obj files go here.txt | 1 + main.c | 42 +++ main.eep | 1 + main.elf | Bin 0 -> 10500 bytes main.hex | 88 ++++++ main.o | Bin 0 -> 1148 bytes makefile | 223 +++++++++++++++ micronucleus | Bin 0 -> 51840 bytes 23 files changed, 1324 insertions(+) create mode 100644 avr_adc.c create mode 100644 avr_adc.h create mode 100644 avr_adc.o create mode 100644 fix_fft.c create mode 100644 fix_fft.h create mode 100644 fix_fft.o create mode 100644 light_ws2812_AVR/Examples/Chained_writes.c create mode 100644 light_ws2812_AVR/Examples/RGBW_blinky.c create mode 100644 light_ws2812_AVR/Examples/RGB_blinky.c create mode 100644 light_ws2812_AVR/Examples/Rainbow.c create mode 100644 light_ws2812_AVR/Light_WS2812/light_ws2812.c create mode 100644 light_ws2812_AVR/Light_WS2812/light_ws2812.h create mode 100644 light_ws2812_AVR/Light_WS2812/light_ws2812.o create mode 100644 light_ws2812_AVR/Light_WS2812/ws2812_config.h create mode 100644 light_ws2812_AVR/Makefile create mode 100644 light_ws2812_AVR/Objects/obj files go here.txt create mode 100644 main.c create mode 100644 main.eep create mode 100755 main.elf create mode 100644 main.hex create mode 100644 main.o create mode 100644 makefile create mode 100755 micronucleus diff --git a/avr_adc.c b/avr_adc.c new file mode 100644 index 0000000..d4e6213 --- /dev/null +++ b/avr_adc.c @@ -0,0 +1,52 @@ +//setup adc for an attiny85 +// +#include +#include"avr_adc.h" +#define _BS(bit) (1<JflWMqH=MuuPp1doAX3L^ul@`1s$5fdR=Dbo*K0dbt=F7=%D76U&O?6H}7)k{ROTg9G9{ z;^QF<9|$AJ)g8dp`7B>lF|Z47iR_rz2eH;lEfqiz2cH02%Q0A zm84dbFzBTumLxLhB^4Jl=q2ap=BDPAfLu&0mWKL^4XObYM<72yxgei_nTk+#%wQgJ zSV9C~@uSYbz`(%(iUWu^BFrItm^vM(d9cU^sS}1M0h1tgFpM0VAq)%*2N)O_K<)*_ sDGLJwg8%~q11FN5AOl1g85lf33@8Sf1!4-Ksf%G`U@!$qKru`m0K88}v;Y7A literal 0 HcmV?d00001 diff --git a/fix_fft.c b/fix_fft.c new file mode 100644 index 0000000..dcc5a9d --- /dev/null +++ b/fix_fft.c @@ -0,0 +1,269 @@ +#include +#include "fix_fft.h" + + +//#include depreacted + +/* fix_fft.c - Fixed-point in-place Fast Fourier Transform */ +/* + All data are fixed-point short integers, in which -32768 + to +32768 represent -1.0 to +1.0 respectively. Integer + arithmetic is used for speed, instead of the more natural + floating-point. + + For the forward FFT (time -> freq), fixed scaling is + performed to prevent arithmetic overflow, and to map a 0dB + sine/cosine wave (i.e. amplitude = 32767) to two -6dB freq + coefficients. The return value is always 0. + + For the inverse FFT (freq -> time), fixed scaling cannot be + done, as two 0dB coefficients would sum to a peak amplitude + of 64K, overflowing the 32k range of the fixed-point integers. + Thus, the fix_fft() routine performs variable scaling, and + returns a value which is the number of bits LEFT by which + the output must be shifted to get the actual amplitude + (i.e. if fix_fft() returns 3, each value of fr[] and fi[] + must be multiplied by 8 (2**3) for proper scaling. + Clearly, this cannot be done within fixed-point short + integers. In practice, if the result is to be used as a + filter, the scale_shift can usually be ignored, as the + result will be approximately correctly normalized as is. + + Written by: Tom Roberts 11/8/89 + Made portable: Malcolm Slaney 12/15/94 malcolm@interval.com + Enhanced: Dimitrios P. Bouras 14 Jun 2006 dbouras@ieee.org + Modified for 8bit values David Keller 10.10.2010 +*/ + + +#define N_WAVE 256 /* full length of Sinewave[] */ +#define LOG2_N_WAVE 8 /* log2(N_WAVE) */ + + + + +/* + Since we only use 3/4 of N_WAVE, we define only + this many samples, in order to conserve data space. +*/ + + +//typedef uint8_t PROGMEM prog_uint8_t; +const uint8_t Sinewave[N_WAVE-N_WAVE/4] PROGMEM = { +0, 3, 6, 9, 12, 15, 18, 21, +24, 28, 31, 34, 37, 40, 43, 46, +48, 51, 54, 57, 60, 63, 65, 68, +71, 73, 76, 78, 81, 83, 85, 88, +90, 92, 94, 96, 98, 100, 102, 104, +106, 108, 109, 111, 112, 114, 115, 117, +118, 119, 120, 121, 122, 123, 124, 124, +125, 126, 126, 127, 127, 127, 127, 127, + +127, 127, 127, 127, 127, 127, 126, 126, +125, 124, 124, 123, 122, 121, 120, 119, +118, 117, 115, 114, 112, 111, 109, 108, +106, 104, 102, 100, 98, 96, 94, 92, +90, 88, 85, 83, 81, 78, 76, 73, +71, 68, 65, 63, 60, 57, 54, 51, +48, 46, 43, 40, 37, 34, 31, 28, +24, 21, 18, 15, 12, 9, 6, 3, + +0, -3, -6, -9, -12, -15, -18, -21, +-24, -28, -31, -34, -37, -40, -43, -46, +-48, -51, -54, -57, -60, -63, -65, -68, +-71, -73, -76, -78, -81, -83, -85, -88, +-90, -92, -94, -96, -98, -100, -102, -104, +-106, -108, -109, -111, -112, -114, -115, -117, +-118, -119, -120, -121, -122, -123, -124, -124, +-125, -126, -126, -127, -127, -127, -127, -127, + +/*-127, -127, -127, -127, -127, -127, -126, -126, +-125, -124, -124, -123, -122, -121, -120, -119, +-118, -117, -115, -114, -112, -111, -109, -108, +-106, -104, -102, -100, -98, -96, -94, -92, +-90, -88, -85, -83, -81, -78, -76, -73, +-71, -68, -65, -63, -60, -57, -54, -51, +-48, -46, -43, -40, -37, -34, -31, -28, +-24, -21, -18, -15, -12, -9, -6, -3, */ +}; + + + + + + +/* + FIX_MPY() - fixed-point multiplication & scaling. + Substitute inline assembly for hardware-specific + optimization suited to a particluar DSP processor. + Scaling ensures that result remains 16-bit. +*/ +static inline char FIX_MPY(char a, char b) +{ + + //Serial.println(a); + //Serial.println(b); + + + /* shift right one less bit (i.e. 15-1) */ + int c = ((int)a * (int)b) >> 6; + /* last bit shifted out = rounding-bit */ + b = c & 0x01; + /* last shift + rounding bit */ + a = (c >> 1) + b; + + /* + Serial.println(Sinewave[3]); + Serial.println(c); + Serial.println(a); + while(1);*/ + + return a; +} + +/* + fix_fft() - perform forward/inverse fast Fourier transform. + fr[n],fi[n] are real and imaginary arrays, both INPUT AND + RESULT (in-place FFT), with 0 <= n < 2**m; set inverse to + 0 for forward transform (FFT), or 1 for iFFT. +*/ +int fix_fft(char fr[], char fi[], int m, int inverse) +{ + int mr, nn, i, j, l, k, istep, n, scale, shift; + char qr, qi, tr, ti, wr, wi; + + n = 1 << m; + + /* max FFT size = N_WAVE */ + if (n > N_WAVE) + return -1; + + mr = 0; + nn = n - 1; + scale = 0; + + /* decimation in time - re-order data */ + for (m=1; m<=nn; ++m) { + l = n; + do { + l >>= 1; + } while (mr+l > nn); + mr = (mr & (l-1)) + l; + + if (mr <= m) + continue; + tr = fr[m]; + fr[m] = fr[mr]; + fr[mr] = tr; + ti = fi[m]; + fi[m] = fi[mr]; + fi[mr] = ti; + } + + l = 1; + k = LOG2_N_WAVE-1; + while (l < n) { + if (inverse) { + /* variable scaling, depending upon data */ + shift = 0; + for (i=0; i 16383 || m > 16383) { + shift = 1; + break; + } + } + if (shift) + ++scale; + } else { + /* + fixed scaling, for proper normalization -- + there will be log2(n) passes, so this results + in an overall factor of 1/n, distributed to + maximize arithmetic accuracy. + */ + shift = 1; + } + /* + it may not be obvious, but the shift will be + performed on each data point exactly once, + during this pass. + */ + istep = l << 1; + for (m=0; m>= 1; + wi >>= 1; + } + for (i=m; i>= 1; + qi >>= 1; + } + fr[j] = qr - tr; + fi[j] = qi - ti; + fr[i] = qr + tr; + fi[i] = qi + ti; + } + } + --k; + l = istep; + } + return scale; +} + +/* + fix_fftr() - forward/inverse FFT on array of real numbers. + Real FFT/iFFT using half-size complex FFT by distributing + even/odd samples into real/imaginary arrays respectively. + In order to save data space (i.e. to avoid two arrays, one + for real, one for imaginary samples), we proceed in the + following two steps: a) samples are rearranged in the real + array so that all even samples are in places 0-(N/2-1) and + all imaginary samples in places (N/2)-(N-1), and b) fix_fft + is called with fr and fi pointing to index 0 and index N/2 + respectively in the original array. The above guarantees + that fix_fft "sees" consecutive real samples as alternating + real and imaginary samples in the complex array. +*/ +int fix_fftr(char f[], int m, int inverse) +{ + int i, N = 1<<(m-1), scale = 0; + char tt, *fr=f, *fi=&f[N]; + + if (inverse) + scale = fix_fft(fi, fr, m-1, inverse); + for (i=1; i //depreacted included in arduino.h + + + + +/* + fix_fft() - perform forward/inverse fast Fourier transform. + fr[n],fi[n] are real and imaginary arrays, both INPUT AND + RESULT (in-place FFT), with 0 <= n < 2**m; set inverse to + 0 for forward transform (FFT), or 1 for iFFT. +*/ +int fix_fft(char fr[], char fi[], int m, int inverse); + + + +/* + fix_fftr() - forward/inverse FFT on array of real numbers. + Real FFT/iFFT using half-size complex FFT by distributing + even/odd samples into real/imaginary arrays respectively. + In order to save data space (i.e. to avoid two arrays, one + for real, one for imaginary samples), we proceed in the + following two steps: a) samples are rearranged in the real + array so that all even samples are in places 0-(N/2-1) and + all imaginary samples in places (N/2)-(N-1), and b) fix_fft + is called with fr and fi pointing to index 0 and index N/2 + respectively in the original array. The above guarantees + that fix_fft "sees" consecutive real samples as alternating + real and imaginary samples in the complex array. +*/ +int fix_fftr(char f[], int m, int inverse); +static inline char FIX_MPY(char a,char b); + + + +#endif diff --git a/fix_fft.o b/fix_fft.o new file mode 100644 index 0000000000000000000000000000000000000000..2e3f4cf93bf031d4d2803dd0738850679872a2d3 GIT binary patch literal 2804 zcmb<-^>JflWMqH=MuuPp1do9sg_D6{CIbV530Q#!0~Z4)gZ?D@N&b`KC*@D7pVU8T z{-pJj_D?!L>Hehmlm1WQpDaK5{N($S&u+iBU2i)7wjWdO?dRWjcE1gyH=|~=RkPv) zg9i);l=zM1y{0mKv1!+C?|(o4y`q8R0~2?<3~7ls2MReIA9w%nh1exm$D{)zu5yq|D?!ubjN zC#;_^e?tF+`U&|H;wSh|u%Dnmfn%z6t4*uvRQ0KQ7?b#m<=Mo=*;zj9WK0Yw8iDlAYztcgDoV$&4EOmhwLt3mU&O7B>H6OlTIImNQXs`V_dh;Ix{_g3}Y4 z{o~{P|G$4P^`A>{8p8o~Mi-t?8HNV}5BNmoSy?_9K2Vl2%?ld2^cZ+{b9c7RYTXM} z{Z9P>T=g@4KWX3gvyAzT6|D>x?l6MXflQsl*umea-yuJfdoLr*2$}k+jmfqelRxx&iQ%~cA2@i4@ z8T1$qoZ-1E0}A6f#x*>9Wk6}gQ8bX1@xv^}6^#2Bk1{e`_{RuJk2<2ZtSleiYcPIM zcwq1VB8M#{F&wxLcDv8Sz{Z%#j?H@U_WnlG7!F`l%Q2OKnT?Z&Ur1C!MqWu(LtD?l z*v!(#-qFR~)5k9`I5Z+ECN3cCpW*KsJOJOyrQzIx~8VKuC5*d>gsB1YO1R$ zE6U4Ci;D{Kb91sX(o&KV;$osALW2YSd_3J<9PMo^&5RB7v^7+fJ`hDELt#c&a4^Jrc9nVp|7{Q ztFxoMt+l14xv8lU1Q^_%ovjo!-2Fl|6%38_jPwk^MF1LsTvo6!eEg3r&5Tl#FfcGP zFe6JdFf*_)a5FG4*uh0V{ug0jV6a8v%Q7%9*dy`P;A{}%<9{Ot1|(ZP{s*b;07-!{ zvg<(hvobg{Ffh1**z z8_UQL%fP^J1S|(47#R{77#PHmTV9dyn3Gy$Jd>#V>LmgNSL@+WGF)%QA zAjwxSFfh0v@j+?}koZju3=DIS`0We~40=fXZUzR1ASRI6Ak4@xfq{Xc2T6V^0|Ubv zB>CA43=Auf_zM{r7)~MamoYFf{6gZdW?*0tfJZAM!v+Qhh6_mYAX{OWnSqUAE0oi~ z#K0iLz{s!{$_It9AOkDIF(@BI2{14)oM&KQ0I3Dp3sTRJmRS*>mR6#d%n%YwV$drtDT2@$Fji4&PNH5(YDEcy zUQ%%}gI+;VetK?du3k!FNg{(@a(-@ZYF-J{7-A@pvp`vs4XPN_=2C;_Ekrp73I-Mi zNPK{lcCa%r%wS|-V2754AURM{GKTVDMnu6FAWcv?5EB&K9H8_E;xI5U;8Ldz)dNa% zAf+I6pnMBrgD}YLAleeD4pw1Eu`n<|lO9MKTwa6Jf-uZ1kc0sXB(HKS0Tv i6Ul8LbsN|i7;b +#include +#include +#include "light_ws2812.h" + +struct cRGB led[2]; + +int main(void) +{ + + uint8_t pos=0; + uint8_t direction=1; + uint8_t i; + + #ifdef __AVR_ATtiny10__ + CCP=0xD8; // configuration change protection, write signature + CLKPSR=0; // set cpu clock prescaler =1 (8Mhz) (attiny 4/5/9/10) + #endif + + led[0].r=16;led[0].g=00;led[0].b=00; // LED 0 is red + led[1].r=16;led[1].g=16;led[1].b=16; // LED 1 is White + + while(1) + { + + for (i=0; i +#include +#include +#include "light_ws2812.h" + +struct cRGBW led[1]; + +int main(void) +{ + #ifdef __AVR_ATtiny10__ + CCP=0xD8; // configuration change protection, write signature + CLKPSR=0; // set cpu clock prescaler =1 (8Mhz) (attiny 4/5/9/10) + #endif + + while(1) + { + led[0].r=128;led[0].g=00;led[0].b=0;led[0].w=0; // Write red to array + ws2812_setleds_rgbw(led,1); + _delay_ms(500); // wait for 500ms. + + led[0].r=0;led[0].g=128;led[0].b=0;led[0].w=0; // green + ws2812_setleds_rgbw(led,1); + _delay_ms(500); + + led[0].r=0;led[0].g=0;led[0].b=128;led[0].w=0; // blue + ws2812_setleds_rgbw(led,1); + _delay_ms(500); + + led[0].r=0;led[0].g=0;led[0].b=0;led[0].w=128; // white + ws2812_setleds_rgbw(led,1); + _delay_ms(500); + + } +} diff --git a/light_ws2812_AVR/Examples/RGB_blinky.c b/light_ws2812_AVR/Examples/RGB_blinky.c new file mode 100644 index 0000000..dfa92bb --- /dev/null +++ b/light_ws2812_AVR/Examples/RGB_blinky.c @@ -0,0 +1,38 @@ +/* +* Light_WS2812 library example - RGB_blinky +* +* cycles one LED through red, green, blue +* +* This example is configured for a ATtiny85 with PLL clock fuse set and +* the WS2812 string connected to PB4. +*/ + +#include +#include +#include +#include "light_ws2812.h" + +struct cRGB led[1]; + +int main(void) +{ + #ifdef __AVR_ATtiny10__ + CCP=0xD8; // configuration change protection, write signature + CLKPSR=0; // set cpu clock prescaler =1 (8Mhz) (attiny 4/5/9/10) + #endif + + while(1) + { + led[0].r=255;led[0].g=00;led[0].b=0; // Write red to array + ws2812_setleds(led,1); + _delay_ms(500); // wait for 500ms. + + led[0].r=0;led[0].g=255;led[0].b=0; // green + ws2812_setleds(led,1); + _delay_ms(500); + + led[0].r=0;led[0].g=00;led[0].b=255; // blue + ws2812_setleds(led,1); + _delay_ms(500); + } +} diff --git a/light_ws2812_AVR/Examples/Rainbow.c b/light_ws2812_AVR/Examples/Rainbow.c new file mode 100644 index 0000000..0f52578 --- /dev/null +++ b/light_ws2812_AVR/Examples/Rainbow.c @@ -0,0 +1,84 @@ +/* + * + * This example is configured for a Atmega32 at 16MHz + */ + +#include +#include +#include +#include "light_ws2812.h" + +#define MAXPIX 30 +#define COLORLENGTH (MAXPIX/2) +#define FADE (256/COLORLENGTH) + +struct cRGB colors[8]; +struct cRGB led[MAXPIX]; + +int main(void) +{ + + uint8_t j = 1; + uint8_t k = 1; + + DDRB|=_BV(ws2812_pin); + + uint8_t i; + for(i=MAXPIX; i>0; i--) + { + led[i-1].r=0;led[i-1].g=0;led[i-1].b=0; + } + + //Rainbowcolors + colors[0].r=150; colors[0].g=150; colors[0].b=150; + colors[1].r=255; colors[1].g=000; colors[1].b=000;//red + colors[2].r=255; colors[2].g=100; colors[2].b=000;//orange + colors[3].r=100; colors[3].g=255; colors[3].b=000;//yellow + colors[4].r=000; colors[4].g=255; colors[4].b=000;//green + colors[5].r=000; colors[5].g=100; colors[5].b=255;//light blue (türkis) + colors[6].r=000; colors[6].g=000; colors[6].b=255;//blue + colors[7].r=100; colors[7].g=000; colors[7].b=255;//violet + + while(1) + { + //shift all vallues by one led + uint8_t i=0; + for(i=MAXPIX; i>1; i--) + led[i-1]=led[i-2]; + //change colour when colourlength is reached + if(k>COLORLENGTH) + { + j++; + if(j>7) + { + j=0; + } + + k=0; + } + k++; + //loop colouers + + //fade red + if(led[0].r<(colors[j].r-FADE)) + led[0].r+=FADE; + + if(led[0].r>(colors[j].r+FADE)) + led[0].r-=FADE; + + if(led[0].g<(colors[j].g-FADE)) + led[0].g+=FADE; + + if(led[0].g>(colors[j].g+FADE)) + led[0].g-=FADE; + + if(led[0].b<(colors[j].b-FADE)) + led[0].b+=FADE; + + if(led[0].b>(colors[j].b+FADE)) + led[0].b-=FADE; + + _delay_ms(10); + ws2812_sendarray((uint8_t *)led,MAXPIX*3); + } +} diff --git a/light_ws2812_AVR/Light_WS2812/light_ws2812.c b/light_ws2812_AVR/Light_WS2812/light_ws2812.c new file mode 100644 index 0000000..d05bc3a --- /dev/null +++ b/light_ws2812_AVR/Light_WS2812/light_ws2812.c @@ -0,0 +1,218 @@ +/* +* light weight WS2812 lib V2.5b +* +* Controls WS2811/WS2812/WS2812B RGB-LEDs +* Author: Tim (cpldcpu@gmail.com) +* +* Jan 18th, 2014 v2.0b Initial Version +* Nov 29th, 2015 v2.3 Added SK6812RGBW support +* Nov 11th, 2023 v2.5 Added support for ports that cannot be addressed with "out" +* Added LGT8F88A support +* +* License: GNU GPL v2+ (see License.txt) +*/ + +#include "light_ws2812.h" +#include +#include +#include + +// Normally ws2812_sendarray_mask() runs under disabled-interrupt condition, +// undefine if you want to accept interrupts in that function. +#define interrupt_is_disabled + +// Setleds for standard RGB +void inline ws2812_setleds(struct cRGB *ledarray, uint16_t leds) +{ + ws2812_setleds_pin(ledarray,leds, _BV(ws2812_pin)); +} + +void inline ws2812_setleds_pin(struct cRGB *ledarray, uint16_t leds, uint8_t pinmask) +{ + ws2812_sendarray_mask((uint8_t*)ledarray,leds+leds+leds,pinmask); + _delay_us(ws2812_resettime); +} + +// Setleds for SK6812RGBW +void inline ws2812_setleds_rgbw(struct cRGBW *ledarray, uint16_t leds) +{ + ws2812_sendarray_mask((uint8_t*)ledarray,leds<<2,_BV(ws2812_pin)); + _delay_us(ws2812_resettime); +} + +void ws2812_sendarray(uint8_t *data,uint16_t datlen) +{ + ws2812_sendarray_mask(data,datlen,_BV(ws2812_pin)); +} + +/* + This routine writes an array of bytes with RGB values to the Dataout pin + using the fast 800kHz clockless WS2811/2812 protocol. +*/ + +// Timing in ns +#define w_zeropulse 350 +#define w_onepulse 900 +#define w_totalperiod 1250 + +// Fixed cycles used by the inner loop +#if defined(__LGT8F__) +#define w_fixedlow 4 +#define w_fixedhigh 6 +#define w_fixedtotal 10 +#else +#define w_fixedlow 3 +#define w_fixedhigh 6 +#define w_fixedtotal 10 +#endif + +// // Fixed cycles used by the inner loop +// #define w_fixedlow 2 +// #define w_fixedhigh 4 +// #define w_fixedtotal 8 + +// Insert NOPs to match the timing, if possible +#define w_zerocycles (((F_CPU/1000)*w_zeropulse )/1000000) +#define w_onecycles (((F_CPU/1000)*w_onepulse +500000)/1000000) +#define w_totalcycles (((F_CPU/1000)*w_totalperiod +500000)/1000000) + +// w1 - nops between rising edge and falling edge - low +#define w1 (w_zerocycles-w_fixedlow) +// w2 nops between fe low and fe high +#define w2 (w_onecycles-w_fixedhigh-w1) +// w3 nops to complete loop +#define w3 (w_totalcycles-w_fixedtotal-w1-w2) + +#if w1>0 + #define w1_nops w1 +#else + #define w1_nops 0 +#endif + +// The only critical timing parameter is the minimum pulse length of the "0" +// Warn or throw error if this timing can not be met with current F_CPU settings. +#define w_lowtime ((w1_nops+w_fixedlow)*1000000)/(F_CPU/1000) +#if w_lowtime>550 + #error "Light_ws2812: Sorry, the clock speed is too low. Did you set F_CPU correctly?" +#elif w_lowtime>450 + #warning "Light_ws2812: The timing is critical and may only work on WS2812B, not on WS2812(S)." + #warning "Please consider a higher clockspeed, if possible" +#endif + +#if w2>0 +#define w2_nops w2 +#else +#define w2_nops 0 +#endif + +#if w3>0 +#define w3_nops w3 +#else +#define w3_nops 0 +#endif + +#define w_nop1 "nop \n\t" +#ifdef interrupt_is_disabled +#define w_nop2 "brid .+0 \n\t" +#else +#define w_nop2 "brtc .+0 \n\t" +#endif +#define w_nop4 w_nop2 w_nop2 +#define w_nop8 w_nop4 w_nop4 +#define w_nop16 w_nop8 w_nop8 + +void inline ws2812_sendarray_mask(uint8_t *data,uint16_t datlen,uint8_t maskhi) +{ + uint8_t curbyte,ctr,masklo; + uint8_t sreg_prev; + uint8_t *port = (uint8_t*) _SFR_MEM_ADDR(ws2812_PORTREG); + + ws2812_DDRREG |= maskhi; // Enable output + + masklo =~maskhi&ws2812_PORTREG; + maskhi |= ws2812_PORTREG; + + sreg_prev=SREG; +#ifdef interrupt_is_disabled + cli(); +#endif + + while (datlen--) { + curbyte=*data++; + + asm volatile( + " ldi %0,8 \n\t" +#ifndef interrupt_is_disabled + " clt \n\t" +#endif + "loop%=: \n\t" + " st X,%3 \n\t" // '1' [02] '0' [02] - re + +#if (w1_nops&1) +w_nop1 +#endif +#if (w1_nops&2) +w_nop2 +#endif +#if (w1_nops&4) +w_nop4 +#endif +#if (w1_nops&8) +w_nop8 +#endif +#if (w1_nops&16) +w_nop16 +#endif +#if defined(__LGT8F__) + " bst %1,7 \n\t" // '1' [02] '0' [02] + " brts 1f \n\t" // '1' [04] '0' [03] + " st X,%4 \n\t" // '1' [--] '0' [04] - fe-low + "1: lsl %1 \n\t" // '1' [05] '0' [05] +#else + " sbrs %1,7 \n\t" // '1' [04] '0' [03] + " st X,%4 \n\t" // '1' [--] '0' [05] - fe-low + " lsl %1 \n\t" // '1' [05] '0' [06] +#endif +#if (w2_nops&1) + w_nop1 +#endif +#if (w2_nops&2) + w_nop2 +#endif +#if (w2_nops&4) + w_nop4 +#endif +#if (w2_nops&8) + w_nop8 +#endif +#if (w2_nops&16) + w_nop16 +#endif + " brcc skipone%= \n\t" // '1' [+1] '0' [+2] - + " st X,%4 \n\t" // '1' [+3] '0' [--] - fe-high + "skipone%=: " // '1' [+3] '0' [+2] - +#if (w3_nops&1) +w_nop1 +#endif +#if (w3_nops&2) +w_nop2 +#endif +#if (w3_nops&4) +w_nop4 +#endif +#if (w3_nops&8) +w_nop8 +#endif +#if (w3_nops&16) +w_nop16 +#endif + + " dec %0 \n\t" // '1' [+4] '0' [+3] + " brne loop%=\n\t" // '1' [+5] '0' [+4] + : "=&d" (ctr) + : "r" (curbyte), "x" (port), "r" (maskhi), "r" (masklo) + ); + } + + SREG=sreg_prev; +} diff --git a/light_ws2812_AVR/Light_WS2812/light_ws2812.h b/light_ws2812_AVR/Light_WS2812/light_ws2812.h new file mode 100644 index 0000000..91388c1 --- /dev/null +++ b/light_ws2812_AVR/Light_WS2812/light_ws2812.h @@ -0,0 +1,98 @@ +/* + * light weight WS2812 lib include + * + * Version 2.3 - Nev 29th 2015 + * Author: Tim (cpldcpu@gmail.com) + * + * Please do not change this file! All configuration is handled in "ws2812_config.h" + * + * License: GNU GPL v2+ (see License.txt) + + + */ + +#ifndef LIGHT_WS2812_H_ +#define LIGHT_WS2812_H_ + +#include "ws2812_config.h" +#include +#include + +/////////////////////////////////////////////////////////////////////// +// Define Reset time in µs. +// +// This is the time the library spends waiting after writing the data. +// +// WS2813 needs 300 µs reset time +// WS2812 and clones only need 50 µs +// +/////////////////////////////////////////////////////////////////////// +#if !defined(ws2812_resettime) +#define ws2812_resettime 300 +#endif + +/////////////////////////////////////////////////////////////////////// +// Define I/O pin +/////////////////////////////////////////////////////////////////////// +#if !defined(ws2812_port) +#define ws2812_port B // Data port +#endif + +#if !defined(ws2812_pin) +#define ws2812_pin 0 // Data out pin +#endif + +/* + * Structure of the LED array + * + * cRGB: RGB for WS2812S/B/C/D, SK6812, SK6812Mini, SK6812WWA, APA104, APA106 + * cRGBW: RGBW for SK6812RGBW + */ + +struct cRGB { uint8_t g; uint8_t r; uint8_t b; }; +struct cRGBW { uint8_t g; uint8_t r; uint8_t b; uint8_t w;}; + + + +/* User Interface + * + * Input: + * ledarray: An array of GRB data describing the LED colors + * number_of_leds: The number of LEDs to write + * pinmask (optional): Bitmask describing the output bin. e.g. _BV(PB0) + * + * The functions will perform the following actions: + * - Set the data-out pin as output + * - Send out the LED data + * - Wait 50µs to reset the LEDs + */ + +void ws2812_setleds (struct cRGB *ledarray, uint16_t number_of_leds); +void ws2812_setleds_pin (struct cRGB *ledarray, uint16_t number_of_leds,uint8_t pinmask); +void ws2812_setleds_rgbw(struct cRGBW *ledarray, uint16_t number_of_leds); + +/* + * Old interface / Internal functions + * + * The functions take a byte-array and send to the data output as WS2812 bitstream. + * The length is the number of bytes to send - three per LED. + */ + +void ws2812_sendarray (uint8_t *array,uint16_t length); +void ws2812_sendarray_mask(uint8_t *array,uint16_t length, uint8_t pinmask); + + +/* + * Internal defines + */ +#if !defined(CONCAT) +#define CONCAT(a, b) a ## b +#endif + +#if !defined(CONCAT_EXP) +#define CONCAT_EXP(a, b) CONCAT(a, b) +#endif + +#define ws2812_PORTREG CONCAT_EXP(PORT,ws2812_port) +#define ws2812_DDRREG CONCAT_EXP(DDR,ws2812_port) + +#endif /* LIGHT_WS2812_H_ */ diff --git a/light_ws2812_AVR/Light_WS2812/light_ws2812.o b/light_ws2812_AVR/Light_WS2812/light_ws2812.o new file mode 100644 index 0000000000000000000000000000000000000000..bb060e7e1d55b8b9e2d61ab7404296d512632cfa GIT binary patch literal 2620 zcmb<-^>JflWMqH=MuuPp1doB?3I_wjOa=x96R-je22KVJhB=I<8N)Y+Xov64*c_rC zFf~j$W3!uf{`MbJn)oNnuXw!SfrhvxJL8x9{Tx$&G8Rsp&-mhj&twJ$_Aj_$`Tv;7 z<@~tiK{5;g#xD#9K(0%EQ1F1^!XCzxj0_iAo^?%S{K7HS;UU9;H2!jV z5O#QoD$d~U>};i=;qDizsbFZVXQXEU_AVNM94;&jAO9muGoyqW0|PSyGqN-TGXo2Q z00RSq9bEL|e@O-g23sV)5(5K+JrZ9V&IU0){x@e}K(giIe;0VXfaDn&ycrl6tUydK zhVX5`Y!CtABkYIp9Y9iG4B|2Jpz*!X_&#WSKQw*- z8b1h)AA-h@LF31v@e|PaNof2OG=3TyKLd@Qg~rc8 zz`#(0#0Q0U9U8v@jo*aEZ$aa?q47J=_+4oH9yER*8h-*Be-avh3L1YJ8h-{7Kazog zK?jK+%fP?@$`cSFMutQN28Im~4mka#GcYimK;pxh450kS%8&~cn8(1tAjH7P(9FQV z0Afo(`3Sc#fb-^j1_p+03=9k`Q2BKX3=F#%7#KvL{6h>34Cj#K8FDhyGfLvii;XM{ zjr5Wk;^Tt@;yvQyAq*b~BgoYq%qYn%h%ZV_2eYeEi}InIoc#O(V-p4+14f48?977v zyi{Wo20b5R20b4m20b4`CPOf3!~n4+zBn~6C9$X|u`)h4u{awcT9T8RQXF59na23_Bh(QfyU{GUVU|<3jGz<(379ch^BoIO63KI{64JuQZcp+?1 zdBVg8VS~yNCVmJTRE{u#3Ooh|22dHoBnS})l^;w(5H_gnU=oI~LFEP$D4-b_7(itP zlPE+SR9-NNLD-_6I7ToFff412PP?q8c^B5Bn@GM$^|AF z2pd!;Fv&vLpz?r84#EbN1x)e~HmDq6Qh=~QWdM^Rgbm97OwdFL%KJ>p5OGkxXHtQ% zL3y4@6~YGPcP3DvGB7ZJ@;Z|`L>!dQnKU45P#$N}gs?&Rn@J182IXxgXe9v3*G$mN z0m{=%x)3#>{LG{WVT1BAlRktE%EwI5S`3tjnG7M~p!~~Z1Yv{nE|W2Y4a&DnkV>8b zlxLYtA>yDs!ejun99#xKysk00g7f2A6E0TfjA%yPz>XOqLBmSSEx8Hb)YB%>48Qg14tb-yMT3q zObjects/$@.lss + +.PHONY: clean + +clean: + rm -f *.hex Objects/*.o Objects/*.lss diff --git a/light_ws2812_AVR/Objects/obj files go here.txt b/light_ws2812_AVR/Objects/obj files go here.txt new file mode 100644 index 0000000..7b4d68d --- /dev/null +++ b/light_ws2812_AVR/Objects/obj files go here.txt @@ -0,0 +1 @@ +empty \ No newline at end of file diff --git a/main.c b/main.c new file mode 100644 index 0000000..4d9b340 --- /dev/null +++ b/main.c @@ -0,0 +1,42 @@ +#define F_CPU 1000000UL + +#include +#include +#include"fix_fft.h" +#include"avr_adc.h" +#include"light_ws2812_AVR/Light_WS2812/ws2812_config.h" +#include"light_ws2812_AVR/Light_WS2812/light_ws2812.h" + + +#define STARTADC ADCSRA |= _BS(ADSC) +#define PB_mic PB0 + +int main (void) +{ + int i; + char sample[128]; + char im[128]; + struct cRGB led_bar1[1]; + //DDRB = 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 literal 0 HcmV?d00001 diff --git a/main.hex b/main.hex new file mode 100644 index 0000000..8798d76 --- /dev/null +++ b/main.hex @@ -0,0 +1,88 @@ +:100000006EC075C074C073C072C071C070C06FC064 +:100010006EC06DC06CC06BC06AC069C068C00003B0 +:1000200006090C0F1215181C1F2225282B2E303301 +:1000300036393C3F414447494C4E515355585A5C20 +:100040005E60626466686A6C6D6F707273757677F5 +:1000500078797A7B7C7C7D7E7E7F7F7F7F7F7F7FD0 +:100060007F7F7F7F7E7E7D7C7C7B7A7978777675DB +:100070007372706F6D6C6A68666462605E5C5A5819 +:100080005553514E4C494744413F3C393633302E4D +:100090002B2825221F1C1815120F0C09060300FD22 +:1000A000FAF7F4F1EEEBE8E4E1DEDBD8D5D2D0CD1F +:1000B000CAC7C4C1BFBCB9B7B4B2AFADABA8A6A4E0 +:1000C000A2A09E9C9A9896949391908E8D8B8A89EB +:1000D00088878685848483828281818181811124BD +:1000E0001FBECFE5D2E0DEBFCDBF03D23EC288CF78 +:1000F00083E287B985E886B908952F923F924F929F +:100100005F926F927F928F929F92AF92BF92CF92A7 +:10011000DF92EF92FF920F931F93CF93DF93CDB7B0 +:10012000DEB72E970FB6F894DEBF0FBECDBF3C01F1 +:100130004B0129833A8321E030E002C0220F331FB4 +:100140004A95E2F73C872B878FEF9FEF213041E004 +:100150003407D4F48901015011097301DB0180E0F7 +:1001600090E041E050E0041715073CF567E0262ECB +:10017000312CEE24E394F12C4B855C85E416F506D6 +:100180000CF44DC080E090E02E960FB6F894DEBFE0 +:100190000FBECDBFDF91CF911F910F91FF90EF90D8 +:1001A000DF90CF90BF90AF909F908F907F906F9097 +:1001B0005F904F903F902F9008952B853C8535950B +:1001C0002795BC01620F731F06171707C4F3B90107 +:1001D0006150710986239723820F931F481759078F +:1001E000BCF4F70161819301280F391FF901708177 +:1001F000F7017183F901608311966C911197940155 +:10020000280F391FF901708111967C931197608333 +:100210004F5F5F4FFFEFEF1AFF0A1196A4CF270140 +:10022000440C551C00E010E00E151F052CF031E0C9 +:10023000231A31087201A0CFC801022C02C0880F16 +:10024000991F0A94E2F7FC01E25AFF4F259134917D +:10025000422FFC01E25EFF4F85919491A981BA8102 +:10026000AB2B19F48195459585955701A00EB11ECC +:100270006801E42F440FFF0BF887EF83282F880FC6 +:10028000330B3A8729872B853C85C216D3061CF091 +:100290000F5F1F4FC9CFA3014A0D5B1D5E834D83C6 +:1002A000DA012C91022E000C330B8F819885B90155 +:1002B0004BD1BC0186FB442740F9660F672F661FB0 +:1002C000770B460F4E87F401EA0DFB1DFC83EB8391 +:1002D000A0810A2E000CBB0B89859A85BD0134D103 +:1002E000BC0186FBEE27E0F9660F672F661F770BD0 +:1002F000E60F4E1B4D87CD016F81788525D1DC013E +:1003000089859A85B90120D19C01880F892F881F82 +:10031000990BBD01660F672F661F770B860FA6FB33 +:10032000AA27A0F9A80F26FB222720F92A0FB3013C +:100330006C0D7D1DDB019C91D401AC0DBD1D8C911C +:1003400049815A81452B11F495958595FE85EF1BC2 +:100350003E2F390FED81FE813083382F321BEB8128 +:10036000FC813083FD859F0FFB019083280F2C9328 +:10037000C40CD51CA40CB51C86CFAF92BF92CF92F3 +:10038000DF92EF92FF920F931F93CF93DF93EC01D5 +:100390007A018B010150110981E090E06C01002E7F +:1003A00002C0CC0CDD1C0A94E2F75E01AC0CBD1C53 +:1003B00080E090E04115510529F09A01A801BE01A5 +:1003C000C5019BDEFE0121E030E02C153D0594F0D7 +:1003D000EF28D9F420E030E0A801BE01C501DF918B +:1003E000CF911F910F91FF90EF90DF90CF90BF9032 +:1003F000AF9083CEDF01AC0DBD1D4C9151815C935C +:1004000041832E5F3F4F3296E0CFDF91CF911F9116 +:100410000F91FF90EF90DF90CF90BF90AF90089535 +:100420009C01CB0157B3542B57BB68B3542F509545 +:10043000562368B3462B6FB7F894820F931FA8E337 +:10044000B0E02817390711F46FBF0895F9017191D1 +:100450009F01E8E04C93000007F407F407F407F469 +:1004600007F407F407F407F407F407F407F407F4B4 +:1004700007F407F477FF5C93770F07F407F407F4AA +:1004800007F407F407F407F407F407F407F407F494 +:1004900007F407F407F407F408F45C9307F407F48F +:1004A00007F407F407F407F407F407F407F407F474 +:1004B00007F407F407F407F4EA9561F6C2CF9C014C +:1004C000CB0163E070E040D0BC01C901A9DF84E644 +:1004D0008A95F1F7089540E1F2CF660F771F660F16 +:1004E000771F40E19DDF84E68A95F1F7089540E1AA +:1004F00097CF00D00F92CDB7DEB784E6F82E1AE082 +:100500000FEF1A82F9821B8361E070E0CE01019641 +:10051000E2DF2FE986E891E0215080409040E1F74A +:1005200000C000000A8319821B8361E070E0CE01E5 +:100530000196D1DF2FE986E891E02150804090407C +:10054000E1F700C00000DDCF0024552704C0080EED +:10055000591F880F991F009729F076956795B8F372 +:0E0560007105B9F7802D952F0895F894FFCFFF +:00000001FF diff --git a/main.o b/main.o new file mode 100644 index 0000000000000000000000000000000000000000..cd9d6949d8fa443a028c910f20be28b15126c89c GIT binary patch literal 1148 zcmb<-^>JflWMqH=MuuPp1doB?4HE;yOa=x96R-je1}+9p28Ij#lg@6xx4q@r4?U>| z{O_fjel|%rCq5{6aE_628p8$smu)X5K2Qv3aG2o0_=VvB0|QsHBmor+2N>L)ovjo! z-2Fl|6%38_jPwk^R-zHeZewBi_#auC8O7xc49pBn$kGhV49pB13=9l*aM6$d1sNC^ zY?1g<3=9nRNPJ~D8^rkdU!Q>i$rg0`Sr}{>7?5m*@DUz?@Pj}`fiVk%0|Ntt8kh|t zSQy+G7#KW2OfY6)@L^zJ5CF451Ph3OV`c_6h5#rpjDdkch=GM66v_utV12oXnR$B2 z4Ds>70r4L3@eqa&gc0QG4rY|(7Q`2&ri0m4sYUrvj*kH&gPxBelOdQiV$kz3VgMP( zP+n|gVQ3UzoLZ8TnombT2aEFmy%eL$e@>0T+EDP0cHT7)%5y4UJ_nA z85qFnj*vP-s2*f{LGcPQ1B78|9~7>jlmH4xkhlvI149A>0|Pq)0|Q7Lgh4?KO2;5Q zu=Ll(z`y{F8jv<{ItIyuFmg^=z`(%ZzzA`(5Y$XiRB(dg1gsN6JYZyCNP#fHB*+{P T1C*y=eg*NDFd?UDME(H)09Jmq literal 0 HcmV?d00001 diff --git a/makefile b/makefile new file mode 100644 index 0000000..b0a3728 --- /dev/null +++ b/makefile @@ -0,0 +1,223 @@ +# Hey Emacs, this is a -*- makefile -*- + +# AVR-GCC Makefile template, derived from the WinAVR template (which +# is public domain), believed to be neutral to any flavor of "make" +# (GNU make, BSD make, SysV make) + + +MCU = attiny85 +FORMAT = ihex +TARGET = main +SRC = $(TARGET).c avr_adc.c fix_fft.c light_ws2812_AVR/Light_WS2812/light_ws2812.c +ASRC = +OPT = s + +# Name of this Makefile (used for "make depend"). +MAKEFILE = Makefile + +# Debugging format. +# Native formats for AVR-GCC's -g are stabs [default], or dwarf-2. +# AVR (extended) COFF requires stabs, plus an avr-objcopy run. +DEBUG = stabs + +# Compiler flag to set the C Standard level. +# c89 - "ANSI" C +# gnu89 - c89 plus GCC extensions +# c99 - ISO C99 standard (not yet fully implemented) +# gnu99 - c99 plus GCC extensions +CSTANDARD = -std=gnu99 + +# Place -D or -U options here +CDEFS = -DF_CPU=1000000UL + +# Place -I options here +CINCS = + + +CDEBUG = -g$(DEBUG) +CWARN = -Wall -Wstrict-prototypes +CTUNING = -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums +#CEXTRA = -Wa,-adhlns=$(<:.c=.lst) +CFLAGS = $(CDEBUG) $(CDEFS) $(CINCS) -O$(OPT) $(CWARN) $(CSTANDARD) $(CEXTRA) + + +#ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs + + +#Additional libraries. + +# Minimalistic printf version +PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min + +# Floating point printf version (requires MATH_LIB = -lm below) +PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt + +PRINTF_LIB = + +# Minimalistic scanf version +SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min + +# Floating point + %[ scanf version (requires MATH_LIB = -lm below) +SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt + +SCANF_LIB = + +MATH_LIB = -lm + +# External memory options + +# 64 KB of external RAM, starting after internal RAM (ATmega128!), +# used for variables (.data/.bss) and heap (malloc()). +#EXTMEMOPTS = -Wl,--section-start,.data=0x801100,--defsym=__heap_end=0x80ffff + +# 64 KB of external RAM, starting after internal RAM (ATmega128!), +# only used for heap (malloc()). +#EXTMEMOPTS = -Wl,--defsym=__heap_start=0x801100,--defsym=__heap_end=0x80ffff + +EXTMEMOPTS = + +#LDMAP = $(LDFLAGS) -Wl,-Map=$(TARGET).map,--cref +LDFLAGS = $(EXTMEMOPTS) $(LDMAP) $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB) + + +# Programming support using avrdude. Settings and variables. + +AVRDUDE_PROGRAMMER = arduino#usbasp +#AVRDUDE_PORT = /dev/term/a + +AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex +#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep + + +# Uncomment the following if you want avrdude's erase cycle counter. +# Note that this counter needs to be initialized first using -Yn, +# see avrdude manual. +#AVRDUDE_ERASE_COUNTER = -y + +# Uncomment the following if you do /not/ wish a verification to be +# performed after programming the device. +#AVRDUDE_NO_VERIFY = -V + +# Increase verbosity level. Please use this when submitting bug +# reports about avrdude. See +# to submit bug reports. +#AVRDUDE_VERBOSE = -v -v + +AVRDUDE_BASIC = -p $(MCU) -c $(AVRDUDE_PROGRAMMER) -B4 +AVRDUDE_FLAGS = $(AVRDUDE_BASIC) $(AVRDUDE_NO_VERIFY) $(AVRDUDE_VERBOSE) $(AVRDUDE_ERASE_COUNTER) + + +CC = avr-gcc +OBJCOPY = avr-objcopy +OBJDUMP = avr-objdump +SIZE = avr-size +NM = avr-nm +AVRDUDE = avrdude +REMOVE = rm -f +MV = mv -f + +# Define all object files. +OBJ = $(SRC:.c=.o) $(ASRC:.S=.o) + +# Define all listing files. +LST = $(ASRC:.S=.lst) $(SRC:.c=.lst) + +# Combine all necessary flags and optional flags. +# Add target processor to flags. +ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) +ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS) + + +# Default target. +all: build + +build: elf hex eep + +elf: $(TARGET).elf +hex: $(TARGET).hex +eep: $(TARGET).eep +lss: $(TARGET).lss +sym: $(TARGET).sym + + +# Program the device. +program: $(TARGET).hex $(TARGET).eep + $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM) + + + + +# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB. +COFFCONVERT=$(OBJCOPY) --debugging \ +--change-section-address .data-0x800000 \ +--change-section-address .bss-0x800000 \ +--change-section-address .noinit-0x800000 \ +--change-section-address .eeprom-0x810000 + + +coff: $(TARGET).elf + $(COFFCONVERT) -O coff-avr $(TARGET).elf $(TARGET).cof + + +extcoff: $(TARGET).elf + $(COFFCONVERT) -O coff-ext-avr $(TARGET).elf $(TARGET).cof + + +.SUFFIXES: .elf .hex .eep .lss .sym + +.elf.hex: + $(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@ + +.elf.eep: + -$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \ + --change-section-lma .eeprom=0 -O $(FORMAT) $< $@ + +# Create extended listing file from ELF output file. +.elf.lss: + $(OBJDUMP) -h -S $< > $@ + +# Create a symbol table from ELF output file. +.elf.sym: + $(NM) -n $< > $@ + + + +# Link: create ELF output file from object files. +$(TARGET).elf: $(OBJ) + $(CC) $(ALL_CFLAGS) $(OBJ) --output $@ $(LDFLAGS) + + +# Compile: create object files from C source files. +.c.o: + $(CC) -c $(ALL_CFLAGS) $< -o $@ + + +# Compile: create assembler files from C source files. +.c.s: + $(CC) -S $(ALL_CFLAGS) $< -o $@ + + +# Assemble: create object files from assembler source files. +.S.o: + $(CC) -c $(ALL_ASFLAGS) $< -o $@ + + + +# Target: clean project. +clean: + $(REMOVE) $(TARGET).hex $(TARGET).eep $(TARGET).cof $(TARGET).elf \ + $(TARGET).map $(TARGET).sym $(TARGET).lss \ + $(OBJ) $(LST) $(SRC:.c=.s) $(SRC:.c=.d) + +depend: + if grep '^# DO NOT DELETE' $(MAKEFILE) >/dev/null; \ + then \ + sed -e '/^# DO NOT DELETE/,$$d' $(MAKEFILE) > \ + $(MAKEFILE).$$$$ && \ + $(MV) $(MAKEFILE).$$$$ $(MAKEFILE); \ + fi + echo '# DO NOT DELETE THIS LINE -- make depend depends on it.' \ + >> $(MAKEFILE); \ + $(CC) -M -mmcu=$(MCU) $(CDEFS) $(CINCS) $(SRC) $(ASRC) >> $(MAKEFILE) + +.PHONY: all build elf hex eep lss sym program coff extcoff clean depend diff --git a/micronucleus b/micronucleus new file mode 100755 index 0000000000000000000000000000000000000000..d410cb4538ba25eee2e4415f804e269fe9fba756 GIT binary patch literal 51840 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�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