summaryrefslogtreecommitdiff
path: root/read-rom/main.c
blob: e20b45f72a75b75b4b8df03190a99c2e75570739 (plain)
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
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdlib.h>

/*
 * Onewire iButton / SmartButton slave.
 * Has the 64bit ID set below
 * (corresponds to <https://wiki.chaosdorf.de/images/f/fc/Smartbutton.jpg>).
 *
 * Only supports non-overdrive READ ROM. Does not hold any data.
 *
 * Tested and working with a DS2482. Should mostly adhere to the standard,
 * but nothing is guaranteed.
 *
 * Any unexpected input (SKIP ROM, overdriv, ...) may cause a hangup requiring
 * an AVR reset.
 */

#define ADDR1 0xC4
#define ADDR2 0x00
#define ADDR3 0x00
#define ADDR4 0x09
#define ADDR5 0x7d
#define ADDR6 0x79
#define ADDR7 0x04
#define ADDR8 0x01

// HCNT: r30 (ZL), r31 (ZH)
// LCNT: r28 (YL), r29 (YH)

#define LCNTH GPIOR2
#define LCNTL GPIOR1
#define HCNTL GPIOR0

#define CNT USIDR
#define LASTCMD OCR0B
#define BUF OCR0A
#define POS OCR1A
#define APOS OCR1B
#define BYTE EEDR

int main (void)
{
	/* watchdog reset after ~4 seconds */
	MCUSR &= ~_BV(WDRF);
	WDTCSR = _BV(WDCE) | _BV(WDE);
	WDTCSR = _BV(WDE) | _BV(WDP3);

	MCUCR = _BV(ISC10);
	GIMSK = _BV(INT1);

	ACSR |= _BV(ACD);

	POS = 0;
	APOS = 0;
	DDRD = 0;
	PORTD = 0;

	sei();

	asm volatile ("ldi r28, 0");
	asm volatile ("ldi r29, 0");
	asm volatile ("ldi r30, 0");
	asm volatile ("ldi r31, 0");

	// 1us
	while (1) { // 1c
		asm volatile ("inc r30"); // 1c
		asm volatile ("adiw r28, 1"); // 2c
		asm volatile ("wdr"); // 1c
	}

	return 0;
}

ISR(INT1_vect)
{
	if (PIND & _BV(PD3)) {

		asm("out 0x15, r29"); // LCNTH
		asm("out 0x14, r28"); // LCNTL
		asm("out 0x13, r30"); // HCNTL

		// > 256us - reset
		if (LCNTH > 0) {
			DDRD = _BV(PD3);
			// 120us
			for (CNT = 0; CNT < 120; CNT++) {
				asm volatile ("wdr");
			}
			DDRD = 0;
			asm volatile ("wdr");
			EIFR |= _BV(INTF1);
		}
		// ~60us - write 0
		else if (LCNTL > 6) {
			if (!LASTCMD)
				POS++;
		}
		// < ~15us - write 1 OR read
		else {
			if (!LASTCMD) {
				BUF |= _BV(POS);
				POS++;
			}
		}
		if (!LASTCMD && (POS == 7)) {
			LASTCMD = BUF;
			POS = 1;
			APOS = 0;
			BYTE = ~ADDR8;
			MCUCR = _BV(ISC11);
			EIFR |= _BV(INTF1);
		}


		asm volatile ("ldi r30, 1"); // HCNTL = 1
	}
	else {
		if (LASTCMD == 0x33) {

			if (BYTE & POS) {

				DDRD = _BV(PD3);
				// 15us
				for (CNT = 0; CNT < 18; CNT++) {
					asm volatile ("wdr");
				}
				DDRD = 0;
				asm volatile ("wdr");
				EIFR |= _BV(INTF1);
			}
			if (POS != 0x80) {
				POS <<= 1;
			}
			else {
				APOS++;
				POS = 1;
				if (APOS == 1)
					BYTE = ~ADDR7;
				else if (APOS == 2)
					BYTE = ~ADDR6;
				else if (APOS == 3)
					BYTE = ~ADDR5;
				else if (APOS == 4)
					BYTE = ~ADDR4;
				else if (APOS == 5)
					BYTE = ~ADDR3;
				else if (APOS == 6)
					BYTE = ~ADDR2;
				else if (APOS == 7)
					BYTE = ~ADDR1;

				else if (APOS == 8) {
					LASTCMD = 0;
					MCUCR = _BV(ISC10);
					POS = 0;
				}
			}
		}
		asm volatile ("ldi r29, 0"); // LCNTH = 0
		asm volatile ("ldi r28, 1"); // LCNTL = 1

	}

}