summaryrefslogtreecommitdiff
path: root/dali_ctl.c
blob: 726387e676bc75d74151d20c0bf3461f02a32365 (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
#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;

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) {
				if ((dali_rx & 0x81) == 0x01) {
					uart_puts(" short: ");
					uart_puthex(dali_rx >> 1);
					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");

					dali_assign++;
				}
			} 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);
}