Commit 287f589e authored by Jan Kasprzak's avatar Jan Kasprzak
Browse files

Added missing source files battery.c and buttons.c

parent 887aa3ba
Loading
Loading
Loading
Loading
+89 −0
Original line number Original line Diff line number Diff line
#include <avr/io.h>

#include "lights.h"

#define BATTERY_ADC_SHIFT	2
#define RESISTOR_HI	1500	// kOhm
#define RESISTOR_LO	 100	// kOhm
/*
 * The internal 1.1V reference has tolerance from 1.0 to 1.2V
 * (datasheet, section 19.6). We have to measure the actual value
 * of our part.
 */
#define AREF_1100MV	1060	// mV

static volatile uint16_t battery_adcval;
static unsigned char initial_readings = 0;

void init_battery()
{
	battery_adcval = 0;
	initial_readings = 5;
}

unsigned char battery_100mv()
{
	/*
	 * This is tricky: we need to maintain precision, so we first
	 * multiply adcval by as big number as possible to fit uint16_t,
	 * then divide to get the final value,
	 * and finally type-cast it to unsigned char.
	 * We don't do running average, as the required precision
	 * is coarse (0.1 V).
	 */
	return (unsigned char)
		((uint16_t)(
		(battery_adcval >> BATTERY_ADC_SHIFT)
		* (11                                      // 1.1V
		* (RESISTOR_HI+RESISTOR_LO)/RESISTOR_LO    // resistor ratio
		/ 4)) >> 8);                               // divide by 1024
}

void battery_adc(uint16_t adcval)
{
	if (initial_readings) {
		initial_readings--;
		battery_adcval = adcval << BATTERY_ADC_SHIFT;
	} else if (battery_adcval == 0) {
		battery_adcval = adcval << BATTERY_ADC_SHIFT;
	} else { // running average
		battery_adcval += (adcval
			- (battery_adcval >> BATTERY_ADC_SHIFT));
	}
#if 0
	log_byte(battery_100mv());
	log_flush();
#endif
}

unsigned char battery_gauge()
{
	unsigned char b8 = battery_100mv();
	unsigned char rv;

	if        (b8 < 70) {
		rv = 1;
	} else if (b8 < 75) {
		rv = 2;
	} else if (b8 < 80) {
		rv = 3;
	} else if (b8 < 85) {
		rv = 4;
	} else if (b8 < 90) {
		rv = 5;
	} else if (b8 < 95) {
		rv = 6;
	} else {
		rv = 7;
	}

	if (rv == 1 && !initial_readings)
		set_error(ERR_BATTERY);

#if 0
	log_byte(0xbb);
	log_byte(rv);
	log_flush();
#endif
	return rv;
}
+133 −0
Original line number Original line Diff line number Diff line
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>
#include <stdlib.h> // for NULL

#include "lights.h"

#define WAKEUP_LIMIT	5	// times 100 ms
#define SHORT_PRESS_MIN	10	// in jiffies (100 Hz ticks)
#define SHORT_PRESS_MAX 50
#define LONG_PRESS_MIN	100
static uint16_t button_start;
static unsigned char prev_state;

void status_led_on_off(unsigned char mode)
{
	if (mode)
		PORTB |= _BV(PORTB0);
	else
		PORTB &= ~_BV(PORTB0);
}

void init_buttons()
{
	DDRB &= ~_BV(DDB1);
	DDRB |= _BV(DDB0);
	PORTB |= _BV(PORTB1); // enable internal pull-up
	PORTB &= ~_BV(PORTB0); // status led off
	GIMSK &= ~_BV(PCIE); // disable pin-change IRQs
	PCMSK = 0; // disable pin-change IRQs on all pins of port B

	button_start = 0;
	prev_state   = 0;
}

void susp_buttons()
{
	DDRB &= ~(_BV(DDB1)); // set as input
	PORTB |= _BV(PORTB1);  // enable internal pull-up
	PORTB &= ~_BV(PORTB0); // set to zero

	GIMSK |= _BV(PCIE);

	PCMSK = _BV(PCINT1);
		// disable pin-change IRQs on all pins except PB1
}

void timer_check_buttons()
{
	unsigned char cur = !(PINB & _BV(PINB1));
	unsigned char prev = prev_state;

	prev_state = cur;

	if (cur && !prev) {                   // --- just pressed ---
		button_start = jiffies;
		// set_status_led(button, NULL);

	} else if (cur && prev) {           // --- is still pressed ---
		uint16_t duration = jiffies - button_start;

		if (duration > LONG_PRESS_MIN) {
			long_press_start();
				// acknowledge long press
		}
	} else if (!cur && prev) {            // --- just released ---
		uint16_t duration = jiffies - button_start;

		if (duration > SHORT_PRESS_MIN && duration < SHORT_PRESS_MAX) {
			short_press();
		} else if (duration > LONG_PRESS_MIN) {
			// set_status_led(button, NULL);
			long_press();
		}
		// ignore other button-press durations
	}
}

#if 0
static void handle_brake(unsigned char cur, unsigned char prev)
{
	if (cur && !prev) {                   // --- just pressed ---
		button_start[2] = jiffies;
	} else if (!cur && prev) {            // --- just released ---
		button_start[2] = jiffies;
	} else {                              // --- no change ---
		uint16_t duration = jiffies - button_start[2];

		if (duration > 6) {
			if (cur) {
				if (button_state.brake_working
					&& !button_state.brake_reported) {
					button_state.brake_reported = 1;
					brake_on();
				}
			} else {
				button_state.brake_working = 1;
				if (button_state.brake_reported) {
					button_state.brake_reported = 0;
					brake_off();
				}
			}
			button_start[2] = jiffies - 7; // avoid overflow
		}
	}
}
#endif

unsigned char buttons_wait_for_release()
{
	uint16_t wake_count = 0;
	unsigned char pin;

	do {
		if (wake_count++ > WAKEUP_LIMIT)
			status_led_on_off(1); // inform the user

		_delay_ms(100);

		pin = PINB & _BV(PINB1);
	} while (!(pin & _BV(PINB1)));

	status_led_on_off(0);

	return wake_count > WAKEUP_LIMIT;
}

ISR(PCINT0_vect)
{
	// empty - let it wake us from sleep, but do nothing else
}