summaryrefslogtreecommitdiff
path: root/autotest.py
blob: 4490c01c173b6c44f7ee3859656657a586b794f4 (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
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
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#!/usr/bin/env python

import usb.core
import usb.util
import time, struct

from hidapi import hidapi
import ctypes

from elftools.elf.elffile import ELFFile

pid_runtime = 0x6080
pid_bootloader = 0x6084

e = ELFFile(open('arcin.elf'))

firmware = ''

for segment in sorted(e.iter_segments(), key = lambda x: x.header.p_paddr):
	if segment.header.p_type != 'PT_LOAD':
		continue
	
	data = segment.data()
	lma = segment.header.p_paddr
	
	# Workaround for LD aligning segments to a larger boundary than 8k.
	if lma == 0x8000000:
		lma += 0x2000
		data = data[0x2000:]
	
	# Add padding if necessary.
	firmware += '\0' * (lma - 0x8002000 - len(firmware))
	
	firmware += data

# Align to 64B
if len(firmware) & (64 - 1):
	firmware += '\0' * (64 - (len(firmware) & (64 - 1)))

# Find test board.
dev = usb.core.find(idVendor = 0x1234, idProduct = 0x5678)

if not dev:
	print 'Test board not found.'
	exit(1)

def set_buttons(value):
	dev.ctrl_transfer(0xc0, 0xf0, value, 0, 0)

def get_leds():
	return struct.unpack('<I', ''.join(chr(c) for c in dev.ctrl_transfer(0xc0, 0xf1, 0, 0, 4)))[0]

def count_qe(value):
	dev.ctrl_transfer(0xc0, 0xf2, value & 0xffff, 0, 0)

def open_hiddev(pid):
	global hiddev
	
	hidapi.hid_exit()
	hiddev = hidapi.hid_open(0x1d50, pid, None)
	
	if not hiddev: 
		raise RuntimeError('Target not found.')

def flash_board():
	print 'Found bootloader device, starting flashing.'
	
	# Prepare
	if hidapi.hid_send_feature_report(hiddev, ctypes.c_char_p('\x00\x20'), 2) != 2:
		raise RuntimeError('Prepare failed.')
	
	buf = firmware
	
	# Flash
	while buf:
		if hidapi.hid_write(hiddev, ctypes.c_char_p('\x00' + buf[:64]), 65) != 65:
			raise RuntimeError('Writing failed.')
		buf = buf[64:]
	
	# Finish
	if hidapi.hid_send_feature_report(hiddev, ctypes.c_char_p('\x00\x21'), 2) != 2:
		raise RuntimeError('Finish failed.')
	
	print 'Flashing finished, resetting to runtime.'
	
	# Reset
	if hidapi.hid_send_feature_report(hiddev, ctypes.c_char_p('\x00\x11'), 2) != 2:
		raise RuntimeError('Reset failed.')

class TestFail(Exception):
	pass

def test_leds(value):
	if hidapi.hid_write(hiddev, ctypes.c_char_p('\x00' + struct.pack('<H', value)), 3) != 3:
		raise RuntimeError('Writing failed.')
	
	v = get_leds()
	
	#print 'Set leds to %#x, got back %#x.' % (value, v)
	
	if v != value | 0x30000:
		raise TestFail('leds')

def test_buttons(value):
	set_buttons(value)
	
	time.sleep(0.04)
	
	data = ctypes.create_string_buffer(4)
	if hidapi.hid_read(hiddev, data, 4) != 4:
		raise RuntimeError('Reading failed.')
	
	v = struct.unpack('<HBB', data)[0]
	
	#print 'Set buttons to %#x, got back %#x.' % (value, v)
	
	if v != value:
		raise TestFail('buttons')

def test_qe(value):
	data = ctypes.create_string_buffer(4)
	if hidapi.hid_read(hiddev, data, 4) != 4:
		raise RuntimeError('Reading failed.')
	
	but, a, b = struct.unpack('<HBB', data)
	
	count_qe(value)
	
	time.sleep(0.1)
	
	data = ctypes.create_string_buffer(4)
	if hidapi.hid_read(hiddev, data, 4) != 4:
		raise RuntimeError('Reading failed.')
	
	but, va, vb = struct.unpack('<HBB', data)
	
	#print 'Count of %d: %d -> %d, %d -> %d' % (value, a, va, b, vb)
	
	if (a + value) & 0xff != va:
		raise TestFail('qe1')
	
	if (b + value) & 0xff != vb:
		raise TestFail('qe2')

def test_all():
	print 'Testing leds.'
	
	test_leds(0)
	test_leds(0x7ff)
	
	for i in range(11):
		test_leds(1 << i)
	
	print 'Testing buttons.'
	
	test_buttons(0)
	test_buttons(0x7ff)
	
	for i in range(11):
		test_buttons(1 << i)
	
	print 'Testing encoders.'
	
	test_qe(5)
	test_qe(5)
	test_qe(-5)
	test_qe(-5)
	
	print 'All passed.'

def process():
	try:
		open_hiddev(pid_runtime)
		
		print 'Found runtime device, resetting to bootloader.'
		
		# Reset bootloader
		if hidapi.hid_send_feature_report(hiddev, ctypes.c_char_p('\x00\x10'), 2) != 2:
			raise RuntimeError('Reset failed.')
		
		time.sleep(1)
	except:
		pass
	
	try:
		open_hiddev(pid_bootloader)
		
		flash_board()
		
		time.sleep(1)
		
		open_hiddev(pid_runtime)
		
		test_all()
	
	except TestFail, e:
		print 'Test failed:', e
	
	except RuntimeError, e:
		print 'Error:', e

while 1:
	raw_input('Press enter to start\n')
	
	process()
	print