1 /*
2  * Copyright (C) 2005-2019 Darron Broad
3  * All rights reserved.
4  *
5  * This file is part of Pickle Microchip PIC ICSP.
6  *
7  * Pickle Microchip PIC ICSP is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as published
9  * by the Free Software Foundation.
10  *
11  * Pickle Microchip PIC ICSP is distributed in the hope that it will be
12  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
14  * Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with Pickle Microchip PIC ICSP. If not, see http://www.gnu.org/licenses/
18  */
19 
20 #include "pickle.h"
21 
22 /******************************************************************************
23  *
24  * Session
25  *
26  *****************************************************************************/
27 
28 extern struct pickle p;
29 
30 /*****************************************************************************
31  *
32  * Hardware operations
33  *
34  *****************************************************************************/
35 
36 struct pic_ops pic16n_ops = {
37 	.arch				= ARCH16BIT,
38 	.align				= sizeof(uint8_t),
39 	.selector			= pic16n_selector,
40 #ifdef LOADER
41 	.bootloader			= pic16n_bootloader,
42 #else
43 	.bootloader			= NULL,
44 #endif
45 	.program_begin			= pic16n_program_begin,
46 	.program_data			= pic16n_program_data,
47 	.program_end			= pic16n_program_end,
48 	.verify_begin			= pic16n_program_verify,
49 	.verify_data			= pic16n_verify_data,
50 	.verify_end			= pic16n_standby,
51 	.view_data			= pic16n_view_data,
52 	.read_config_memory		= pic16n_read_config_memory,
53 	.get_program_count		= pic16n_get_program_count,
54 	.get_program_size		= pic16n_get_program_size,
55 	.get_data_size			= pic16n_get_data_size,
56 	.get_executive_size		= NULL,
57 	.get_boot_size			= NULL,
58 	.read_program_memory_block	= pic16n_read_program_memory_block,
59 	.read_data_memory_block		= pic16n_read_data_memory_block,
60 	.write_panel			= pic16n_write_panel,
61 	.bulk_erase			= pic16n_bulk_erase,
62 	.write_osccal			= NULL,
63 	.write_bandgap			= NULL,
64 	.write_calib			= NULL,
65 	.row_erase			= NULL,
66 	.dumpdeviceid			= pic16n_dumpdeviceid,
67 	.dumpconfig			= pic16n_dumpconfig,
68 	.dumposccal			= NULL,
69 	.dumpdevice			= pic16n_dumpdevice,
70 	.dumpadj			= 2,
71 	.dumphexcode			= pic16n_dumphexcode,
72 	.dumpinhxcode			= pic16n_dumpinhxcode,
73 	.dumphexdata			= pic16n_dumphexdata,
74 	.dumpinhxdata			= pic16n_dumpinhxdata,
75 	.debug				= NULL,
76 };
77 
78 uint32_t
pic16n_arch(void)79 pic16n_arch(void)
80 {
81 	p.pic = &pic16n_ops;
82 
83 	return p.pic->arch;
84 }
85 
86 /*****************************************************************************
87  *
88  * Hardware configuration
89  *
90  *****************************************************************************/
91 
92 struct pic16n_config pic16n_conf;
93 
94 /*****************************************************************************
95  *
96  * Hardware config masks
97  *
98  *  DS40001772B TABLE B-4: SUMMARY OF CONFIGURATION WORDS
99  *  DS40001836A TABLE B-4: SUMMARY OF CONFIGURATION WORDS
100  *  DS40001886B TABLE B-4: SUMMARY OF CONFIGURATION WORDS
101  *  DS40001927A TABLE B-4: SUMMARY OF CONFIGURATION WORDS
102  *  DS40001874F TABLE B-1: CONFIGURATION WORD AND MASK
103  *
104  * In the following tables ZERO represents undocumented configuration bits
105  *
106  *****************************************************************************/
107 
108 /*                          0 1L 1 1H 2 2L 3 2H 4 3L 5 3H 6 4L 7 4H 8 5L 9 5H A 6L B 6H */
109 uint8_t DS40001772B_B4[] = {0x77,0x29,0xE3,0xBF,0x7F,0x3F,0xFF,0x37,0x03,ZERO,0xFF,0x02};
110 uint8_t DS40001836A_B4[] = {0x77,0x2B,0xFF,0xBF,0x7F,0x3F,0x9F,0x2F,0x01,0x00};
111 uint8_t DS40001886B_B4[] = {0x77,0x2B,0xFF,0xBF,0x7F,0x3F,0x9F,0x2F,0x01,0x00};
112 uint8_t DS40001927A_B4[] = {0x77,0x2B,0xFF,0xBF,0x7F,0x3F,0x9F,0x2F,0x01,0x00};
113 uint8_t DS40001874F_B1[] = {0x77,0x29,0xE3,0xBF,0x7F,0x3F,0xFF,0x37,0x03,0x00,0xFF,0x02};
114 
115 /*****************************************************************************
116  *
117  * Hardware algorithm map
118  *
119  *****************************************************************************/
120 
121 struct pic16n_dsmap pic16n_map[] =
122 {
123 /*Device name	Device id	Data-sheet	Flash		 Config   EEProm	Latches Inf/Con/Id	MASKS*/
124 {"PIC18F24K40", PIC18F24K40,    DS40001772B,	PIC16N_WORD(16), 12,      256,		64,	0,0,16,		DS40001772B_B4},
125 {"PIC18F25K40", PIC18F25K40,    DS40001772B,	PIC16N_WORD(32), 12,      256,		64,	0,0,16,		DS40001772B_B4},
126 {"PIC18F45K40", PIC18F45K40,    DS40001772B,	PIC16N_WORD(32), 12,      256,		64,	0,0,16,		DS40001772B_B4},
127 {"PIC18F26K40", PIC18F26K40,    DS40001772B,	PIC16N_WORD(64), 12,      1024,		64,	0,0,16,		DS40001772B_B4},
128 {"PIC18F46K40", PIC18F46K40,    DS40001772B,	PIC16N_WORD(64), 12,      1024,		64,	0,0,16,		DS40001772B_B4},
129 {"PIC18F27K40", PIC18F27K40,    DS40001772B,	PIC16N_WORD(128),12,      1024,		128,	0,0,16,		DS40001772B_B4},
130 {"PIC18F47K40", PIC18F47K40,    DS40001772B,	PIC16N_WORD(128),12,      1024,		128,	0,0,16,		DS40001772B_B4},
131 {"PIC18LF24K40",PIC18LF24K40,   DS40001772B,	PIC16N_WORD(16), 12,      256,		64,	0,0,16,		DS40001772B_B4},
132 {"PIC18LF25K40",PIC18LF25K40,   DS40001772B,	PIC16N_WORD(32), 12,      256,		64,	0,0,16,		DS40001772B_B4},
133 {"PIC18LF45K40",PIC18LF45K40,   DS40001772B,	PIC16N_WORD(32), 12,      256,		64,	0,0,16,		DS40001772B_B4},
134 {"PIC18LF26K40",PIC18LF26K40,   DS40001772B,	PIC16N_WORD(64), 12,      1024,		64,	0,0,16,		DS40001772B_B4},
135 {"PIC18LF46K40",PIC18LF46K40,   DS40001772B,	PIC16N_WORD(64), 12,      1024,		64,	0,0,16,		DS40001772B_B4},
136 {"PIC18LF27K40",PIC18LF27K40,   DS40001772B,	PIC16N_WORD(128),12,      1024,		128,	0,0,16,		DS40001772B_B4},
137 {"PIC18LF47K40",PIC18LF47K40,   DS40001772B,	PIC16N_WORD(128),12,      1024,		128,	0,0,16,		DS40001772B_B4},
138 
139 {"PIC18F24K42", PIC18F24K42,    DS40001836A,	PIC16N_WORD(16), 10,      256,		64,	32,5,16,	DS40001836A_B4},
140 {"PIC18F25K42", PIC18F25K42,    DS40001836A,	PIC16N_WORD(32), 10,      256,		64,	32,5,16,	DS40001836A_B4},
141 {"PIC18LF24K42",PIC18LF24K42,   DS40001836A,	PIC16N_WORD(16), 10,      256,		64,	32,5,16,	DS40001836A_B4},
142 {"PIC18LF25K42",PIC18LF25K42,   DS40001836A,	PIC16N_WORD(32), 10,      256,		64,	32,5,16,	DS40001836A_B4},
143 
144 {"PIC18F26K42", PIC18F26K42,    DS40001886B,	PIC16N_WORD(64), 10,      1024,		128,	32,5,16,	DS40001886B_B4},
145 {"PIC18F27K42", PIC18F27K42,    DS40001886B,	PIC16N_WORD(128),10,      1024,		128,	32,5,16,	DS40001886B_B4},
146 {"PIC18F45K42", PIC18F45K42,    DS40001886B,	PIC16N_WORD(32), 10,      256,		128,	32,5,16,	DS40001886B_B4},
147 {"PIC18F46K42", PIC18F46K42,    DS40001886B,	PIC16N_WORD(64), 10,      1024,		128,	32,5,16,	DS40001886B_B4},
148 {"PIC18F47K42", PIC18F47K42,    DS40001886B,	PIC16N_WORD(128),10,      1024,		128,	32,5,16,	DS40001886B_B4},
149 {"PIC18F55K42", PIC18F55K42,    DS40001886B,	PIC16N_WORD(32), 10,      256,		128,	32,5,16,	DS40001886B_B4},
150 {"PIC18F56K42", PIC18F56K42,    DS40001886B,	PIC16N_WORD(64), 10,      1024,		128,	32,5,16,	DS40001886B_B4},
151 {"PIC18F57K42", PIC18F57K42,    DS40001886B,	PIC16N_WORD(128),10,      1024,		128,	32,5,16,	DS40001886B_B4},
152 {"PIC18LF26K42",PIC18LF26K42,   DS40001886B,	PIC16N_WORD(64), 10,      1024,		128,	32,5,16,	DS40001886B_B4},
153 {"PIC18LF27K42",PIC18LF27K42,   DS40001886B,	PIC16N_WORD(128),10,      1024,		128,	32,5,16,	DS40001886B_B4},
154 {"PIC18LF45K42",PIC18LF45K42,   DS40001886B,	PIC16N_WORD(32), 10,      256,		128,	32,5,16,	DS40001886B_B4},
155 {"PIC18LF46K42",PIC18LF46K42,   DS40001886B,	PIC16N_WORD(64), 10,      1024,		128,	32,5,16,	DS40001886B_B4},
156 {"PIC18LF47K42",PIC18LF47K42,   DS40001886B,	PIC16N_WORD(128),10,      1024,		128,	32,5,16,	DS40001886B_B4},
157 {"PIC18LF55K42",PIC18LF55K42,   DS40001886B,	PIC16N_WORD(32), 10,      256,		128,	32,5,16,	DS40001886B_B4},
158 {"PIC18LF56K42",PIC18LF56K42,   DS40001886B,	PIC16N_WORD(64), 10,      1024,		128,	32,5,16,	DS40001886B_B4},
159 {"PIC18LF57K42",PIC18LF57K42,   DS40001886B,	PIC16N_WORD(128),10,      1024,		128,	32,5,16,	DS40001886B_B4},
160 
161 {"PIC18F25K83", PIC18F25K83,    DS40001927A,	PIC16N_WORD(32), 10,      1024,		128,	32,5,16,	DS40001927A_B4},
162 {"PIC18F26K83", PIC18F26K83,    DS40001927A,	PIC16N_WORD(64), 10,      1024,		128,	32,5,16,	DS40001927A_B4},
163 {"PIC18LF25K83",PIC18LF25K83,   DS40001927A,	PIC16N_WORD(32), 10,      1024,		128,	32,5,16,	DS40001927A_B4},
164 {"PIC18LF26K83",PIC18LF26K83,   DS40001927A,	PIC16N_WORD(64), 10,      1024,		128,	32,5,16,	DS40001927A_B4},
165 
166 {"PIC18F46Q10",	PIC18F46Q10,    DS40001874F,	PIC16N_WORD(64), 12,      1024,		2,	0,0,256,	DS40001874F_B1},
167 {"PIC18F45Q10",	PIC18F45Q10,    DS40001874F,	PIC16N_WORD(32), 12,      256,		2,	0,0,256,	DS40001874F_B1},
168 {"PIC18F26Q10",	PIC18F26Q10,    DS40001874F,	PIC16N_WORD(64), 12,      1024,		2,	0,0,256,	DS40001874F_B1},
169 {"PIC18F25Q10",	PIC18F25Q10,    DS40001874F,	PIC16N_WORD(32), 12,      256,		2,	0,0,256,	DS40001874F_B1},
170 {"PIC18F24Q10",	PIC18F24Q10,    DS40001874F,	PIC16N_WORD(16), 12,      256,		2,	0,0,256,	DS40001874F_B1},
171 {"PIC18F27Q10",	PIC18F27Q10,    DS40001874F,	PIC16N_WORD(128),12,      1024,		2,	0,0,256,	DS40001874F_B1},
172 {"PIC18F47Q10",	PIC18F47Q10,    DS40001874F,	PIC16N_WORD(128),12,      1024,		2,	0,0,256,	DS40001874F_B1},
173 
174 {"(null)",      0,              0,              0,               0,       0,		0,	0,0,0,		0},
175 /*Device name	Device id	Data-sheet	Flash		 Config   EEProm	Latches Inf/Con/Id	MASKS*/
176 };
177 #define PIC16N_SIZE ((sizeof(pic16n_map) / sizeof(struct pic16n_dsmap)) - 1)
178 
179 /* Default device (null) */
180 uint32_t pic16n_index = PIC16N_SIZE;
181 
182 void
pic16n_selector(void)183 pic16n_selector(void)
184 {
185 	uint32_t i;
186 	char *dnames[PIC16N_SIZE];
187 
188 	for (i = 0; i < PIC16N_SIZE; ++i) {
189 		dnames[i] = pic16n_map[i].devicename;
190 	}
191 	qsort(dnames, PIC16N_SIZE, sizeof(char *), pic_cmp);
192 	for (i = 0; i < PIC16N_SIZE; ++i) {
193 		if ((i % PIC_NCOLS) == (PIC_NCOLS - 1))
194 			printf("%s\n", dnames[i]);
195 		else
196 			printf("%s\t", dnames[i]);
197 	}
198 	if (i % PIC_NCOLS)
199 		printf("\n");
200 	printf("Total: %u\n", (uint32_t)PIC16N_SIZE);
201 }
202 
203 #ifdef LOADER
204 void
pic16n_bootloader(void)205 pic16n_bootloader(void)
206 {
207 	uint32_t dev, i;
208 	char s[BUFLEN];
209 
210 	for (dev = 0; pic16n_map[dev].deviceid; ++dev) {
211 		if (pic16n_map[dev].datasheet == DS40001874F)
212 			continue;
213 
214 		for (i = 0; pic16n_map[dev].devicename[i] && i < BUFLEN; ++i)
215 			s[i] = tolower(pic16n_map[dev].devicename[i]);
216 		s[i] = 0;
217 		printf("#IFDEF __%s\n", &pic16n_map[dev].devicename[3]);
218 		printf("    LIST        P=%s\n", pic16n_map[dev].devicename);
219 		printf("    #INCLUDE    \"p%s.inc\"\n", &s[3]);
220 		printf("    NOLIST\n");
221 		printf("    #DEFINE     ERASE_FLASH 0x94\n");
222 		printf("    #DEFINE     WRITE_FLASH 0x84\n");
223 		printf("    #DEFINE     MAX_FLASH   0x%X\n",
224 			pic16n_map[dev].flash << 1);
225 		if (pic16n_map[dev].eeprom)
226 		printf("    #DEFINE     MAX_EE      %d ; X 64\n",
227 			pic16n_map[dev].eeprom / 64);
228 		printf("    #DEFINE     ROWSIZE     %d\n",
229 			pic16n_map[dev].latches);
230 		printf("    #DEFINE     ERASESIZE   %d\n",
231 			pic16n_map[dev].latches);
232 		printf("    #DEFINE     TYPE        2\n");
233 		printf("#ENDIF\n");
234 	}
235 }
236 #endif
237 
238 /*****************************************************************************
239  *
240  * Program/Verify mode
241  *
242  *****************************************************************************/
243 
244 /*
245  * ENTER HVP/LVP PROGRAM/VERIFY MODE
246  *
247  * ENTRY - VDD FIRST
248  */
249 void
pic16n_program_verify(void)250 pic16n_program_verify(void)
251 {
252 	/* RESET & ACQUIRE GPIO */
253 	io_set_vpp(LOW);
254 	/* DS40001753B TENTS(100ns) */
255 	io_usleep(1000);
256 
257 	/* PGD + PGC + PGM(N/A) LOW */
258 	io_set_pgd(LOW);
259 	io_set_pgc(LOW);
260 	io_set_pgm(LOW);
261 	io_usleep(1000);
262 
263 	/* INPUT DATA ON CLOCK RISING EDGE, MSB FIRST */
264 	io_configure(FALSE, TRUE);
265 
266 	/* LVP */
267 	if (p.key == LVPKEY) {
268 		/* VPP HIGH */
269 		io_set_vpp(HIGH);
270 		/* TENTH(250ns) */
271 		io_usleep(250);
272 
273 		/* VPP LOW */
274 		io_set_vpp(LOW);
275 		/* TENTH(250ns) */
276 		io_usleep(250);
277 
278 		/* PROGRAM/VERIFY ENTRY CODE */
279 		io_program_out(MCHPKEY, 32);
280 		/* UNSPECIFIED */
281 		io_usleep(250);
282 	}
283 	/* HVP */
284 	else {
285 		/* VPP HIGH */
286 		io_set_vpp(HIGH);
287 		/* DS40001753B TENTS(100ns) */
288 		io_usleep(250);
289 	}
290 }
291 
292 /*
293  * EXIT HVP/LVP PROGRAM/VERIFY MODE
294  *
295  * EXIT - VDD LAST
296  */
297 void
pic16n_standby(void)298 pic16n_standby(void)
299 {
300 	/* PGD + PGC + VPP + PGM(N/A) LOW */
301 	io_set_pgd(LOW);
302 	io_set_pgc(LOW);
303 	io_set_vpp(LOW);
304 	io_set_pgm(LOW);
305 }
306 
307 /*****************************************************************************
308  *
309  * Hardware functions
310  *
311  *****************************************************************************/
312 
313 /*I/O*************************************************************************/
314 
315 /*
316  * LOAD DATA FOR NVM
317  *  0x00 PC = PC
318  *  0x02 PC = PC + 2 CODE
319  *  0x02 PC = PC + 1 DATA
320  *
321  * DS40001772B-page 12
322  */
323 static inline void
pic16n_load_data_for_nvm(uint32_t word,uint8_t j)324 pic16n_load_data_for_nvm(uint32_t word, uint8_t j /* 0 || 1 */)
325 {
326 	io_program_out(j << 1, 8);
327 	/* TDLY 1us */
328 	io_program_out(word << 1, 24);
329 	/* TDLY 1us */
330 }
331 
332 /*
333  * READ DATA FROM NVM
334  *  0xFC PC = PC
335  *  0xFE PC = PC + 2 CODE
336  *  0xFE PC = PC + 1 DATA
337  *
338  * DS40001772B-page 10
339  */
340 static inline uint32_t
pic16n_read_data_from_nvm(uint8_t j)341 pic16n_read_data_from_nvm(uint8_t j /* 0 || 1 */)
342 {
343 	uint32_t word;
344 
345 	io_program_out(0xFC | (j << 1), 8);
346 	/* TDLY 1us */
347 	word = io_program_in(24);
348 	/* TDLY 1us */
349 
350 	word = (word >> 1) & PIC16N_WORD_MASK;
351 
352 	return word;
353 }
354 
355 /*
356  * INCREMENT ADDRESS
357  *  0xF8 PC = PC + 2 CODE
358  *  0xF8 PC = PC + 1 DATA
359  *
360  * DS40001772B-page 10
361  */
362 static inline void
pic16n_increment_address(void)363 pic16n_increment_address(void)
364 {
365 	io_program_out(0xF8, 8);
366 	/* TDLY 1us */
367 }
368 
369 /*
370  * LOAD PC ADDRESS
371  *  0x80 PC = address
372  *
373  * DS40001772B-page 10
374  * DS40001874F-page 10
375  */
376 static inline void
pic16n_load_pc_address(uint32_t address)377 pic16n_load_pc_address(uint32_t address)
378 {
379 	io_program_out(0x80, 8);
380 	/* TDLY 1us */
381 	io_program_out(address << 1, 24);
382 	/* TDLY 1us */
383 }
384 
385 /*PROG************************************************************************/
386 
387 /*
388  * BEGIN INTERNALLY TIMED PROGRAMMING
389  *  0xE0
390  *
391  * DS40001772B-page 12
392  *
393  * DS40001772B TPINT(2.8ms PROGRAM) TPINT(5.6ms CONFIG/EEPROM)
394  */
395 static inline void
pic16n_begin_internally_timed_programming(uint32_t t)396 pic16n_begin_internally_timed_programming(uint32_t t)
397 {
398 	io_program_out(0xE0, 8);
399 	/* TPINT */
400 	io_usleep(t);
401 }
402 
403 /*
404  * BEGIN EXTERNALLY TIMED PROGRAMMING
405  *  0xC0
406  *
407  * DS40001772B-page 12
408  *
409  * DS40001772B TPEXT(2.1ms PROGRAM) (NOT CONFIG)
410  */
411 static inline void
pic16n_begin_externally_timed_programming(uint32_t t)412 pic16n_begin_externally_timed_programming(uint32_t t)
413 {
414 	io_program_out(0xC0, 8);
415 	/* TPEXT */
416 	io_usleep(t);
417 }
418 
419 /*
420  * END EXTERNALLY TIMED PROGRAMMING
421  *  0x82
422  *
423  * DS40001772B-page 12
424  *
425  * DS40001772B TDIS(300us PROGRAM)
426  */
427 static inline void
pic16n_end_externally_timed_programming(uint32_t t)428 pic16n_end_externally_timed_programming(uint32_t t)
429 {
430 	io_program_out(0x82, 8);
431 	/* TDIS */
432 	io_usleep(t);
433 }
434 
435 /*
436  * PROGRAM DATA COMMAND
437  *  0xC0 PC = PC
438  *  0xE0 PC = PC + 2
439  *
440  * DS40001874F-page 12
441  *
442  * DS40001874F TPINT(65us PROGRAM & CONFIG) TPDFM (11ms EEPROM)
443  */
444 static inline void
pic16n_program_data_command(uint16_t word,uint8_t j,uint32_t t)445 pic16n_program_data_command(uint16_t word, uint8_t j /* 0 || 1 */, uint32_t t)
446 {
447 	io_program_out(j ? 0xE0 : 0xC0, 8);
448 	/* TDLY 1us */
449 	io_program_out(word << 1, 24);
450 	/* TPINT or TPDFM */
451 	io_usleep(t);
452 }
453 
454 /*ERASE***********************************************************************/
455 
456 /*
457  * BULK ERASE MEMORY (PRELOAD PC)
458  *  0x18
459  *
460  * PC = 0x000000 ERASE PROGRAM AND CONFIG
461  * PC = 0x300000 ERASE PROGRAM AND CONFIG AND USERID
462  * PC = 0x310000 ERASE EEPROM
463  *
464  * DS40001772B-page 12
465  * DS40001874F-page 10
466  *
467  * DS40001772B TERAB(25.2ms PIC18F26K40)
468  */
469 static inline void
pic16n_bulk_erase_memory(uint32_t t)470 pic16n_bulk_erase_memory(uint32_t t)
471 {
472 	io_program_out(0x18, 8);
473 	io_usleep(t);
474 }
475 
476 /*
477  * ROW ERASE MEMORY (PRELOAD PC)
478  *  0xF0
479  *
480  * DS40001772B-page 12
481  *
482  * DS40001772B TERAR(2.8ms)
483  */
484 static inline void
pic16n_row_erase_memory(uint32_t t)485 pic16n_row_erase_memory(uint32_t t)
486 {
487 	io_program_out(0xF0, 8);
488 	io_usleep(t);
489 }
490 
491 /*****************************************************************************
492  *
493  * Compound functions
494  *
495  *****************************************************************************/
496 
497 void
pic16n_bulk_erase(void)498 pic16n_bulk_erase(void)
499 {
500 	uint32_t t = (pic16n_map[pic16n_index].datasheet == DS40001874F)
501 		? PIC16N_TERAB_Q : PIC16N_TERAB;
502 
503 	pic16n_program_verify();
504 
505 	pic16n_load_pc_address(PIC16N_USERID_ADDR);
506 	pic16n_bulk_erase_memory(t);
507 
508 	if (pic16n_map[pic16n_index].eeprom) {
509 		pic16n_load_pc_address(PIC16N_EEPROM_ADDR);
510 		pic16n_bulk_erase_memory(t);
511 	}
512 
513 	pic16n_standby();
514 }
515 
516 #if 0
517 void
518 pic16n_row_erase(uint32_t row, uint32_t nrows)
519 {
520 	fprintf(stderr, "%s()\n", __func__);
521 }
522 #endif
523 
524 /*****************************************************************************
525  *
526  * Read block data
527  *
528  *****************************************************************************/
529 
530 /*
531  * READ CONFIGURATION MEMORY AND STORE DEVICE MAP INDEX
532  */
533 int
pic16n_read_config_memory(void)534 pic16n_read_config_memory(void)
535 {
536 	uint32_t dev;
537 	uint16_t word;
538 
539 	/* NULL device */
540 	pic16n_index = PIC16N_SIZE;
541 
542 	/* Reset configuraton */
543 	memset(&pic16n_conf, 0, sizeof(pic16n_conf));
544 
545 	pic16n_program_verify();
546 	pic16n_load_pc_address(PIC16N_REVID_ADDR);
547 
548 	pic16n_conf.revisionid = pic16n_read_data_from_nvm(1);	/* Revisionid */
549 	pic16n_conf.deviceid = pic16n_read_data_from_nvm(1);	/* Deviceid   */
550 
551 	/* Device detect */
552 	for (dev = 0; pic16n_map[dev].deviceid; ++dev) {
553 		if (pic16n_map[dev].deviceid == pic16n_conf.deviceid) {
554 			break;
555 		}
556 	}
557 	if (pic16n_map[dev].deviceid == 0) {
558 		/*
559 		 * VELLEMAN K8048 SWITCH IN STANDBY [0000]
560 		 * VELLEMAN K8048 NO POWER          [3FFF]
561 		 * VELLEMAN K0848 SWITCH IN RUN     [3FFF]
562 		 * VELLEMAN K0848 SWITCH IN PROG    [XXXX]
563 		 */
564 		if (pic16n_conf.deviceid == 0x0000 || pic16n_conf.deviceid == 0x3FFF) {
565 			printf("%s: information: %s\n",
566 				__func__, io_fault(pic16n_conf.deviceid));
567 		} else {
568 			printf("%s: information: device unknown: [%04X]\n",
569 				__func__, pic16n_conf.deviceid);
570 		}
571 		pic16n_standby();
572 		return -1;
573 	}
574 
575 	/* Device recognised */
576 	pic16n_index = dev;
577 
578 	/*
579 	 * USER ID and CONFIG words are mapped to bytes because PIC18 HEX uses byte addressing.
580 	 */
581 
582 	/* User ID */
583 	pic16n_load_pc_address(PIC16N_USERID_ADDR);
584 	for (uint32_t i = 0; i < pic16n_map[pic16n_index].idsize; i += 2) {
585 		word = pic16n_read_data_from_nvm(1);
586 		pic16n_conf.userid[i] = word;
587 		pic16n_conf.userid[i + 1] = word >> 8;
588 	}
589 
590 	/* Config word(s) */
591 	pic16n_load_pc_address(PIC16N_CONFIG_ADDR);
592 	for (uint32_t i = 0; i < pic16n_map[pic16n_index].config; i += 2) {
593 		word = pic16n_read_data_from_nvm(1);
594 		pic16n_conf.config[i] = word;
595 		pic16n_conf.config[i + 1] = word >> 8;
596 		if (pic16n_map[pic16n_index].masks && (p.config & CONFIGAND)) {
597 			pic16n_conf.config[i] &= pic16n_map[pic16n_index].masks[i];
598 			pic16n_conf.config[i + 1] &= pic16n_map[pic16n_index].masks[i + 1];
599 		}
600 	}
601 
602 	/* Device information area */
603 	if (pic16n_map[pic16n_index].devinfo) {
604 		pic16n_load_pc_address(PIC16N_DEVINFO_ADDR);
605 		for (uint32_t i = 0; i < pic16n_map[pic16n_index].devinfo && i < PIC16N_DEVINFO_MAX; ++i)
606 			pic16n_conf.devinfo[i] = pic16n_read_data_from_nvm(1);
607 	}
608 
609 	/* Device configuration information */
610 	if (pic16n_map[pic16n_index].devconf) {
611 		pic16n_load_pc_address(PIC16N_DEVCONF_ADDR);
612 		for (uint32_t i = 0; i < pic16n_map[pic16n_index].devconf && i < PIC16N_DEVCONF_MAX; ++i)
613 			pic16n_conf.devconf[i] = pic16n_read_data_from_nvm(1);
614 	}
615 
616 	pic16n_standby();
617 
618 	return 0;
619 }
620 
621 /*
622  * GET PROGRAM COUNT
623  *
624  *  RETURN NUMBER OF PARTITIONS
625  */
626 uint32_t
pic16n_get_program_count(void)627 pic16n_get_program_count(void)
628 {
629 	return 1;
630 }
631 
632 /*
633  * GET PROGRAM FLASH SIZE
634  *
635  *  RETURN SIZE IN WORDS
636  */
637 uint32_t
pic16n_get_program_size(uint32_t * addr,uint32_t partition)638 pic16n_get_program_size(uint32_t *addr, uint32_t partition)
639 {
640 	*addr = 0;
641 
642 	return pic16n_map[pic16n_index].flash;
643 }
644 
645 /*
646  * GET DATA EEPROM/FLASH SIZE
647  *
648  *  RETURN SIZE IN BYTES
649  */
650 uint32_t
pic16n_get_data_size(uint32_t * addr)651 pic16n_get_data_size(uint32_t *addr)
652 {
653 	*addr = PIC16N_EEPROM_ADDR;
654 
655 	return pic16n_map[pic16n_index].eeprom;
656 }
657 
658 /*
659  * REWRITE EEPROM/FLASH ADDRESS
660  */
661 #if 0
662 static inline uint32_t
663 pic16n_get_data_addr(uint32_t addr)
664 {
665 	if (addr >= PIC16N_EEFAKE_ADDR)
666 		addr = addr - PIC16N_EEFAKE_ADDR + PIC16N_EEPROM_ADDR;
667 
668 	return addr;
669 }
670 #endif
671 
672 /*
673  * READ PROGRAM FLASH MEMORY BLOCK ADDR .. ADDR + SIZE
674  *
675  *  RETURN ADDR
676  */
677 uint32_t
pic16n_read_program_memory_block(uint32_t * data,uint32_t addr,uint32_t size)678 pic16n_read_program_memory_block(uint32_t *data, uint32_t addr, uint32_t size)
679 {
680 	uint32_t i;
681 
682 	pic16n_program_verify();
683 	pic16n_load_pc_address(addr);
684 
685 	for (i = 0; i < size; ++i)
686 		data[i] = (uint32_t)pic16n_read_data_from_nvm(1);
687 
688 	pic16n_standby();
689 
690 	return addr;
691 }
692 
693 /*
694  * READ DATA EEPROM BLOCK ADDR .. ADDR + SIZE
695  *
696  *  RETURN ADDR
697  */
698 uint32_t
pic16n_read_data_memory_block(uint16_t * data,uint32_t addr,uint16_t size)699 pic16n_read_data_memory_block(uint16_t *data, uint32_t addr, uint16_t size)
700 {
701 	uint32_t i;
702 
703 	pic16n_program_verify();
704 	pic16n_load_pc_address(addr);
705 
706 	for (i = 0; i < size; i++)
707 		data[i] = (uint16_t)pic16n_read_data_from_nvm(1);
708 
709 	pic16n_standby();
710 
711 	return addr;
712 }
713 
714 /*****************************************************************************
715  *
716  * Program Code Panel
717  *
718  *****************************************************************************/
719 
720 /*
721  * WRITE PANEL
722  */
723 void
pic16n_write_panel(uint32_t region,uint32_t address,uint32_t * panel,uint32_t panel_size)724 pic16n_write_panel(uint32_t region, uint32_t address, uint32_t *panel, uint32_t panel_size)
725 {
726 	uint16_t word;
727 
728 	if (panel_size == 2) { /* DS40001874F */
729 		word = panel[0] | panel[1] << 8;
730 		pic16n_load_pc_address(address);
731 		pic16n_program_data_command(word, 0, PIC16N_TPINT_Q);
732 	} else {
733 		for (uint32_t i = 0; i < panel_size; i += 2) {
734 			word = panel[i] | panel[i + 1] << 8;
735 			pic16n_load_data_for_nvm(word, 1);
736 		}
737 		pic16n_load_pc_address(address);
738 		pic16n_begin_internally_timed_programming(PIC16N_TPINT_CODE);
739 	}
740 }
741 
742 /*****************************************************************************
743  *
744  * Program Data/EEPROM
745  *
746  *****************************************************************************/
747 
748 /*
749  * WRITE Data/EEPROM WORD
750  */
751 static inline
752 void
pic16n_write_data_memory(uint32_t address,uint16_t word)753 pic16n_write_data_memory(uint32_t address, uint16_t word)
754 {
755 	pic16n_load_pc_address(address);
756 
757 	if (pic16n_map[pic16n_index].datasheet == DS40001874F) {
758 		pic16n_program_data_command(word, 0, PIC16N_TPDFM_Q);
759 	} else {
760 		pic16n_load_data_for_nvm(word, 0);
761 		pic16n_begin_internally_timed_programming(PIC16N_TPINT_CONFIG);
762 	}
763 }
764 
765 /*****************************************************************************
766  *
767  * Program UserID/Config
768  *
769  *****************************************************************************/
770 
771 /*
772  * WRITE USERID/CONFIG WORD
773  *
774  *  RETURN WORD
775  */
776 static inline uint16_t
pic16n_write_config_word(uint16_t word)777 pic16n_write_config_word(uint16_t word)
778 {
779 	if (pic16n_map[pic16n_index].datasheet == DS40001874F) {
780 		pic16n_program_data_command(word, 0, PIC16N_TPINT_Q);
781 	} else {
782 		pic16n_load_data_for_nvm(word, 0);
783 		pic16n_begin_internally_timed_programming(PIC16N_TPINT_CONFIG);
784 	}
785 
786 	return pic16n_read_data_from_nvm(1);
787 }
788 
789 /*
790  * WRITE CONFIG
791  *
792  *  RETURN 0 ON ERROR ELSE PROGRAM COUNT
793  */
794 uint32_t
pic16n_write_config(void)795 pic16n_write_config(void)
796 {
797 	uint16_t wdata, vdata;
798 
799 	pic16n_program_verify();
800 
801 	pic16n_load_pc_address(PIC16N_USERID_ADDR);
802 	for (uint32_t i = 0; i < pic16n_map[pic16n_index].idsize; i += 2) {
803 		wdata = pic16n_conf.userid[i] | pic16n_conf.userid[i + 1] << 8;
804 		vdata = pic16n_write_config_word(wdata);
805 		if (vdata != wdata) {
806 			printf("%s: error: USERID%d write failed: read [%04X] expected [%04X]\n",
807 				__func__, i, vdata, wdata);
808 			pic16n_standby();
809 			return 0;
810 		}
811 	}
812 
813 	pic16n_load_pc_address(PIC16N_CONFIG_ADDR);
814 	for (uint32_t i = 0; i < pic16n_map[pic16n_index].config; i += 2) {
815 		wdata = pic16n_conf.config[i] | pic16n_conf.config[i + 1] << 8;
816 		if (pic16n_map[pic16n_index].masks && (p.config & CONFIGSET))
817 			wdata |= ~(pic16n_map[pic16n_index].masks[i] |
818 				pic16n_map[pic16n_index].masks[i + 1] << 8);
819 		vdata = pic16n_write_config_word(wdata);
820 		if (pic16n_map[pic16n_index].masks && (p.config & CONFIGVER)) {
821 			uint16_t mask = pic16n_map[pic16n_index].masks[i] |
822 				pic16n_map[pic16n_index].masks[i + 1] << 8;
823 			wdata &= mask;
824 			vdata &= mask;
825 		}
826 		if (vdata != wdata) {
827 			printf("%s: error: CONFIG%d write failed: read [%04X] expected [%04X]\n",
828 				__func__, i + 1, vdata, wdata);
829 			pic16n_standby();
830 			return 0;
831 		}
832 	}
833 
834 	pic16n_standby();
835 
836 	return pic16n_map[pic16n_index].idsize + pic16n_map[pic16n_index].config;
837 }
838 
839 /*****************************************************************************
840  *
841  * Programming
842  *
843  *****************************************************************************/
844 
845 /*
846  * DETERMINE MEMORY REGION: CODE, ID, CONFIG or DATA
847  *
848  *  RETURN PIC_REGIONCODE:
849  *      0 .. FLASH SIZE - 1
850  *
851  *  RETURN PIC_REGIONID:
852  *      0x200000 .. 0x200007
853  *
854  *  RETURN PIC_REGIONCONFIG:
855  *      0x300000 .. 0x30000B
856  *
857  *  RETURN PIC_REGIONDATA:
858  *      0x310000 .. 0x31XXXX
859  */
860 uint16_t
pic16n_getregion(uint32_t address)861 pic16n_getregion(uint32_t address)
862 {
863 	/* CODE */
864 	if (address < (pic16n_map[pic16n_index].flash << 1)) {
865 		return PIC_REGIONCODE;
866 	}
867 	/* ID */
868 	if (address >= PIC16N_USERID_ADDR && address < (PIC16N_USERID_ADDR +
869 		pic16n_map[pic16n_index].idsize)) {
870 		return PIC_REGIONID;
871 	}
872 	/* CONFIG */
873 	if (address >= PIC16N_CONFIG_ADDR && address < (PIC16N_CONFIG_ADDR +
874 		pic16n_map[pic16n_index].config)) {
875 		return PIC_REGIONCONFIG;
876 	}
877 	/* DATA EEPROM */
878 	if (pic16n_map[pic16n_index].eeprom) {
879 		if (address >= PIC16N_EEPROM_ADDR && address < (PIC16N_EEPROM_ADDR +
880 			pic16n_map[pic16n_index].eeprom))
881 			return PIC_REGIONDATA;
882 	}
883 	if (p.f) fprintf(p.f, "%s: warning: address unsupported [%04X]\n",
884 		__func__, address);
885 	return PIC_REGIONNOTSUP;
886 }
887 
888 /*
889  * INIT REGION FOR WRITING (ID & CONFIG DELAYED)
890  *
891  *  RETURN REGION IF WRITING SUPPORTED
892  */
893 static inline uint32_t
pic16n_init_writeregion(uint32_t region)894 pic16n_init_writeregion(uint32_t region)
895 {
896 	switch (region) {
897 	case PIC_REGIONCODE:
898 		pic16n_load_pc_address(0); /* Reset latch address */
899 		pic_write_panel(PIC_PANEL_BEGIN, region, pic16n_map[pic16n_index].latches);
900 		/* Follow through */
901 	case PIC_REGIONID:
902 	case PIC_REGIONCONFIG:
903 	case PIC_REGIONDATA:
904 		return region;
905 	}
906 	if (p.f) fprintf(p.f, "%s: warning: region unsupported [%d]\n",
907 		__func__, region);
908 	return PIC_REGIONNOTSUP;
909 }
910 
911 /*
912  * WRITE REGION (CACHE ID & CONFIG)
913  */
914 static inline void
pic16n_writeregion(uint32_t address,uint32_t region,uint16_t data)915 pic16n_writeregion(uint32_t address, uint32_t region, uint16_t data)
916 {
917 	switch (region) {
918 	case PIC_REGIONCODE:
919 		pic_write_panel(PIC_PANEL_UPDATE, address, data);
920 		return;
921 	case PIC_REGIONID:
922 		pic16n_conf.userid[address - PIC16N_USERID_ADDR] = data;
923 		return;
924 	case PIC_REGIONCONFIG:
925 		pic16n_conf.config[address - PIC16N_CONFIG_ADDR] = data;
926 		return;
927 	case PIC_REGIONDATA:
928 		pic16n_write_data_memory(address, data);
929 		return;
930 	}
931 }
932 
933 /*
934  * INIT REGION FOR VERIFY
935  *
936  *  RETURN REGION IF VERIFY SUPPORTED
937  */
938 static inline uint32_t
pic16n_init_verifyregion(uint32_t region)939 pic16n_init_verifyregion(uint32_t region)
940 {
941 	if (region == PIC_REGIONNOTSUP) {
942 		if (p.f) fprintf(p.f, "%s: warning: region unsupported [%d]\n",
943 			__func__, region);
944 	}
945 
946 	return region;
947 }
948 
949 /*
950  * GET VERIFY DATA FOR REGION
951  */
952 static uint16_t
pic16n_verifyregion(uint32_t address,uint32_t region,uint16_t index,uint8_t mode)953 pic16n_verifyregion(uint32_t address, uint32_t region, uint16_t index, uint8_t mode)
954 {
955 	if (index == 0)
956 		pic16n_load_pc_address(address);
957 
958 	if (mode == 0)
959 		return pic16n_read_data_from_nvm(1) & 0xFF;		/* EEPROM BYTE */
960 
961 	if (mode == 1) {						/* CODE/USERID/CONFIG BYTE */
962 		if (address & 1)
963 			return pic16n_read_data_from_nvm(1) >> 8;	/* HIGH BYTE */
964 		else
965 			return pic16n_read_data_from_nvm(1) & 0xFF;	/* LOW  BYTE */
966 	}
967 	return pic16n_read_data_from_nvm(1);				/* CODE/USERID/CONFIG WORD */
968 }
969 
970 /*****************************************************************************
971  *
972  * Program & verify
973  *
974  *****************************************************************************/
975 
976 /*
977  * BEGIN PROGRAMMING
978  */
979 void
pic16n_program_begin(void)980 pic16n_program_begin(void)
981 {
982 	pic16n_program_verify();
983 
984 	memset(pic16n_conf.userid, -1, sizeof(uint8_t) * pic16n_map[pic16n_index].idsize);
985 	memset(pic16n_conf.config, -1, sizeof(uint8_t) * PIC16N_CONFIG_MAX);
986 }
987 
988 /*
989  * PROGRAM DATA
990  */
991 uint32_t
pic16n_program_data(uint32_t current_region,pic_data * pdata)992 pic16n_program_data(uint32_t current_region, pic_data *pdata)
993 {
994 	uint32_t address, new_region;
995 
996 	for (uint32_t i = 0; i < pdata->nbytes; ++i) {
997 		address = pdata->address + i;
998 		new_region = pic16n_getregion(address);
999 		if (new_region != current_region) {
1000 			pic_write_panel(PIC_PANEL_END, PIC_VOID, PIC_VOID);
1001 			current_region = pic16n_init_writeregion(new_region);
1002 		}
1003 		if (current_region == PIC_REGIONNOTSUP)
1004 			continue;
1005 		pic16n_writeregion(address, current_region, pdata->bytes[i]);
1006 	}
1007 	return current_region;
1008 }
1009 
1010 /*
1011  * END PROGRAMMING
1012  */
1013 void
pic16n_program_end(int config)1014 pic16n_program_end(int config)
1015 {
1016 	pic_write_panel(PIC_PANEL_END, PIC_VOID, PIC_VOID);
1017 	pic16n_standby();
1018 	if (config)
1019 		pic16n_write_config();
1020 }
1021 
1022 /*
1023  * VERIFY DATA
1024  */
1025 uint32_t
pic16n_verify_data(uint32_t current_region,pic_data * pdata,uint32_t * fail)1026 pic16n_verify_data(uint32_t current_region, pic_data *pdata, uint32_t *fail)
1027 {
1028 	uint32_t address, new_region;
1029 	uint16_t wdata, vdata;
1030 
1031 	for (uint32_t i = 0; i < pdata->nbytes;) {
1032 		address = pdata->address + i;
1033 		new_region = pic16n_getregion(address);
1034 		if (new_region != current_region)
1035 			current_region = pic16n_init_verifyregion(new_region);
1036 		if (current_region == PIC_REGIONNOTSUP) {
1037 			i += 1;
1038 		}
1039 		else if (current_region == PIC_REGIONDATA) {
1040 			wdata = pdata->bytes[i];
1041 			vdata = pic16n_verifyregion(address, current_region, i, 0);
1042 			if (vdata != wdata) {
1043 				if (p.f) printf("%s: error: read [%02X] expected [%02X] at [%06X]\n",
1044 					__func__, vdata, wdata, address);
1045 				pdata->bytes[i] = vdata;
1046 				(*fail) += 1;
1047 			}
1048 			i += 1;
1049 		}
1050 		else if ((pdata->nbytes - i) == 1) {	/* BYTE */
1051 			wdata = pdata->bytes[i];
1052 			vdata = pic16n_verifyregion(address, current_region, i, 1);
1053 			if (current_region == PIC_REGIONCONFIG) {
1054 				if (pic16n_map[pic16n_index].masks && (p.config & CONFIGVER)) {
1055 					uint8_t a = address - PIC16N_CONFIG_ADDR;
1056 					wdata &= pic16n_map[pic16n_index].masks[a];
1057 					vdata &= pic16n_map[pic16n_index].masks[a];
1058 				}
1059 			}
1060 			if (vdata != wdata) {
1061 				if (p.f) printf("%s: error: read [%02X] expected [%02X] at [%06X]\n",
1062 					__func__, vdata, wdata, address);
1063 				pdata->bytes[i] = vdata;
1064 				(*fail) += 1;
1065 			}
1066 			i += 1;
1067 		}
1068 		else {					/* WORD */
1069 			wdata = pdata->bytes[i] | pdata->bytes[i + 1] << 8;
1070 			vdata = pic16n_verifyregion(address, current_region, i, 2);
1071 			if (current_region == PIC_REGIONCONFIG) {
1072 				if (pic16n_map[pic16n_index].masks && (p.config & CONFIGVER)) {
1073 					uint8_t a = address - PIC16N_CONFIG_ADDR;
1074 					if (a < PIC16N_CONFIG_MAX) {
1075 						uint16_t mask = pic16n_map[pic16n_index].masks[a] |
1076 							pic16n_map[pic16n_index].masks[a + 1] << 8;
1077 						wdata &= mask;
1078 						vdata &= mask;
1079 					} else {
1080 						if (p.f) fprintf(p.f, "%s: warning: config address invalid [%06X]\n",
1081 							__func__, address);
1082 					}
1083 				}
1084 			}
1085 			if (vdata != wdata) {
1086 				if (p.f) printf("%s: error: read [%04X] expected [%04X] at [%06X]\n",
1087 					__func__, vdata, wdata, address);
1088 				pdata->bytes[i] = vdata;
1089 				pdata->bytes[i + 1] = vdata >> 8;
1090 				(*fail) += 2;
1091 			}
1092 			i += 2;
1093 		}
1094 	}
1095 	return current_region;
1096 }
1097 
1098 /*
1099  * VIEW DATA
1100  */
1101 void
pic16n_view_data(pic_data * pdata)1102 pic16n_view_data(pic_data *pdata)
1103 {
1104 	printf("[%06X] ", pdata->address);
1105 	for (uint32_t i = 0; i < pdata->nbytes; ++i)
1106 		printf("%02X ", pdata->bytes[i]);
1107 	putchar('\n');
1108 }
1109 
1110 /*****************************************************************************
1111  *
1112  * Diagnostic functions
1113  *
1114  *****************************************************************************/
1115 
1116 /*
1117  * DUMP DEVICE ID DETAILS
1118  */
1119 void
pic16n_dumpdeviceid(void)1120 pic16n_dumpdeviceid(void)
1121 {
1122 	uint32_t i, j;
1123 	uint16_t word;
1124 
1125 	printf("[000000] [PROGRAM]  %04X WORDS (%04X ROWS OF %04X WORDS)\n",
1126 		pic16n_map[pic16n_index].flash,
1127 		2 * pic16n_map[pic16n_index].flash / pic16n_map[pic16n_index].latches,
1128 		pic16n_map[pic16n_index].latches / 2);
1129 
1130 	if (pic16n_map[pic16n_index].idsize <= 16) {
1131 		for (i = j = 0; i < pic16n_map[pic16n_index].idsize; i += 2, ++j) {
1132 			word = pic16n_conf.userid[i] | pic16n_conf.userid[i + 1] << 8;
1133 			printf("[%06X] [USERID%d]  %04X\n", PIC16N_USERID_ADDR + i, j, word);
1134 		}
1135 	} else for (i = 0; i < pic16n_map[pic16n_index].idsize; i += 16) {
1136 		printf("[%04X] [USERID%02X] ", PIC16N_USERID_ADDR + i, i / 2);
1137 		for (j = 0; j < 16; j += 2) {
1138 			word = pic16n_conf.userid[i + j] | pic16n_conf.userid[i + j + 1] << 8;
1139 			if (j != 14)
1140 				printf("%04X ", word);
1141 			else
1142 				printf("%04X\n", word);
1143 		}
1144 	}
1145 
1146 	pic16n_dumpconfig(PIC_BRIEF, 0);
1147 
1148 	if (pic16n_map[pic16n_index].eeprom) {
1149 		printf("[%06X] [DATA]     %04X BYTES\n",
1150 			PIC16N_EEPROM_ADDR, pic16n_map[pic16n_index].eeprom);
1151 	}
1152 
1153 	/* Device information area */
1154 	if (pic16n_map[pic16n_index].devinfo) {
1155 		for (uint32_t i = 0; i < pic16n_map[pic16n_index].devinfo; i += 8) {
1156 			printf("[%04X] [DEVINF%02X] ", PIC16N_DEVINFO_ADDR + 2 * i, 2 * i);
1157 			uint32_t j;
1158 			for (j = 0; j < 7; ++j)
1159 				printf("%04X ", pic16n_conf.devinfo[i + j]);
1160 			printf("%04X\n", pic16n_conf.devinfo[i + j]);
1161 		}
1162 	}
1163 
1164 	/* Device configuration information */
1165 	if (pic16n_map[pic16n_index].devconf) {
1166 		printf("[%04X] [ERASE]    %04X\n", PIC16N_ERASE, pic16n_conf.devconf[0]);
1167 		printf("[%04X] [LATCHES]  %04X\n", PIC16N_LATCHES, pic16n_conf.devconf[1]);
1168 		printf("[%04X] [ROWS]     %04X\n", PIC16N_ROWS, pic16n_conf.devconf[2]);
1169 		printf("[%04X] [EEPROM]   %04X\n", PIC16N_EEPROM, pic16n_conf.devconf[3]);
1170 		printf("[%04X] [PINS]     %04X\n", PIC16N_PINS, pic16n_conf.devconf[4]);
1171 	}
1172 
1173 	printf("[3FFFFC] [REVISION] %04X MAJ:%02X MIN:%02X\n",
1174 		pic16n_conf.revisionid,
1175 		(pic16n_conf.revisionid >> PIC16N_MAJOR_SHIFT) & PIC16N_REV_MASK,
1176 		pic16n_conf.revisionid & PIC16N_REV_MASK);
1177 	printf("[3FFFFE] [DEVICEID] %04X %s\n", pic16n_conf.deviceid,
1178 		pic16n_map[pic16n_index].devicename);
1179 }
1180 
1181 /*
1182  * DUMP CONFIG WORD DETAILS FOR DEVICE
1183  */
1184 void
pic16n_dumpconfig(uint32_t mode,uint32_t partition)1185 pic16n_dumpconfig(uint32_t mode, uint32_t partition)
1186 {
1187 	for (uint32_t i = 0; i < pic16n_map[pic16n_index].config; i += 2) {
1188 		printf("[%06X] [CONFIG%d]  %04X\n",
1189 			PIC16N_CONFIG_ADDR + i, i / 2 + 1,
1190 			(pic16n_conf.config[i + 1] << 8) | pic16n_conf.config[i]);
1191 	}
1192 #ifdef VERBOSE
1193 	if (mode == PIC_VERBOSE) switch (pic16n_map[pic16n_index].datasheet) {
1194 	default:break;
1195 	}
1196 #endif
1197 }
1198 
1199 /*
1200  * DUMP HEX FLASH WORDS
1201  */
1202 void
pic16n_dumphexcode(uint32_t address,uint32_t size,uint32_t * data)1203 pic16n_dumphexcode(uint32_t address, uint32_t size, uint32_t *data)
1204 {
1205 	uint32_t i, j, nlines = 0;
1206 
1207 	for (i = 0; i < size; address += 16, i += 8) {
1208 		if (pic_mtcode(PIC16N_WORD_MASK, 8, &data[i]))
1209 			continue;
1210 		printf("[%06X] ", address);
1211 		for (j = 0; j < 8; ++j)
1212 			printf("%04X ", data[i + j] & PIC16N_WORD_MASK);
1213 		for (j = 0; j < 8; ++j) {
1214 			putchar(PIC_CHAR(0xFF & data[i + j]));
1215 			putchar(PIC_CHAR(0xFF & (data[i + j] >> 8)));
1216 		}
1217 		putchar('\n');
1218 		nlines++;
1219 	}
1220 	if (!nlines)
1221 		printf("%s: information: flash empty\n", __func__);
1222 }
1223 
1224 /*
1225  * DUMP INHX32 FLASH WORDS
1226  */
1227 void
pic16n_dumpinhxcode(uint32_t address,uint32_t size,uint32_t * data)1228 pic16n_dumpinhxcode(uint32_t address, uint32_t size, uint32_t *data)
1229 {
1230 	uint32_t i, j;
1231 
1232 	/* 16-bit: Extended address */
1233 	pic_dumpaddr(address, 1);
1234 
1235 	for (i = 0; i < size; address += 16, i += 8) {
1236 		if (pic_mtcode(PIC16N_WORD_MASK, 8, &data[i]))
1237 			continue;
1238 		/* 16-bit: Extended address */
1239 		pic_dumpaddr(address, 0);
1240 
1241 		uint8_t cc, hb, lb;
1242 		hb = address >> 8;
1243 		lb = address;
1244 		printf(":%02X%02X%02X00", 16, hb, lb);
1245 		cc = 16 + hb + lb + 0x00;
1246 		for (j = 0; j < 8; ++j) {
1247 			lb = data[i + j];
1248 			hb = data[i + j] >> 8;
1249 			printf("%02X%02X", lb, hb);
1250 			cc = cc + lb + hb;
1251 		}
1252 		printf("%02X\n", (0x0100 - cc) & 0xFF);
1253 	}
1254 }
1255 
1256 /*
1257  * DUMP HEX DATA EEPROM BYTES
1258  */
1259 void
pic16n_dumphexdata(uint32_t address,uint32_t size,uint16_t * data)1260 pic16n_dumphexdata(uint32_t address, uint32_t size, uint16_t *data)
1261 {
1262 	uint32_t i, j, nlines = 0;
1263 
1264 	for (i = 0; i < size; address += 16, i += 16) {
1265 		if (pic_mtdata(0xFF, 16, &data[i]))
1266 			continue;
1267 		printf("[%06X] ", address);
1268 		for (j = 0; j < 16; ++j)
1269 			printf("%02X ", data[i + j]);
1270 		for (j = 0; j < 16; ++j)
1271 			putchar(PIC_CHAR(0xFF & data[i + j]));
1272 		putchar('\n');
1273 		nlines++;
1274 	}
1275 	if (!nlines)
1276 		printf("%s: information: data empty\n", __func__);
1277 }
1278 
1279 /*
1280  * DUMP INHX32 DATA EEPROM BYTES
1281  */
1282 void
pic16n_dumpinhxdata(uint32_t address,uint32_t size,uint16_t * data)1283 pic16n_dumpinhxdata(uint32_t address, uint32_t size, uint16_t *data)
1284 {
1285 	uint32_t i, j;
1286 
1287 	/* PIC18: Extended address = 0x0031 (EEPROM: 0x310000) */
1288 	pic_dumpaddr(PIC16N_EEPROM_ADDR, 1);
1289 
1290 	for (i = 0; i < size; address += 16, i += 16) {
1291 		if (pic_mtdata(0xFF, 16, &data[i]))
1292 			continue;
1293 
1294 		uint8_t cc, hb, lb;
1295 		hb = address >> 8;
1296 		lb = address;
1297 		printf(":%02X%02X%02X00", 16, hb, lb);
1298 		cc = 16 + hb + lb + 0x00;
1299 		for (j = 0; j < 16; ++j) {
1300 			lb = data[i + j];
1301 			printf("%02X", lb);
1302 			cc = cc + lb;
1303 		}
1304 		printf("%02X\n", (0x0100 - cc) & 0xFF);
1305 	}
1306 }
1307 
1308 /*
1309  * DUMP INHX32 DEVICE CONFIGURATION
1310  */
1311 void
pic16n_dumpdevice(void)1312 pic16n_dumpdevice(void)
1313 {
1314 	uint32_t i;
1315 
1316 	/* PIC18: Extended address = 0x0020 (USERID: 0x200000) */
1317 	pic_dumpaddr(PIC16N_USERID_ADDR, 1);
1318 
1319 	for (i = 0; i < pic16n_map[pic16n_index].idsize; i += 2)
1320 		pic_dumpword16(i / 2, pic16n_conf.userid[i] | pic16n_conf.userid[i + 1] << 8);
1321 
1322 	/* PIC18: Extended address = 0x0030 (CONFIG: 0x300000) */
1323 	pic_dumpaddr(PIC16N_CONFIG_ADDR, 1);
1324 
1325 	for (i = 0; i < pic16n_map[pic16n_index].config; i += 2)
1326 		pic_dumpword16(i / 2, pic16n_conf.config[i] | pic16n_conf.config[i + 1] << 8);
1327 }
1328