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=MuuPp1doAX3Xn4sC}{##puxbwz|PS8sC{Sai?*E{QyJWyovjo! z-2Fl|6%38_jPwj(<{;C^=CLq*{EsZhjA9!D12Y2?vNVv-%)kv4v4e|#{4WAz+amF0 zfoyvuz8ahjVto8>1SAn|K)0U-u9pj_P6(tjv8*UQF(p|qnIS$tI3V65J|4pGfiQwx z-NB5K+=BR`)O0YrDzzvd$|+7QDJ^hxab{r9E3V8fNlXILB}EWA1I8*zttes8OGzwA zWY9}0E@se6&d<$F%_{-9m{=eUR0#4H8&m@*jzE5Z0hpf^fdU{lGgJZ*mJk7$I&~nI zg9vpxKs6veu*e3PCk(_e0Fr}Y 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 zcma);4NOy46vyvvD+&~!xFJqpMMS_sUQ4S^42mEMC<02%9Aj3H@?of8K}AKd)>4>G zUt0>w$aI@AZo26{)VPUsi`$GDfjCXf+@#BlS>|RTVNpcw&UvpbZ;4BGntSi>f6jUL z-Fx48FKu3yyPQ%=d`3wj8CQgq1rl-uf^+$V1QJ97iPDy4%eQH5HMVBkA=^>g8C$Qd z-!^D-+dMYLuCVvp2km_q?p$Cyne&g@@ANX4`+8I9N;=21&@|JfauH_?qfxAINJdgE ziIzj|qwblibl2R8vXM4Q3qk|y=xw^k#kta51uj{582Bq(acpwZgV^8Nhm%&Ci_LeZ z{T(11Ax_LJ$Ot;S*&;7imesmcW)-owN4B7P7-%hr2$cB}O|AR9_{&6<%s$v}zo zDwQM=XDf3=5!5ajc|u(ULrZ2`=UOwA0-LSv)(?$e8c!wC5u;<7!|ZsC9-I8>%a!!5 zGL!KHKeD(@3CdPR6THwe$AWwLX4;PdvLQyR$S2MZ=!%dxqSl*MnSP>4RtZbwn&3mm z!{&>W3|yiuW0~4GD80d8H;*ix^FsW41(;hg4@hp<{oeMgLs!e z`yP`QvC7g%Ym5zMGVn9SJe;+gwlZzXR>hIv9_pL9g*h?yQT(ydlT6%LOnmg{E6nG# zI%Id$ZQ5;i^7>kU{V2=*i;WM*4VzDxX`OEmss4^{3sw3_jp8!2IA7#cU zXG&m_>{sMBBah3^MH1)p>g`XulkVrM#|Sl1O$ke!KgfTH#4}z`Ps@8E`HBi#J%J8& z(UbHt{T9~#jAA_|g)M?7vH8qc0Q`7Fo#$7viG;H6twa!pmqp#jnSzcDUVSRDYy0wL?^Kx^tGSkyiQ|4<_ zY+}Of7)9jtu&InZFhEM4K7Ked{NVoYcYnQe`_|3t1AW)Nzw&kOrHdE7`0UKbr%s+Y z{{FFdySol|wA-!R!MFFn)z)fhG4I=F+Pl|?MzWSJT^OB^mA7_Ibh3t3vnt;=LOhDU z6*4mH5yzze`jQYLg`e1@L`H(avDoh%_PhwZNTj2H(?mMX&j`aFHT2_a81`UpD~5O* zkD!#231lgZ%lQ~~l;l94A=3H42SvIN*eTNMfMfmBQt~F~E24M_@HA0e2fA7muL52y zif;zpB#Ik=vqkX+(3v8QxwRs_7j(BsTR^iSy&v=%33R+s!ohez6nB6=EsDPb`lLv| z2l|>wp8)+>q)&mK;(x4^oCQ4~ii7lXjN#)RiWkZvM@JO)UB$EZMMP>wUK@NfjBi6eV4-4!%G)X9r z3>&L8OuOGP* zSTY@nkapyk1nvTs&Jg%Ka-6_-MJ$00`TTMb=K@P2g#0G-M+$rb89x$WpJ2|*0$)Z} z2z(WDVgvawFge|SB zBW$gqrb4gNvt=dqC4}8rqu1*;*L$b=KSMMm!BN0lA{hSXiu1o)vV^~TWul7w*pY%NqWI`qu_X&cXrRLhzdJzF79YJzyvrF3j-e I;NZ*q2L(V!I{*Lx literal 0 HcmV?d00001 diff --git a/light_ws2812_AVR/Examples/Chained_writes.c b/light_ws2812_AVR/Examples/Chained_writes.c new file mode 100644 index 0000000..3a2ca72 --- /dev/null +++ b/light_ws2812_AVR/Examples/Chained_writes.c @@ -0,0 +1,52 @@ +/* + * ATTENTION: This example uses the old v1.0 interface. + * + * Light_WS2812 library example - Chained Writes + * + * This example shows how to use multiple calls without issuing a reset + * in between, allowing to send the same buffer to the string + * multiple times. This technique can be useful to conserve memory + * or to calculate LED colors on-the-fly. + * + * Please make sure to set your configuration in "WS2812_config.h" first + * + */ + +#include +#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 zcma)-`)eFk6vxlpO`EM&6YHZss#&ep)aW$38?_CwhCY&_OAKwaD6!Ms>^2*_FL%do zDpE@fC6rRyCXp(|{wDq)QVgi5U=e@t0TR?dAR>tPTOdE^PwV;4naNHMR6Wa?`}y2+ z=dm+$@4UG;HDFm51!2(vY8ufmQKEOa*y9c8q;(XfOV$t8!G)2ogJ0wqMz#&lzpy#K zFwj;0^sl+8w%Lvke!H^Nxp7CUwNm~nI{&xz>iNsoA4{oOqSlq`|LTp=*?Qac>!{Gm z=y6* zCwbevhULZ{c6lzSTl6e%dx2hv_XXmPCZIp=M@f6eWWoI#xm6XSW;sn-(Q;|Y6= z9OuBWv(Iq^QUd$;4tn4gD^4{x?(yrnYT1`Uxm-#1P^#Oa+R=$hxs+qGQ%TMQXWYcS zZGz-1PAyl;rmNNTai^HB9c}iygIJY!JrUVQv-1x?ymmIZ~YF zb`NO?e24Hbc%v}Z34;g8@e-%OV#Fh*I0L>{I19c{7;Ay)5XL%S zV!~Jh%>BXzu>Vq)z?-GN0)9{!bKX28jQMVGQ#p=tnuk54NpPny=D67^d;6!^QQ~Objects/$@.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 = (1<U{Q( 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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 zcma)5OKTKC5U$x7qQ=K+JY@rtAZP^X?2H~nj1I(Pa~Q&s7_Z|bJ47LqEHfiME`}s{ z@T49DZyx*)x%vl``~sPiC z_Zrb#IIorg(=ZC<#_sRkiM^=k7N0EZ4IR#Wd;axRG1cDj zU;5Th`am?gH$Ef+QLVYT>yy*1rPWK5?iJyQrtZmL5~I=2Rs)?=aQ}7uk~}kJd<$PNEa#5s9@dBaz0Nkzgx=qcnfmC9%Gp zB=J@*6aU9Lff#<{5fv+EzuKtZe@eyKL*g#N&vQ2{&Q5UHzXw09Jmq 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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 Bq@4f& literal 0 HcmV?d00001