]> git.zerfleddert.de Git - rsbs2/blame - bmc/chassis.c
use tristate on outputs. Tested with a PC connected and everything works :-)
[rsbs2] / bmc / chassis.c
CommitLineData
da7751cb 1#include <avr/io.h>
93402c2c 2#include <avr/interrupt.h>
da7751cb
MG
3#include <stdio.h>
4
ae50f4d4 5#include "config.h"
da7751cb
MG
6#include "chassis.h"
7
19d56e39
MG
8#ifdef __AVR_ATmega16__
9#define CHASSISPORT B
10#define POWER_PIN 0
11#define RESET_PIN 1
12#define ACTIVE_LOW
13#else
14#error "Please add chassis power/reset-PIN information for this chip"
15#endif
16
17#define __CPORT(port) PORT##port
18#define _CPORT(port) __CPORT(port)
19#define CPORT _CPORT(CHASSISPORT)
20
21#define __CDDR(port) DDR##port
22#define _CDDR(port) __CDDR(port)
23#define CDDR _CDDR(CHASSISPORT)
24
93402c2c
MG
25static volatile int power_cnt = 0;
26static volatile int reset_cnt = 0;
ae50f4d4 27static volatile int power_cycle = 0;
93402c2c 28
19d56e39
MG
29static void chassis_set_pins(uint8_t pins, uint8_t state);
30
da7751cb
MG
31void chassis_init()
32{
19d56e39 33 chassis_set_pins((1<<POWER_PIN) | (1<<RESET_PIN), 0);
93402c2c
MG
34
35 /* About 1ms */
70947537 36 OCR0 = ((F_CPU/64)/1000) - 1;
93402c2c 37
70947537 38 TCCR0 = ((1<<WGM01) | (1<<CS01) | (1<<CS00)); /* CTC, Prescaler 64 */
93402c2c
MG
39 TIMSK |= (1<<OCIE0);
40
19d56e39
MG
41}
42
adc673c1 43/* gracefully transition between tri-state and active */
19d56e39
MG
44static void chassis_set_pins(uint8_t pins, uint8_t state)
45{
19d56e39 46 if(state) {
adc673c1
MG
47 /* active */
48#ifndef ACTIVE_LOW
49 /* Pull UPs for a short moment... */
19d56e39 50 CPORT |= pins;
adc673c1
MG
51#endif
52 CDDR |= pins;
53#ifdef ACTIVE_LOW
54 CPORT &= ~pins;
55#endif
19d56e39 56 } else {
adc673c1
MG
57#ifdef ACTIVE_LOW
58 CPORT &= ~pins; /* NoOp... */
59#endif
60 CDDR &= ~pins;
61#ifndef ACTIVE_LOW
19d56e39 62 CPORT &= ~pins;
adc673c1 63#endif
19d56e39
MG
64 }
65}
66
67static void chassis_power(int msec)
68{
93402c2c 69 uint8_t old_SREG = SREG;
19d56e39
MG
70
71 chassis_set_pins((1<<POWER_PIN), 1);
72
93402c2c
MG
73 cli();
74 if (!power_cnt)
75 power_cnt = msec;
76 SREG = old_SREG;
19d56e39
MG
77}
78
79static void chassis_reset(int msec)
80{
93402c2c 81 uint8_t old_SREG = SREG;
19d56e39
MG
82
83 chassis_set_pins((1<<RESET_PIN), 1);
84
93402c2c
MG
85 cli();
86 if (!reset_cnt)
87 reset_cnt = msec;
88 SREG = old_SREG;
da7751cb
MG
89}
90
91void chassis_control(unsigned char action)
92{
ae50f4d4
MG
93 uint8_t old_SREG = SREG;
94
da7751cb
MG
95#ifdef DEBUG
96 printf("Chassis control 0x%02x\n", action);
97#endif
98
99 switch(action) {
100 case CHASSIS_ACTION_POWER_DOWN:
ae50f4d4 101 chassis_power(POWERDOWN_TIME_MS);
da7751cb
MG
102 break;
103
104 case CHASSIS_ACTION_POWER_UP:
ae50f4d4 105 chassis_power(POWERUP_TIME_MS);
da7751cb
MG
106 break;
107
108 case CHASSIS_ACTION_HARD_RESET:
ae50f4d4 109 chassis_reset(RESET_TIME_MS);
da7751cb
MG
110 break;
111
ae50f4d4
MG
112 case CHASSIS_ACTION_POWER_CYCLE:
113 cli();
114 power_cycle = POWER_CYCLE_PAUSE_MS;
115 SREG = old_SREG;
116 chassis_power(POWERDOWN_TIME_MS);
117
da7751cb 118 default:
f9d5c6e0 119#ifdef DEBUG
da7751cb 120 printf("Unimplemented chassis action 0x%02x\n", action);
f9d5c6e0 121#endif
da7751cb
MG
122 break;
123 }
124}
93402c2c
MG
125
126ISR(TIMER0_COMP_vect)
127{
128 if (power_cnt) {
129 power_cnt--;
130
131 if (!power_cnt)
132 chassis_set_pins((1<<POWER_PIN), 0);
ae50f4d4
MG
133 } else if (power_cycle) {
134 power_cycle--;
135
136 if (!power_cycle) {
137 chassis_set_pins((1<<POWER_PIN), 1);
138 power_cnt = POWERUP_TIME_MS;
139 }
93402c2c
MG
140 }
141 if (reset_cnt) {
142 reset_cnt--;
143
144 if (!reset_cnt)
145 chassis_set_pins((1<<RESET_PIN), 0);
146 }
147}
Impressum, Datenschutz