Exemple #1
0
void pmu_power_on(void)
{
	uint8_t i;
	int8_t ret;
	pmu_regulator_t *reg;

	/* if somehow this gets called twice, bail early on */
	if (is_booting)
		return;
	else if (is_on)
		return;
	else
		state = BOOT;

	/* reset the fpga */
	pmu_reset_fpga(true);
	fpga_init();

	for (i = 0; i < ARRAY_SIZE(boot_order); i++) {
		reg = boot_order[i];
		/* if regulator set a on/off function, call it */
		if (reg->ops->set_regulator) {
			ret = pmu_set_regulator(reg, true);
			if (ret) {
				pmu_error = reg->error_code;
				goto fail_regulators;
			}
		}

		/* if regulator set a set_voltage function, call it */
		if (reg->ops->set_voltage && reg->voltage) {
			ret = reg->ops->set_voltage(reg, reg->voltage);
			if (ret) {
				pmu_error = reg->error_code;
				goto fail_regulators;
			}
		}

		/* if we got here, this means all is well */
		reg->powered = true;
	}

	/* enable the usb clock */
	io_set_pin(USB_CLK_EN);
	_delay_ms(PMU_USB_CLK_WAIT);
	io_set_pin(FTDI_RESETn);
	_delay_ms(PMU_FTDI_WAIT);

	/* power for the fpga should be up now, let it run */
	pmu_reset_fpga(false);

	state = ON;

	return;

fail_regulators:
	/* TODO: Turn of stuff again in reverse order */
	return;
}
Exemple #2
0
bool ltc3675_init(ltc3675_reg_helper_fn helper)
{
	if (helper)
		_ltc3675_reg_helper = helper;
	else
		_ltc3675_reg_helper = _ltc3675_default_reg_helper;
#ifdef HARDWIRE_ENABLE
    io_output_pin(PWR_EN1);
    io_output_pin(PWR_EN2);
    io_output_pin(PWR_EN3);
    io_output_pin(PWR_EN4);
    io_output_pin(PWR_EN5);
#endif // HARDWIRE_ENABLE

 /*	io_output_pin(PWR_SDA);
    io_output_pin(PWR_SCL);

    // Must remain HIGH when idle
    io_set_pin(PWR_SDA);
    io_set_pin(PWR_SCL);
*/
#ifdef I2C_REWORK
	i2c_init_ex(PWR_SDA, PWR_SCL, _ltc3675_pull_up);
#endif // I2C_REWORK
    io_input_pin(PWR_IRQ);
#if !defined(DEBUG) && !defined(ATTINY88_DIP)
	io_set_pin(PWR_IRQ);	// Enable pull-up for Open Drain
#endif // DEBUG
	
    io_input_pin(WAKEUP);
	io_set_pin(WAKEUP);	// Enable pull-up for Open Drain
	
    io_input_pin(ONSWITCH_DB);
	io_set_pin(ONSWITCH_DB);	// Enable pull-up for Open Drain
	
    io_input_pin(PWR_RESET);
	io_set_pin(PWR_RESET);	// Enable pull-up for Open Drain
	
	_ltc3675_clear_irq();	// Clear old interrupt - state might have changed (e.g. undervoltage might have been resolved)

    if (i2c_write_ex(PWR_SDA, PWR_SCL, LTC3675_WRITE_ADDRESS, LTC3675_REG_IRQB_MASK, 0xFF, _ltc3675_pull_up) == false)	// Any PGOOD fault will pull IRQB low
		return false;
	
	if (i2c_write_ex(PWR_SDA, PWR_SCL, LTC3675_WRITE_ADDRESS, LTC3675_REG_UVOT, 0x70, _ltc3675_pull_up) == false)	// 3.4V UV
		return false;
	
	if (ltc3675_has_interrupt())
		_ltc3675_handle_irq();
	
	// Non-maskable:
	//	UV warning threshold (default): 2.7V
	//	Over temp warning threshold (default): 10 degrees below

    return true;
}
Exemple #3
0
static void pmu_reset_fpga(bool delay)
{
	io_clear_pin(PS_POR);
	io_clear_pin(PS_SRST);

	if (delay)
		_delay_ms(PMU_FPGA_RESET_DELAY);

	io_set_pin(PS_POR);
	io_set_pin(PS_SRST);
}
Exemple #4
0
static bool _i2c_read_byte_ex(io_pin_t sda, io_pin_t scl, uint8_t* value, bool pull_up)
{
    // Assumes:
    //  SDA output is LOW
    //  SCL output is LOW
	
	io_input_pin(sda);
	if (pull_up)
		io_set_pin(sda);	// OK to leave line floating for a moment (better not to drive as slave will be pulling it to ground)

    (*value) = 0x00;

    for (uint8_t i = 0; i < 8; ++i)
    {
//		if (pull_up)
//			io_set_pin(scl);	// [Not ideal with pull-up]
        io_input_pin(scl);	// Release HIGH
		if (pull_up)
			io_set_pin(scl);
        I2C_DELAY(I2C_DEFAULT_SCL_HIGH_PERIOD);
#ifdef I2C_ALLOW_CLOCK_STRETCH
		uint8_t retries = I2C_DEFAULT_MAX_BUS_RETRIES;
		while (io_test_pin(scl) == false)	// Clock stretch requested?
		{
			I2C_DELAY(I2C_DEFAULT_BUS_WAIT);
			if (--retries == 0)
			{
				debug_log_ex("I2C:R ");
				debug_log_hex(scl);
				debug_blink_rev(5);
				return false;
			}				
		}
#endif // I2C_ALLOW_CLOCK_STRETCH
        (*value) |= ((io_test_pin(sda) ? 0x1 : 0x0) << (7 - i));   // MSB first

		if (pull_up)
			io_clear_pin(scl);
        io_output_pin(scl);	// Drive LOW (not ideal with pull-up)
//		if (pull_up)
//			io_clear_pin(scl);
        I2C_DELAY(I2C_DEFAULT_SCL_LOW_PERIOD);
    }

    // Not necessary to ACK since it's only this one byte

    return true;
}
Exemple #5
0
void debug_init()
{
#ifdef ENABLE_SERIAL
	io_set_pin(SERIAL_DEBUG);
	io_output_pin(SERIAL_DEBUG);
#endif // ENABLE_SERIAL
}
Exemple #6
0
/*
static void _i2c_stop(io_pin_t sda, io_pin_t scl)
{
	_i2c_stop_ex(sda, scl, false);
}
*//*
static void _i2c_abort_safe_ex(io_pin_t pin, bool pull_up)
{
	if (io_is_output(pin))
	{
		if (io_is_pin_set(pin))	// This is bad - hope no slave is pulling down the line
		{
			io_input_pin(pin);	// Pull-up already enabled
			
			if (pull_up == false)
				io_clear_pin(pin);	// Doing this after changing direction ensures the line is not brought down
		}
		else	// Currently pulling line down
		{
			io_input_pin(pin);	// Hi-Z
			
			if (pull_up)	// There will be a moment where the line will float (better than driving the line though...)
			{
				io_set_pin(pin);
			}
		}
	}
	else	// Already an input
	{
		if (pull_up)
		{
			io_set_pin(pin);	// Enable pull-ups
		}
		else
		{
			io_clear_pin(pin);	// Disable pull-ups
		}
	}
	
	// Normally: pin will be Hi-Z input
	// With internal pull-up: pin will be input with pull-up enabled
}
*/
static void _i2c_abort_safe(io_pin_t pin, bool pull_up)
{
	if (pull_up == false)
		io_clear_pin(pin);	// Should never be output/HIGH, could be input/<was outputting HIGH> so disable pull-ups
	
	io_input_pin(pin);
	
	if (pull_up)
		io_set_pin(pin);	// Enable pull-up
}
Exemple #7
0
int8_t ltc3675_init(void)
{
	uint8_t id;
	int8_t ret;

	ret = ltc3675_read(LTC3675_REG_LED_CONFIG, &id);
	if (ret)
		return ret;

	button.pmu_button.ops = &ltc3675_pmu_button_ops;
	button.onswitch_last_state = io_test_pin(ONSWITCH_DB);

	/* setup the input pins with pull-up for open drain */
	io_input_pin(PWR_IRQ);
	io_set_pin(PWR_IRQ);
	io_input_pin(WAKEUP);
	io_set_pin(WAKEUP);
	io_input_pin(ONSWITCH_DB);
	io_set_pin(ONSWITCH_DB);
	io_input_pin(PWR_RESET);
	io_set_pin(PWR_RESET);

	/* clear the old interrupts */
	ltc3675_clear_interrupts();

	/* setup interrupt masks on chip to be notified of any faults */
	ret = ltc3675_write(LTC3675_REG_IRQB_MASK, 0xff);
	if (ret)
		goto fail_i2c_write_mask;

	/* program warning @ 3.4V */
	ret = ltc3675_write(LTC3675_REG_UVOT, 0x70);
	if (ret)
		goto fail_i2c_write_uvot;

	pmu_register_button(&button.pmu_button);

	return 0;

fail_i2c_write_uvot:
fail_i2c_write_mask:
	return ret;
}
Exemple #8
0
void tps54478_init(bool enable)
{
	/* enable pull-up for open drain */
	io_input_pin(CORE_PGOOD);
	io_set_pin(CORE_PGOOD);

	tps54478_set_regulator(NULL, enable);

	io_clear_pin(CORE_PWR_EN);
}
Exemple #9
0
/**
 * Initialize the ST7565
 */
