source: avrstuff/V-USB_Dev/firmwares/herePic/main.c@ 3587f7f

main
Last change on this file since 3587f7f was 3587f7f, checked in by Adrien Destugues <pulkomandy@…>, 12 years ago

Add first version of herePic, an AVR based PIc programmer using ICSP protocol.
Untested, no host software written yet.

git-svn-id: svn://pulkomandy.tk/avrstuff@64 c6672c3c-f6b6-47f9-9001-1fd6b12fecbe

  • Property mode set to 100644
File size: 4.1 KB
Line 
1/* HEREPIC - AVR-based ICSP programmer for microchip PIC16F6xx and 16F8xx devices
2 * Copyright 2012, Adrien Destugues <pulkomandy@pulkomandy.tk>
3 *
4 * This file is distributed under the terms of the MIT licence.
5 */
6
7/* This project is targetted at the VUSBDev hacking board. */
8
9#include <avr/io.h>
10#include <avr/interrupt.h>
11#include <avr/wdt.h>
12#include <avr/pgmspace.h>
13#include <util/delay.h>
14
15#include <string.h>
16#include <stdbool.h>
17
18#include "usbdrv/usbdrv.h"
19
20// IO pins:
21// PIC <> AVR
22// PGC PB3
23// PGD PB2
24// PGM PB1
25// VPP PB0
26// VDD VCC
27// VSS GND
28#define PGC 8
29#define PGD 4
30#define PGM 2
31#define VPP 1
32
33
34// TODO is it wise to use a timer or two for bit patterns generation ? (see
35// CrO2 architecture)
36//
37// As usual the SPI, TWI and USART are not useable, because we need 6 and 16 bit
38// communcations in the ICSP protocol. So we are bit banging bhe ICSP protocol.
39// Timers may make it easier to do that in parallel with the USB handling, since
40// timings are in the nanosecond range.
41
42
43// ICSP commands are 6-bit wide, for most of them (but not all) the 2 MSb are
44// ignored.
45// We also use these as USB commands for now, but we may do otherwise, since
46// transferring only 14 data bytes in an USB frame is quite a bit of waste.
47// We need some custom commands on USB side as well, to reset the PIC and such
48// things.
49typedef enum
50{
51 // HOST to DEVICE
52 LoadConfigWord = 0b0000,
53 LoadCodeWord = 0b0010,
54 LoadDataWord = 0b0011,
55
56 // Configuration
57 NextAddress = 0b0110,
58 BeginEraseProgram = 0b001000,
59 BeginProgramOnly = 0b011000,
60 BulkEraseCode = 0b1001,
61 BulkEraseData = 0b1011,
62 BulkEraseConfig1 = 0b000001,
63 BulkEraseConfig2 = 0b000111,
64
65 // DEVICE to HOST
66 ReadCodeWord = 0b0100,
67 ReadDataWord = 0b0101,
68} ICSPCommands;
69
70
71uint8_t command;
72uint16_t ICSP_data;
73
74
75int main() {
76 // Init
77 wdt_enable(WDTO_2S);
78
79 // USB
80 usbInit();
81 sei();
82
83 // Enter Low Voltage ICSP mode on the PIC
84 PORTB &= ~(VPP|PGM|PGD|PGC); // Start with all pin low
85 DDRB |= VPP|PGM|PGD|PGC; // set them as outputs
86 _delay_us(4); // Wait for some time
87 PORTB |= PGM; // Enable low voltage programming
88 PORTB |= VPP; // Enter programming mode
89
90 while(1) {
91 wdt_reset();
92 usbPoll();
93 }
94}
95
96
97void ICSP_command(uint8_t cmd)
98{
99 for(int i = 6; --i>= 0;)
100 {
101 PORTB |= PGC;
102 if(cmd & 1)
103 PORTB |= PGD;
104 else
105 PORTB &= ~PGD;
106 PORTB &= ~PGC;
107
108 cmd >>= 1;
109 }
110
111 _delay_us(1);
112}
113
114
115void ICSP_write(uint8_t cmd, uint16_t data)
116{
117 ICSP_command(cmd);
118
119 // send data
120 for(int i = 16; --i>= 0;)
121 {
122 PORTB |= PGC;
123 if(data & 1)
124 PORTB |= PGD;
125 else
126 PORTB &= ~PGD;
127 PORTB &= ~PGC;
128
129 data >>= 1;
130 }
131 _delay_us(1);
132}
133
134
135void ICSP_read(uint8_t cmd, uint16_t *const data)
136{
137 ICSP_command(cmd);
138
139 // get data
140 for(int i = 16; --i>= 0;)
141 {
142 PORTB |= PGC;
143 *data |= (PORTB & PGD) / PGD;
144 PORTB &= ~PGC;
145
146 *data <<= 1;
147 }
148 _delay_us(1);
149}
150
151
152uint8_t usbFunctionSetup(uint8_t data[8]) {
153 usbRequest_t *rq = (void *)data;
154
155 switch(rq->bRequest)
156 {
157 /* HOST to DEVICE data transfers requests */
158 case LoadConfigWord:
159 case LoadCodeWord:
160 case LoadDataWord:
161 {
162 // TODO check there is only and exactly 16 bits of data
163
164 /* Read the 16-bit data */
165 ICSP_data = (rq->wValue.bytes[0] << 8) | rq->wValue.bytes[0];
166 command = rq->bRequest;
167
168 // send the command and data
169 ICSP_write(command, ICSP_data);
170
171 // Return the number of bytes we wrote (none here)
172 return 0;
173 }
174
175 /* CONFIGURATION commands (no data is transferred) */
176 case NextAddress:
177 case BeginEraseProgram:
178 case BeginProgramOnly:
179 case BulkEraseCode:
180 case BulkEraseData:
181 case BulkEraseConfig1:
182 case BulkEraseConfig2:
183 {
184 command = rq->bRequest;
185
186 // send the command
187 ICSP_command(command);
188
189 return 0;
190 }
191
192 /* DEVICE to HOST data transfers requests */
193 case ReadCodeWord:
194 case ReadDataWord:
195 {
196 command = rq->bRequest;
197 // TODO send the command and get the result
198 ICSP_read(command, &ICSP_data);
199 usbMsgPtr = (uint8_t*)&ICSP_data;
200
201 return 2; // We send 2 bytes back
202 }
203 }
204 return 0;
205}
206
Note: See TracBrowser for help on using the repository browser.