#include <avr/io.h>
+#include <avr/interrupt.h>
#include <stdio.h>
+#include "config.h"
#include "chassis.h"
#ifdef __AVR_ATmega16__
#define _CDDR(port) __CDDR(port)
#define CDDR _CDDR(CHASSISPORT)
+static volatile int power_cnt = 0;
+static volatile int reset_cnt = 0;
+static volatile int power_cycle = 0;
+
static void chassis_set_pins(uint8_t pins, uint8_t state);
void chassis_init()
{
chassis_set_pins((1<<POWER_PIN) | (1<<RESET_PIN), 0);
- CDDR |= ((1<<POWER_PIN) | (1<<RESET_PIN));
+
+ /* About 1ms */
+ OCR0 = ((F_CPU/64)/1000) - 1;
+
+ TCCR0 = ((1<<WGM01) | (1<<CS01) | (1<<CS00)); /* CTC, Prescaler 64 */
+ TIMSK |= (1<<OCIE0);
+
}
+/* gracefully transition between tri-state and active */
static void chassis_set_pins(uint8_t pins, uint8_t state)
{
-#ifdef ACTIVE_LOW
- state = !state;
-#endif
-
if(state) {
+ /* active */
+#ifndef ACTIVE_LOW
+ /* Pull UPs for a short moment... */
CPORT |= pins;
+#endif
+ CDDR |= pins;
+#ifdef ACTIVE_LOW
+ CPORT &= ~pins;
+#endif
} else {
+#ifdef ACTIVE_LOW
+ CPORT &= ~pins; /* NoOp... */
+#endif
+ CDDR &= ~pins;
+#ifndef ACTIVE_LOW
CPORT &= ~pins;
+#endif
}
}
static void chassis_power(int msec)
{
- volatile int i;
+ uint8_t old_SREG = SREG;
chassis_set_pins((1<<POWER_PIN), 1);
- /* FIXME */
- for(i = 0; i < (msec<<2); i++);
-
- chassis_set_pins((1<<POWER_PIN), 0);
+ cli();
+ if (!power_cnt)
+ power_cnt = msec;
+ SREG = old_SREG;
}
static void chassis_reset(int msec)
{
- volatile int i;
+ uint8_t old_SREG = SREG;
chassis_set_pins((1<<RESET_PIN), 1);
- /* FIXME */
- for(i = 0; i < (msec<<2); i++);
-
- chassis_set_pins((1<<RESET_PIN), 0);
+ cli();
+ if (!reset_cnt)
+ reset_cnt = msec;
+ SREG = old_SREG;
}
void chassis_control(unsigned char action)
{
+ uint8_t old_SREG = SREG;
+
#ifdef DEBUG
printf("Chassis control 0x%02x\n", action);
#endif
switch(action) {
case CHASSIS_ACTION_POWER_DOWN:
- chassis_power(5000);
+ chassis_power(POWERDOWN_TIME_MS);
break;
case CHASSIS_ACTION_POWER_UP:
- chassis_power(500);
+ chassis_power(POWERUP_TIME_MS);
break;
case CHASSIS_ACTION_HARD_RESET:
- chassis_reset(500);
+ chassis_reset(RESET_TIME_MS);
break;
+ case CHASSIS_ACTION_POWER_CYCLE:
+ cli();
+ power_cycle = POWER_CYCLE_PAUSE_MS;
+ SREG = old_SREG;
+ chassis_power(POWERDOWN_TIME_MS);
+
default:
#ifdef DEBUG
printf("Unimplemented chassis action 0x%02x\n", action);
break;
}
}
+
+ISR(TIMER0_COMP_vect)
+{
+ if (power_cnt) {
+ power_cnt--;
+
+ if (!power_cnt)
+ chassis_set_pins((1<<POWER_PIN), 0);
+ } else if (power_cycle) {
+ power_cycle--;
+
+ if (!power_cycle) {
+ chassis_set_pins((1<<POWER_PIN), 1);
+ power_cnt = POWERUP_TIME_MS;
+ }
+ }
+ if (reset_cnt) {
+ reset_cnt--;
+
+ if (!reset_cnt)
+ chassis_set_pins((1<<RESET_PIN), 0);
+ }
+}