void st7565_init(void)
{
    io_set_pin_dir(ST7565_RST_PORT,ST7565_RST_PIN, IO_DIR_OUT);
    io_set_pin_dir(ST7565_RS_PORT,ST7565_RS_PIN, IO_DIR_OUT);
    io_set_pin(ST7565_RST_PORT,ST7565_RST_PIN, 1);   
    tick_wait_ms(10);   
    io_set_pin(ST7565_RST_PORT,ST7565_RST_PIN, 0);   
    tick_wait_ms(10);   
    io_set_pin(ST7565_RST_PORT,ST7565_RST_PIN, 1);   
    tick_wait_ms(10);
    
    spi_set_baud(ST7565_DRV, ST7565_BAUD);
    
    spi_cs_en(ST7565_DRV);
    
    st7565_command(CMD_SET_BIAS_7);
    st7565_command(CMD_SET_ADC_NORMAL);
    st7565_command(CMD_SET_COM_NORMAL);
    st7565_command(CMD_SET_DISP_START_LINE);
    st7565_command(CMD_SET_POWER_CONTROL | 0x4);
    tick_wait_ms(50);

    st7565_command(CMD_SET_POWER_CONTROL | 0x6);
    tick_wait_ms(50);

    st7565_command(CMD_SET_POWER_CONTROL | 0x7);
    tick_wait_ms(10);

    st7565_command(CMD_SET_RESISTOR_RATIO | 0x6);
 
    st7565_command(CMD_DISPLAY_ON);
    st7565_command(CMD_SET_ALLPTS_NORMAL);

    /*Set brightness*/
    st7565_command(CMD_SET_VOLUME_FIRST);
    st7565_command(CMD_SET_VOLUME_SECOND | (0x18 & 0x3f));
    
    spi_cs_dis(ST7565_DRV);   
    
    memset(lcd_fb, 0x00, sizeof(lcd_fb));
}
Exemple #10
0
void debug_init()
{
	io_output_pin(DEBUG_1);
	io_output_pin(DEBUG_2);
	
	io_enable_pin(DEBUG_1, true);
	io_enable_pin(DEBUG_2, true);
#ifdef ENABLE_SERIAL	
	io_set_pin(SERIAL_DEBUG);
	io_output_pin(SERIAL_DEBUG);
#endif // ENABLE_SERIAL
}
Exemple #11
0
void _debug_log_ex(const char* message, bool new_line)
{
	if (message[0] == '\0')
	return;
	
	pmc_mask_irqs(true);

	do
	{
		_serial_tx_char(*message);
	} while (*(++message) != '\0');
	
	if (new_line)
	_serial_tx_char('\n');

	io_set_pin(SERIAL_DEBUG);
	
	pmc_mask_irqs(false);
}
Exemple #12
0
void debug_log_ex_P(const char* message, bool new_line)
{
	char c = pgm_read_byte(message);
	if (c == '\0')
		return;
	
	pmc_mask_irqs(true);

	do
	{
		_serial_tx_char(c);
		c = pgm_read_byte(++message);
	} while (c != '\0');
	
	if (new_line)
		_serial_tx_char('\n');

	io_set_pin(SERIAL_DEBUG);
	
	pmc_mask_irqs(false);
}
Exemple #13
0
/**
 * Write a command to the ST7565
 * @param cmd the command
 */
