#define WAKEUP_POLL 50 // msec
#define WAKEUP_LIMIT 5 // times WAKEUP_POLL
-/* output power levels */
-#define N_POWER_LEVELS 5
-static unsigned char power_levels[N_POWER_LEVELS] = {
-
-};
-
-static unsigned char power_level = 0; // selected power level
-
/* which state (output on or output off) are we measuring now */
static volatile unsigned char adc_type, adc_drop;
#define ADC_RUNAVG_SHIFT 5 // running average shift on batt_on, batt_off
#define MV_TO_ADC8(mV) ((unsigned char)(((uint32_t)(1UL << ADC_RUNAVG_SHIFT) \
* (1024UL * (mV)) \
/ (6UL * ADC_1100MV_VALUE)) >> 8))
-#define BATT_N_LEVELS 3
-static unsigned char batt_levels[BATT_N_LEVELS] = {
- MV_TO_ADC8(3500),
+static unsigned char batt_levels[] = {
+ MV_TO_ADC8(3350),
MV_TO_ADC8(3700),
MV_TO_ADC8(3900),
};
+#define BATT_N_LEVELS (sizeof(batt_levels) / sizeof(batt_levels[0]))
+
+/* output power and PWM calculation */
+#define PWM_TOP 255
+#define PWM_MAX (PWM_TOP - 8) // to allow for ADC "batt_off" measurements
+
+/*
+ * The values in power_levels[] array are voltages at which the load
+ * would give the expected power (we don't have sqrt() function,
+ * so we cannot use mW values directly. They can be calculated as
+ * voltage[V] = sqrt(load_resistance[Ohm] * expected_power[W])
+ * or
+ * voltage[mV] = sqrt(load_resistance[mOhm] * expected_power[mW])
+ *
+ * I use 1.25 W as minimum power, each step is sqrt(2)*previous_step,
+ * so the 5th step is 5 W.
+ */
+static unsigned char power_levels[] = {
+ MV_TO_ADC8(1581), // 1250 mW for 2 Ohm load
+ MV_TO_ADC8(1880), // 1768 mW for 2 Ohm load
+ MV_TO_ADC8(2236), // 2500 mW for 2 Ohm load
+ MV_TO_ADC8(2659), // 3536 mW for 2 Ohm load
+ MV_TO_ADC8(3162), // 5000 mW for 2 Ohm load
+};
+#define N_POWER_LEVELS (sizeof(power_levels) / sizeof(power_levels[0]))
+
+static unsigned char power_level = 0; // selected power level
/* timing by WDT */
static volatile unsigned char jiffies, next_clock_tick;
// TCCR1 = _BV(CS10); // clk/1 = 1 MHz
TCCR1 = _BV(CS11) | _BV(CS13); // clk/512 = 2 kHz
GTCCR = _BV(COM1B1) | _BV(PWM1B);
- OCR1C = 255;
+ OCR1C = PWM_TOP;
// OCR1B = steps[0];
OCR1B = 0;
TIMSK = _BV(OCIE1B) | _BV(TOIE1);
{
// for now, display the selected intensity
- n_blinks = power_level + 1;
- // n_blinks = battery_level() + 1;
+ // n_blinks = power_level + 1;
+ n_blinks = battery_level() + 1;
blink_on_time = 0;
blink_off_time = 2;
blink_counter = 10;
}
}
+static void calculate_power_level()
+{
+ uint32_t pwm;
+ unsigned char batt_on8;
+
+ if (battery_level() == 0 || batt_on == 0) {
+ pwm_set(0);
+ // TODO power_down() after some time
+ return;
+ }
+
+ batt_on8 = batt_on >> 8;
+
+ pwm = (uint32_t)PWM_TOP * power_levels[power_level]
+ * power_levels[power_level];
+ pwm /= (uint32_t)batt_on8 * batt_on8;
+
+ if (pwm > PWM_MAX)
+ pwm = PWM_MAX;
+
+ log_byte(0x10 + power_level);
+ log_byte(batt_on8);
+ log_byte(pwm & 0xFF);
+
+ pwm_set(pwm);
+}
+
int main()
{
log_init();
log_word(batt_levels[2]);
log_flush();
#endif
+ log_byte(power_levels[0]);
+ log_byte(power_levels[4]);
+ log_flush();
power_down();
timer_check_buttons();
if ((jiffies & 0x0F) == 0) {
- unsigned char i;
-
- for (i = 0; i < BATT_N_LEVELS; i++)
- if (batt_levels[i] > batt_off)
- break;
-
+ calculate_power_level();
#if 0
log_byte(0xcc);
log_byte(i);