summaryrefslogtreecommitdiff
path: root/dali_ctl.c
blob: 797f58fb18c6241cffa31d11fa4cb6eb6070e176 (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
#define DALI_C_TERMINATE	0xa100
#define DALI_C_DTR		0xa300
#define DALI_C_INITIALISE	0xa500
#define DALI_C_RANDOMISE	0xa700
#define DALI_C_COMPARE		0xa900
#define DALI_C_WITHDRAW		0xab00

#define DALI_C_SADDR_H		0xb100
#define DALI_C_SADDR_M		0xb300
#define DALI_C_SADDR_L		0xb500

#define DALI_C_PROGSHORT	0xb701
#define DALI_C_VRFYSHORT	0xb901
#define DALI_C_QURYSHORT	0xbb00

static uint8_t dali_s_byte, dali_sh, dali_sm, dali_sl;
static bool dali_s_notfound;

/* [0] bit 0 => addr 0, [0] bit 1 => addr 1, etc. */
static uint8_t dali_map[8];

EEMEM uint8_t dali_nextaddr = 0x02;
static uint8_t dali_assign;

static bool dali_compare(void)
{
	uint16_t manchester = dalistat.manchester, falsestart = dalistat.falsestart, noise = dalistat.noise;

	dali_send(DALI_C_COMPARE);
	asm volatile ("" ::: "memory");

	return dali_rx_avail
		|| (manchester != dalistat.manchester)
		|| (falsestart != dalistat.falsestart)
		|| (noise != dalistat.noise);
}

static void dali_search_byte(uint16_t cmd)
{
	dali_s_byte = 0xff;
	uint8_t bit = 0x80;

	while (bit) {
		dali_twice(cmd | (dali_s_byte & ~bit));
		if (dali_compare()) {
			_delay_ms(1);
			if (dali_compare())
				dali_s_byte &= ~bit;
		}
		bit >>= 1;
	}
	dali_twice(cmd | dali_s_byte);
}

static void dali_search_single(void)
{
	dali_twice(DALI_C_SADDR_H | 0xff);
	dali_twice(DALI_C_SADDR_M | 0xff);
	dali_twice(DALI_C_SADDR_L | 0xff);

	if (!dali_compare()) {
		dali_s_notfound = 1;
		return;
	}

	dali_search_byte(DALI_C_SADDR_H);
	if (dali_s_notfound)
		return;
	dali_sh = dali_s_byte;
	dali_search_byte(DALI_C_SADDR_M);
	if (dali_s_notfound)
		return;
	dali_sm = dali_s_byte;
	dali_search_byte(DALI_C_SADDR_L);
	if (dali_s_notfound)
		return;
	dali_sl = dali_s_byte;
}

static void dali_search(void)
{
	dali_twice(DALI_C_INITIALISE);
	// dali_twice(DALI_C_RANDOMISE);

	dali_assign = eeprom_read_byte(&dali_nextaddr);

	do {
		dali_search_single();
		if (!dali_s_notfound) {
			uart_puts("dali scan found\t\t");
			uart_puthex(dali_sh);
			uart_puthex(dali_sm);
			uart_puthex(dali_sl);
			dali_send(DALI_C_QURYSHORT);
			if (dali_rx_avail) {
				uint8_t addr = 0xff;

				if ((dali_rx & 0x81) == 0x01) {
					addr = dali_rx >> 1;

					uart_puts(" short: ");
					uart_puthex(addr);
					uart_puts("\n");
				} else {
					uart_puts(" noshort ");

					dali_send(DALI_C_PROGSHORT | (dali_assign << 1));
					dali_send(DALI_C_VRFYSHORT | (dali_assign << 1));
					if (dali_rx_avail) {
						uart_puts("prog ");
						uart_puthex(dali_assign);
						uart_puts("\n");
					} else
						uart_puts("progfail\n");

					addr = dali_assign;
					dali_assign++;
				}

				if (addr < 64)
					dali_map[addr >> 3] |= 1 << (addr & 0x7);
			} else
				uart_puts(" error\n");
			dali_send(DALI_C_WITHDRAW);
		}
	} while (!dali_s_notfound);

	dali_twice(DALI_C_TERMINATE);
	uart_puts("dali scan end\n");

	eeprom_write_byte(&dali_nextaddr, dali_assign);
}