static void st7565_command(uint8_t cmd) 
{
    io_set_pin(ST7565_RS_PORT, ST7565_RS_PIN, ST7565_CMD_MODE);
    spi_xchg(ST7565_DRV, &cmd, NULL, sizeof(cmd));
}
Exemple #14
0
static bool _i2c_stop_ex(io_pin_t sda, io_pin_t scl, bool pull_up)
{
	// Assumes:
	//	SCL is output & LOW
	//	SDA is input (Hi-Z, or pull-up enabled)
	
	// Assuming pull-up already enabled
	//if (pull_up)
	//	io_set_pin(sda);
	
	bool result = true;
	
	// SDA should be HIGH after ACK has been clocked away
//	bool skip_drive = false;
	uint8_t retries = 0;
	while (io_test_pin(sda) == false)
	{
		if (retries == I2C_DEFAULT_MAX_ACK_RETRIES)
		{
			debug_log_ex("I2C:STP ", false);
			debug_log_hex(sda);
			debug_blink_rev(4);
			
//			skip_drive = true;
			result = false;
			break;	// SDA is being held low?!
		}

		++retries;
		I2C_DELAY(I2C_DEFAULT_RETRY_DELAY);
	}
	
	// STOP condition
//	if ((pull_up == false) || (skip_drive))
		io_clear_pin(sda);	// Don't tri-state if internal pull-up is used
//	//else
//	// Pin will now be driven, but having checked SDA is HIGH above means slave's SDA should be Open Collector (i.e. it won't blow up)
	io_output_pin(sda);	// Drive LOW
//	if (pull_up)
//		io_clear_pin(sda);

	///////////////////////////////////
	
//	if (pull_up)
//		io_set_pin(scl);	// Don't tri-state if internal pull-up is used. Line will be driven, but assuming this is the only master on the clock line (i.e. no one else will pull it low).
	io_input_pin(scl);
	if (pull_up)
		io_set_pin(scl);
	I2C_DELAY(I2C_DEFAULT_STOP_TIME);
	
	///////////////////////////////////

//	if ((pull_up) && (skip_drive == false))
//		io_set_pin(sda);	// Don't tri-state if internal pull-up is used
	io_input_pin(sda);
//	if ((pull_up) && (skip_drive))
		io_set_pin(sda);
	I2C_DELAY(I2C_DEFAULT_BUS_FREE_TIME);
	
	return result;
}
Exemple #15
0
bool i2c_read2_ex(io_pin_t sda, io_pin_t scl, uint8_t addr, uint8_t subaddr, uint8_t* value, bool pull_up)
{
	if (_i2c_start_ex(sda, scl, pull_up) == false)
		return false;

	if (_i2c_write_byte_ex(sda, scl, addr & ~0x01, pull_up) == false)
	{
#ifdef I2C_EXTRA_DEBUGGING
		//debug_log_ex("R21:", false);
		debug_log("R21");
		//debug_log_hex(addr);
#endif // I2C_EXTRA_DEBUGGING
		goto i2c_read2_fail;
	}

	if (_i2c_write_byte_ex(sda, scl, subaddr, pull_up) == false)
	{
#ifdef I2C_EXTRA_DEBUGGING
		//debug_log_ex("R22:", false);
		debug_log("R22");
		//debug_log_hex(subaddr);
#endif // I2C_EXTRA_DEBUGGING
		goto i2c_read2_fail;
	}
	
	io_input_pin(scl);
	if (pull_up)
		io_set_pin(scl);
	I2C_DELAY(I2C_DEFAULT_BUS_WAIT);
	
	if (_i2c_start_ex(sda, scl, pull_up) == false)
	{
		return false;
	}
	
	if (_i2c_write_byte_ex(sda, scl, addr | 0x01, pull_up) == false)
	{
#ifdef I2C_EXTRA_DEBUGGING
		//debug_log_ex("R23:", false);
		debug_log("R23");
		//debug_log_hex(addr);
#endif // I2C_EXTRA_DEBUGGING
		goto i2c_read2_fail;
	}

	if (_i2c_read_byte_ex(sda, scl, value, pull_up) == false)
	{
#ifdef I2C_EXTRA_DEBUGGING
		//debug_log_ex("R24:", false);
		debug_log("R24");
		//debug_log_hex(*value);
#endif // I2C_EXTRA_DEBUGGING
		goto i2c_read2_fail;
	}
	
	if (_i2c_stop_ex(sda, scl, pull_up) == false)
	{
#ifdef I2C_EXTRA_DEBUGGING
		debug_log("R25");
#endif // I2C_EXTRA_DEBUGGING
	}

	return true;
i2c_read2_fail:
	_i2c_abort_ex(sda, scl, pull_up);
	return false;
}
Exemple #16
0
/*
static void _i2c_abort(io_pin_t sda, io_pin_t scl)
{
	_i2c_abort_ex(sda, scl, false);
}
*/
static bool _i2c_write_byte_ex(io_pin_t sda, io_pin_t scl, uint8_t value, bool pull_up)
{
    // Assumes:
    //  SDA output is LOW
    //  SCL output is LOW

    for (uint8_t i = 0; i < 8; ++i)
    {
		bool b = ((value & (0x01 << (7 - i))) != 0x00);	// MSB first
		
		if (b)
		{
			if (pull_up)
			{
//				io_set_pin(sda);	// This is bad (will drive line for a moment), but more stable than letting line float
				io_input_pin(sda);
				io_set_pin(sda);
			}				
			else
				io_input_pin(sda);	// Release HIGH
			
			if (io_test_pin(sda) == false)
			{
				debug_log("I2C:WR ");
				debug_log_hex(sda);
				debug_blink_rev(1);
				return false;
			}			
		}			
		else
		{
			if (pull_up)
			{
//				if (io_is_output(sda))
					io_clear_pin(sda);
//				else
//				{
					io_output_pin(sda);	// [This is bad (will drive line for a moment), but more stable than letting line float]
//					io_clear_pin(sda);
//				}
			}
			else
			{
				io_enable_pin(sda, false);
				io_output_pin(sda);	// Drive LOW
			}				
		}
		
		///////////////////////////////

        io_input_pin(scl);	// Release HIGH
		if (pull_up)
			io_set_pin(scl);
        I2C_DELAY(I2C_DEFAULT_SCL_HIGH_PERIOD);
#ifdef I2C_ALLOW_CLOCK_STRETCH
		uint8_t retries = I2C_DEFAULT_MAX_BUS_RETRIES;
		while (io_test_pin(scl) == false)	// Clock stretch requested?
		{
			I2C_DELAY(I2C_DEFAULT_BUS_WAIT);
			if (--retries == 0)
			{
				io_input_pin(sda);	// Release HIGH
				if (pull_up)
					io_set_pin(sda);
				
				debug_log_ex("I2C:STRTCH ", false);
				debug_log_hex(scl);
				debug_blink_rev(2);
				return false;
			}
		}
#endif // I2C_ALLOW_CLOCK_STRETCH
		if (pull_up)
			io_clear_pin(scl);
        io_output_pin(scl);	// Drive LOW
        I2C_DELAY(I2C_DEFAULT_SCL_LOW_PERIOD);
    }

    io_input_pin(sda);	// Release HIGH
	if (pull_up)
		io_set_pin(sda);	// Assuming letting line float won't confuse slave when pulling line LOW for ACK
    I2C_DELAY(I2C_DEFAULT_SCL_HIGH_PERIOD);

    uint8_t retries = 0;
    while ((_i2c_disable_ack_check == false) && (io_test_pin(sda)))
    {
        if (retries == I2C_DEFAULT_MAX_ACK_RETRIES)
		{
			debug_log_ex("I2C:ACK ", false);
			debug_log_hex_ex(sda, false);
			debug_log_hex(value);
			debug_blink_rev(3);
            return false;	// Will abort and not release bus - done by caller
		}

        ++retries;
        I2C_DELAY(I2C_DEFAULT_RETRY_DELAY);
    }

    // Clock away acknowledge
//	if (pull_up)
//		io_set_pin(scl);
    io_input_pin(scl);	// Release HIGH
	if (pull_up)
		io_set_pin(scl);
    I2C_DELAY(I2C_DEFAULT_SCL_HIGH_PERIOD);

	if (pull_up)
		io_clear_pin(scl);
    io_output_pin(scl);	// Drive LOW
//	if (pull_up)
//		io_clear_pin(scl);
    I2C_DELAY(I2C_DEFAULT_SCL_LOW_PERIOD);

    return true;
}
Exemple #17
0
int8_t ltc294x_init(ltc294x_model_t model)
{
	uint8_t val;
	int8_t ret;

	/* make input, set pullup */
	io_input_pin(FG_ALn_CC);
	io_set_pin(FG_ALn_CC);

	gauge.pmu_gauge.ops = &ltc294x_pmu_gauge_ops;

	ret = ltc294x_read(LTC294X_REG_STATUS, &val);
	if (ret)
		goto fail_i2c_read;
	val &= LTC294X_CHIP_ID_MASK;
	val >>= LTC294X_CHIP_ID_SHIFT;

	if (val != model)
		goto fail_id;

	/* set ACR to 0, this allows for calibrating by
	 * completely discharging the battery once */
	ltc294x_set_charge(0x0010);

	/* set low threshold to 10% assuming full is 0xeae4... */
	ltc294x_write16(LTC294X_REG_LOW_THRESH_MSB, 0x1794);
	gauge.charge_lo_thesh = 0x1794;

	/* set high threshold for temperature to 85 C */
	ltc294x_write16(LTC294X_REG_TEMP_THRESH_HI, 0x98);
	gauge.temp_thresh_high = 0x9800;

	/* set low threshold for temperature to -2 C */
	ltc294x_write16(LTC294X_REG_TEMP_THRESH_LO, 0x74);
	gauge.temp_thresh_low = 0x7400;

	ret = ltc294x_read(LTC294X_REG_CONTROL, &val);
	if (ret)
		goto fail_i2c_read;

	/* enable automatic temp conversion */
	val &= ~LTC294X_ADC_MODE_MASK;
	val |= 0x3 << LTC294X_ADC_MODE_SHIFT;

	/* set prescaler to 16 */
	val &= ~LTC294X_PRESCALER_MASK;
	val |= 0x4 << LTC294X_PRESCALER_SHIFT;

	/* disable IRQ mode */
	val &= ~LTC294X_ALCC_CFG_MASK;
	val |= 0x0 << LTC294X_ALCC_CFG_SHIFT;

	ret = ltc294x_write(LTC294X_REG_CONTROL, val);

	pmu_register_gauge(&gauge.pmu_gauge);

	return 0;

fail_id:
fail_i2c_read:
	return ret;
}
Exemple #18
0
/**
 * Write data to the ST7565
 * @param data the data
 */
