#include #include #include // Liste mit Registern, um dem C-Compiler zu erklären, // dass ALLE Register beim vom ihm nicht erklärten Sprüngen // im Ablauf geändert sein können. //#define no_op /* ohne Opimierung // weglassen */ #ifdef no_op // ohne optimierung (-o0):Y in asm führt zu: r28 cannot be used in 'asm' here #define reg_use "r0","r2" , "r3" , "r4" , "r5" ,"r6" ,"r7" ,\ "r8" , "r9" , "r10", "r11", "r12", "r13","r14","r15",\ "memory","r16", "r17","r18", "r19", "r20", "r21","r22","r23","r24", "r25", "r26", "r27","r30","r31"/**/ #else // optimierung mit -o1/-o2: Y muss als benutzt deklariert werden #define reg_use "r0","r2" , "r3" , "r4" , "r5" ,"r6" ,"r7" ,\ "r8" , "r9" , "r10", "r11", "r12", "r13","r14","r15",\ "memory","r16", "r17","r18", "r19", "r20", "r21","r22","r23","r24", "r25", "r26", "r27","r30","r31","r28","r29"/**/ #endif #define max_macro 5 /*max. Anzahl gleichzeitig laufender Makros*/ typedef void (*VoidFnct) (void); typedef struct{uint8_t r,g,b;} tColor;// für 'Farbe' typedef struct{ // Variablen in Macro-C VoidFnct adr; // !!! adr must be first element uint16_t cnt; // used for delay uint8_t para; // macro parameter uint8_t a,b,c; // 3*8bit work vars uint16_t A,B,C;// 3*16bit work vars tColor col_1,col_2;//for color work } tMacVar; //internal use tMacVar m_A[max_macro];// all macro vars uint8_t m_cur; // current macro uint16_t m_cnt; // current counter tMacVar *tsk; // short pointer "m_A[m_cur]" int runMacro(uint8_t aMacN,VoidFnct aAdr, uint8_t aPara){ if (aMacN>max_macro)return(-1);//"out of range"] if (aMacN==0){ //0: sucht freien 'Prozess' aMacN=max_macro; while(m_A[aMacN].adr!=NULL) if (--aMacN==0)return(-2);//"all slots in use"] } m_A[aMacN].adr=aAdr; m_A[aMacN].para=aPara; return(0); } void stepMacro(){ tsk=&m_A[m_cur]; if (tsk->adr!=NULL)asm volatile( "lds yl,tsk lds yh,tsk+1 " "ldd zl,y+0 ldd zh,y+1 " "ijmp " :::reg_use); runMain: //goto from yield m_cur++; if (m_cur==max_macro){ m_cur=0; // if (flag_10Hz) // {flag_10HZ=false; m_cnt++; } } // assembler: speichert µC-PC(Programm counter) // und springt zum Aufruf aus stepMacro(in main loop) zurück #define yield asm volatile("call yield_asm":::reg_use) __attribute__((naked)) void yield_asm() {asm volatile ( "pop r17 pop r16 " // PC from stack "lds yl,tsk lds yh,tsk+1 "// store in m_A[m_cur].adr "std y+0,r16 std y+1,r17 " "jmp runMain "); // jump to main loop } // --- types from channels.h/config.h -- #define CHANNELNUMS 32 #define PWM_STEPS 250 // PWM-Schritte pro Zyklus(1..255) volatile uint8_t pwm[CHANNELNUMS][2]; //nach Falk-Plan (Internet) volatile uint8_t PWM_CH_IS[CHANNELNUMS]; /*suggest*/typedef struct{ uint8_t is; //cur(rent)/ist uint8_t to; //des(tination)/soll uint8_t speed_div;//speed|delta / delay|divider... uint8_t chg_mode; //mode(linear/log;auto;) } tChannel ; //tChannel pwm[CHANNELNUMS]; // ---test macros -- __attribute__((OS_task))void macro_c_0_13_on(void) { for(m_A[m_cur].a =0; m_A[m_cur].a<=14; m_A[m_cur].a++){ pwm[m_A[m_cur].a][0]=PWM_STEPS; //pwm[tsk->a].to = PWM_STEPS; while(PWM_CH_IS[m_A[m_cur].a]<25)yield; } while(PWM_CH_IS[14]adr = NULL; } // einfachere(?) Schreibweisen/ syntax Spielwiese #define Macro(name)__attribute__((OS_task))void macro_##name(void){ #define macro_adr(name) ¯o_##name #define M_(var) m_A[m_cur].var #define End_Macro M_(adr)=NULL;} #define M_Wait(cond) while(not(cond))yield; #define M_Delay(aCnt) M_(cnt)=m_cnt+aCnt;M_Wait(m_cnt==M_(cnt)) #define m_UP 1 #define m_TO 1 #define m_DOWN_TO -1 #define M_For(var,from,dir,to)\ for(M_(var)=from;M_(var)!=to +m_##dir; M_(var)+=m_##dir){ #define M_Loop while(1){ #define M_Next } //#define M_Goto //todo uint8_t ch(uint8_t c){// simple mapping if (1) return(c-1); else return((c-1)%2*16+ (c-1)/2);}; Macro(ch_1_14_off) M_For(a,ch(1),TO,ch(14))// first: all on PWM_CH_IS[M_(a)]=PWM_STEPS; //pwm[M_(a)].is =PWM_STEPS; pwm[M_(a)][0] = PWM_STEPS; //pwm[M_(a)].to = PWM_STEPS; M_Next M_For(a,ch(14),DOWN_TO,ch(1)) pwm[M_(a)][0] = 0; //pwm[M_(a)].to = 0; M_Wait(PWM_CH_IS[M_(a)]<100); //M_Wait(pwm(M_(a).is < 100); M_Next M_Wait(PWM_CH_IS[ch(1)]==0) End_Macro; Macro(on_off_repeat)//para=anz der wiederholungen M_For(a,0,TO,M_(para)) m_A[0].adr=macro_adr(c_0_13_on); M_Wait(m_A[0].adr==NULL) m_A[0].adr=macro_adr(ch_1_14_off); M_Wait(m_A[0].adr==NULL) M_Next End_Macro; //'helper': 'normale' C-funktionen bool fade_done_all(uint8_t s,uint8_t l){ for(int i=s; i