-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathds2413ex.c
192 lines (175 loc) · 4.23 KB
/
ds2413ex.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
#include "ows.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include <wdt.h>
#include "debounce.h"
#include <string.h> /* for memcpy */
#include <avr/eeprom.h>
#ifdef OWS_SPM_ENABLE
# include "ows_spm.h"
#endif
/*
* b0 - PioA
* b1 - PioB
* b2 - PioC
* b3 - PioD
* b4 - 1wire bus
*/
static struct {
uint8_t debouncer_mask;
uint8_t int_mask;
uint8_t int_type;
uint8_t padding[5];
} config;
void pio_send_state()
{
/* | 7 6 5 4 | 3 2 1 0 |
|<complement of 3-0>|OutB PinB OutA PinA | */
uint8_t sample = PIO_PORT(PIN) & 0x03;
sample = ((sample & 0x02) << 1) | (sample & 0x01);
/* output values is inversion of direction register */
sample |= ((PIO_PORT(DDR) & 0x02) << 2); /* OutB */
sample |= ((PIO_PORT(DDR) & 0x01) << 1); /* OutA */
sample |= (~sample << 4);
ows_send(sample);
}
void pio_send_state2()
{
/* | 7 6 5 4 | 3 2 1 0 |
|<complement of 3-0>|PinD PinC PinB PinA | */
uint8_t sample = (PIO_PORT(PIN) & ~config.debouncer_mask) | (debounced_state & config.debouncer_mask);
sample &= 0x0F;
sample |= (~sample << 4);
ows_send(sample);
}
inline void pio_read()
{
while(! errno)
pio_send_state();
}
inline void pio_read2()
{
while(! errno)
pio_send_state2();
}
void pio_write()
{
uint8_t data, cfm;
while(! errno)
{
data = ows_recv();
cfm = ~ows_recv();
if(cfm != data)
break;
data = cfm & 0x03;
data |= PIO_PORT(DDR) & ~0x03;
PIO_PORT(DDR) = data;
ows_send(0xAA);
pio_send_state();
}
}
void pio_write2()
{
uint8_t data, cfm;
while(! errno)
{
/* | 7 6 5 4 | 3 2 1 0 |
| x x x x |OutD OutC OutB OutA | */
data = ows_recv();
cfm = ~ows_recv();
if(cfm != data)
break;
data = cfm & 0x0F;
data |= PIO_PORT(DDR) & 0xF0;
PIO_PORT(DDR) = data;
ows_send(0xAA);
pio_send_state2();
}
}
ISR(TIM1_COMPA_vect) { /* occurs every 100uS */
}
int main()
{
cli();
wdt_disable();
#if defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny13__)
CLKPR = 0x80; /* Clock prescaler change enable */
CLKPR = 0x00; /* Division Factor = 1, system clock 9.6MHz */
#endif
ows_setup2(0x3A, 0);
eeprom_read_block(&config, (const void*)6, sizeof(config));
PIO_PORT(PORT) = 0;
#if 1
/* set up timer 1 */
TCCR1 = 1<<CTC1 | 0x04; /* CTC mode, prescaler = 4 (clk/8) */
GTCCR = 0;
OCR1A = 0; // interrupt on 0
OCR1C = CLK_FREQ / 80; /* 1/(9.6E6/8)*120=100uS period: OCR0A = 100 * CLK_FREQ / 1000 / 8 */
TIMSK |= 1<<OCIE1A; /* interrupt on compare match */
PLLCSR = 0;
#endif
for(;;)
ows_wait_request();
}
void ows_process_cmds()
{
switch(ows_recv())
{
case 0xF5: /* PIO ACCESS READ */
pio_read();
break;
case 0xFA: /* PIO ACCESS READ 2 */
pio_read2();
break;
case 0x5A: /* PIO ACCESS WRITE */
pio_write();
break;
case 0x5F: /* PIO ACCESS WRITE 2 */
pio_write2();
break;
case 0x4E: /* Write Scratchpad */
{
char buf[sizeof(config) + 1];
ows_recv_data(buf, sizeof(buf));
if(buf[sizeof(config)] == ows_crc8(buf, sizeof(config)))
memcpy(&config, buf, sizeof(config));
}
/* no break! */
case 0xBE: /* Read Scratchpad */
ows_send_data((char*)&config, 8);
ows_send(ows_crc8((char*)&config, 8));
break;
case 0x48: /* Copy Scratchpad */
eeprom_write_block(&config, (void*)6, sizeof(config));
break;
case 0xB8: /* Recall Scratchpad */
eeprom_read_block(&config, (const void*)6, sizeof(config));
break;
#ifdef OWS_SPM_ENABLE
case 0xDA:
ows_spm();
break;
#endif
default:
break;
}
}
void ows_process_interrupt()
{
int8_t diff = debounce(PIO_PORT(PIN));
#ifdef OWS_CONDSEARCH_ENABLE
/*
,----------- and --------+--> any
| ,-/ > or ----- and --> interrupt
l = int_mask(n) --|-- not --+-- or -- not -+--> edge /
h = int_mask(n+4) --+-- xor -----/ |
s = state(n) -----/ |
d = diff --------------------------------------'
*/
int8_t s = debounced_state;
int8_t h = config.int_mask >> 4;
int8_t il = ~config.int_mask & 0x0F;
if( ((il & h) | ~((s ^ h) | il)) & diff )
ows_set_flag(OWS_FLAG_CONDSEARCH | (config.int_type & (OWS_FLAG_INT_TYPE1 | OWS_FLAG_INT_TYPE2)));
#endif
}