]> git.zerfleddert.de Git - rsbs2/blob - bmc/chassis.c
use tristate on outputs. Tested with a PC connected and everything works :-)
[rsbs2] / bmc / chassis.c
1 #include <avr/io.h>
2 #include <avr/interrupt.h>
3 #include <stdio.h>
4
5 #include "config.h"
6 #include "chassis.h"
7
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
25 static volatile int power_cnt = 0;
26 static volatile int reset_cnt = 0;
27 static volatile int power_cycle = 0;
28
29 static void chassis_set_pins(uint8_t pins, uint8_t state);
30
31 void chassis_init()
32 {
33 chassis_set_pins((1<<POWER_PIN) | (1<<RESET_PIN), 0);
34
35 /* About 1ms */
36 OCR0 = ((F_CPU/64)/1000) - 1;
37
38 TCCR0 = ((1<<WGM01) | (1<<CS01) | (1<<CS00)); /* CTC, Prescaler 64 */
39 TIMSK |= (1<<OCIE0);
40
41 }
42
43 /* gracefully transition between tri-state and active */
44 static void chassis_set_pins(uint8_t pins, uint8_t state)
45 {
46 if(state) {
47 /* active */
48 #ifndef ACTIVE_LOW
49 /* Pull UPs for a short moment... */
50 CPORT |= pins;
51 #endif
52 CDDR |= pins;
53 #ifdef ACTIVE_LOW
54 CPORT &= ~pins;
55 #endif
56 } else {
57 #ifdef ACTIVE_LOW
58 CPORT &= ~pins; /* NoOp... */
59 #endif
60 CDDR &= ~pins;
61 #ifndef ACTIVE_LOW
62 CPORT &= ~pins;
63 #endif
64 }
65 }
66
67 static void chassis_power(int msec)
68 {
69 uint8_t old_SREG = SREG;
70
71 chassis_set_pins((1<<POWER_PIN), 1);
72
73 cli();
74 if (!power_cnt)
75 power_cnt = msec;
76 SREG = old_SREG;
77 }
78
79 static void chassis_reset(int msec)
80 {
81 uint8_t old_SREG = SREG;
82
83 chassis_set_pins((1<<RESET_PIN), 1);
84
85 cli();
86 if (!reset_cnt)
87 reset_cnt = msec;
88 SREG = old_SREG;
89 }
90
91 void chassis_control(unsigned char action)
92 {
93 uint8_t old_SREG = SREG;
94
95 #ifdef DEBUG
96 printf("Chassis control 0x%02x\n", action);
97 #endif
98
99 switch(action) {
100 case CHASSIS_ACTION_POWER_DOWN:
101 chassis_power(POWERDOWN_TIME_MS);
102 break;
103
104 case CHASSIS_ACTION_POWER_UP:
105 chassis_power(POWERUP_TIME_MS);
106 break;
107
108 case CHASSIS_ACTION_HARD_RESET:
109 chassis_reset(RESET_TIME_MS);
110 break;
111
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
118 default:
119 #ifdef DEBUG
120 printf("Unimplemented chassis action 0x%02x\n", action);
121 #endif
122 break;
123 }
124 }
125
126 ISR(TIMER0_COMP_vect)
127 {
128 if (power_cnt) {
129 power_cnt--;
130
131 if (!power_cnt)
132 chassis_set_pins((1<<POWER_PIN), 0);
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 }
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