static void st7565_data(uint8_t data) 
{
    io_set_pin(ST7565_RS_PORT, ST7565_RS_PIN, ST7565_DATA_MODE);
    spi_xchg(ST7565_DRV, &data, NULL, sizeof(data));
}
Exemple #19
0
int8_t pmu_init(void)
{
	int8_t ret;
	bool battery_present;

	state = OFF;

	/* make panic button an input */
	io_input_pin(PANICn);
	panic_last = io_test_pin(PANICn);

	/* make the LED outputs */
	io_output_pin(CHARGE);
	io_output_pin(POWER_LED);

	/* initialize the ADC, so we can sense the battery */
	adc_init();

	/* initialize TPS54478 for core power */
	tps54478_init(true);

	/* wiggle USB and FTDI pins */
	io_input_pin(USB_RESETn);
	io_output_pin(FTDI_RESETn);
	io_output_pin(USB_CLK_EN);
	io_input_pin(FTDI_CBUS3);

	/* make OVERTEMP input pin */
	io_input_pin(OVERTEMP);

	/* initialize the charger */
	ret = bq2419x_init();
	if (ret)
		goto fail_bq2419x;

	/* wait a sec */
	_delay_ms(1000);

	/* wdt setup */
	cli();
	WDTCSR |= BIT(WDCE) | BIT(WDE);
	WDTCSR = BIT(WDIE);
	sei();

	/* see if we got a battery */
	battery_present = pmu_battery_present();
	battery_present_last = battery_present;

	if (battery_present) {
		last_full_charge = eeprom_get_last_full();
		ret = ltc294x_init(LTC294X_MODEL_2942);
	}
	if (ret)
		return ret;

	ret = ltc3675_init();
	if (ret)
		goto fail_ltc3675;


	/* need to hold them low until power is stable */
	io_output_pin(PS_POR);
	io_output_pin(PS_SRST);
	io_clear_pin(PS_POR);
	io_clear_pin(PS_SRST);

	/* TODO: Not sure if needed */
	io_input_pin(AVR_RESET);

	/* TODO: This will probably need to change */
	io_input_pin(AVR_IRQ);
	io_set_pin(AVR_IRQ); // enable pull-up ?

	/* configure and enable interrupts */
	interrupt_init();

	/* initialize the timers */
	timer0_init();
	timer1_init();

	state = OFF;

	return 0;

fail_ltc3675:
fail_bq2419x:
	return -1;
}