//####################################################################################################### void pwm_update(void) // PWM Update, berechnet aus den PWM Einstellungen die neuen Werte für die Interruptroutine { uint8_t i, j, k, min; uint8_t tmp; // PWM Maske für Start berechnen und gleichzeitig die Bitmasken generieren und PWM Werte kopieren tmp=0; j = 1; for(i=1; i<=(PWM_CHANNELS); i++) { main_ptr_mask[i]=~j; // Maske zum Löschen der PWM Ausgänge pwm_setting_tmp[i] = pwm_setting[i-1]; if (pwm_setting_tmp[i]!=0) tmp |= j; // Maske zum setzen der IOs am PWM Start j <<= 1; } main_ptr_mask[0]=tmp; // PWM Start Daten // PWM settings sortieren; Einfügesortieren for(i=1; i<=PWM_CHANNELS; i++) { min=255; k=i; for(j=i; j<=PWM_CHANNELS; j++) { if (pwm_setting_tmp[j]<min) { k=j; // Index und PWM-setting merken min = pwm_setting_tmp[j]; } } if (k!=i) { // ermitteltes Minimum mit aktueller Sortiertstelle tauschen tmp = pwm_setting_tmp[k]; pwm_setting_tmp[k] = pwm_setting_tmp[i]; pwm_setting_tmp[i] = tmp; tmp = main_ptr_mask[k]; main_ptr_mask[k] = main_ptr_mask[i]; main_ptr_mask[i] = tmp; } } // Gleiche PWM-Werte vereinigen, ebenso den PWM-Wert 0 löschen falls vorhanden k=PWM_CHANNELS; // PWM_CHANNELS Datensätze i=1; // Startindex while(k>i) { while ( ((pwm_setting_tmp[i]==pwm_setting_tmp[i+1]) || (pwm_setting_tmp[i]==0)) && (k>i) ) { // aufeinanderfolgende Werte sind gleich und können vereinigt werden // oder PWM Wert ist Null if (pwm_setting_tmp[i]!=0) main_ptr_mask[i+1] &= main_ptr_mask[i]; // Masken vereinigen // Datensatz entfernen, // Nachfolger alle eine Stufe hochschieben for(j=i; j<k; j++) { pwm_setting_tmp[j] = pwm_setting_tmp[j+1]; main_ptr_mask[j] = main_ptr_mask[j+1]; } k--; } i++; } // letzten Datensatz extra behandeln // Vergleich mit dem Nachfolger nicht möglich, nur löschen // gilt nur im Sonderfall, wenn alle Kanäle 0 sind if (pwm_setting_tmp[i]==0) k--; // Zeitdifferenzen berechnen if (k==0) { // Sonderfall, wenn alle Kanäle 0 sind main_ptr_time[0]=(uint16_t)T_PWM*PWM_STEPS/2; main_ptr_time[1]=(uint16_t)T_PWM*PWM_STEPS/2; k=1; } else { i=k; main_ptr_time[i]=(uint16_t)T_PWM*(PWM_STEPS-pwm_setting_tmp[i]); j=pwm_setting_tmp[i]; i--; for (; i>0; i--) { main_ptr_time[i]=(uint16_t)T_PWM*(j-pwm_setting_tmp[i]); j=pwm_setting_tmp[i]; } main_ptr_time[0]=(uint16_t)T_PWM*j; } // auf Sync warten pwm_sync=0; // Sync wird im Interrupt gesetzt while(pwm_sync==0); // Zeiger tauschen cli(); tausche_zeiger(); pwm_cnt_max = k; sei(); }
void pwm_update(void) { uint8_t i, j, k; uint8_t m1, m2, tmp_mask; // ändern uint16_t oder uint32_t für mehr Kanäle uint16_t min, tmp_set; // ändern auf uint16_t für mehr als 8 Bit Auflösung // PWM Maske für Start berechnen // gleichzeitig die Bitmasken generieren und PWM Werte kopieren m1 = 1 << PWM_CHANNEL_OFFSET; m2 = 0; for (i = 1; i <= (PWM_CHANNELS); i++) { main_ptr_mask[i] = ~m1; // Maske zum Löschen der PWM Ausgänge pwm_setting_tmp[i] = pgm_read_word (& pwmtable[pwm_setting[i - 1]]); if (pwm_setting_tmp[i] != 0) m2 |= m1; // Maske zum setzen der IOs am PWM Start m1 <<= 1; } main_ptr_mask[0] = m2; // PWM Start Daten // PWM settings sortieren; Einfügesortieren for (i = 1; i <= PWM_CHANNELS; i++) { min = PWM_STEPS - 1; k = i; for (j = i; j <= PWM_CHANNELS; j++) { if (pwm_setting_tmp[j] < min) { k = j; // Index und PWM-setting merken min = pwm_setting_tmp[j]; } } if (k != i) { // ermitteltes Minimum mit aktueller Sortiertstelle tauschen tmp_set = pwm_setting_tmp[k]; pwm_setting_tmp[k] = pwm_setting_tmp[i]; pwm_setting_tmp[i] = tmp_set; tmp_mask = main_ptr_mask[k]; main_ptr_mask[k] = main_ptr_mask[i]; main_ptr_mask[i] = tmp_mask; } } // Gleiche PWM-Werte vereinigen, ebenso den PWM-Wert 0 löschen falls vorhanden k = PWM_CHANNELS; // PWM_CHANNELS Datensätze i = 1; // Startindex while (k > i) { while (((pwm_setting_tmp[i] == pwm_setting_tmp[i + 1]) || (pwm_setting_tmp[i] == 0)) && (k > i)) { // aufeinanderfolgende Werte sind gleich und können vereinigt werden // oder PWM Wert ist Null if (pwm_setting_tmp[i] != 0) main_ptr_mask[i + 1] &= main_ptr_mask[i]; // Masken vereinigen // Datensatz entfernen, // Nachfolger alle eine Stufe hochschieben for (j = i; j < k; j++) { pwm_setting_tmp[j] = pwm_setting_tmp[j + 1]; main_ptr_mask[j] = main_ptr_mask[j + 1]; } k--; } i++; } // letzten Datensatz extra behandeln // Vergleich mit dem Nachfolger nicht möglich, nur löschen // gilt nur im Sonderfall, wenn alle Kanäle 0 sind if (pwm_setting_tmp[i] == 0) k--; // Zeitdifferenzen berechnen if (k == 0) { // Sonderfall, wenn alle Kanäle 0 sind main_ptr_time[0] = (uint16_t) T_PWM * PWM_STEPS / 2; main_ptr_time[1] = (uint16_t) T_PWM * PWM_STEPS / 2; k = 1; } else { i = k; main_ptr_time[i] = (uint16_t) T_PWM * (PWM_STEPS - pwm_setting_tmp[i]); tmp_set = pwm_setting_tmp[i]; i--; for (; i > 0; i--) { main_ptr_time[i] = (uint16_t) T_PWM * (tmp_set - pwm_setting_tmp[i]); tmp_set = pwm_setting_tmp[i]; } main_ptr_time[0] = (uint16_t) T_PWM * tmp_set; } // auf Sync warten pwm_sync = 0; // Sync wird im Interrupt gesetzt while (pwm_sync == 0) ; // Zeiger tauschen cli(); tausche_zeiger(); pwm_cnt_max = k; sei(); }