~ubuntu-branches/debian/experimental/arduino/experimental

« back to all changes in this revision

Viewing changes to build/shared/examples/ArduinoISP/ArduinoISP.pde

  • Committer: Package Import Robot
  • Author(s): Scott Howard
  • Date: 2012-03-11 18:19:42 UTC
  • mfrom: (1.1.5) (5.1.14 sid)
  • Revision ID: package-import@ubuntu.com-20120311181942-be2clnbz1gcehixb
Tags: 1:1.0.1~rc1+dfsg-1
New upstream release, experimental.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// this sketch turns the Arduino into a AVRISP
2
 
// using the following pins:
3
 
// 10: slave reset
4
 
// 11: MOSI
5
 
// 12: MISO
6
 
// 13: SCK
7
 
 
8
 
// Put an LED (with resistor) on the following pins:
9
 
// 9: Heartbeat - shows the programmer is running
10
 
// 8: Error - Lights up if something goes wrong (use red if that makes sense)
11
 
// 7: Programming - In communication with the slave
12
 
//
13
 
// October 2009 by David A. Mellis
14
 
// - Added support for the read signature command
15
 
// 
16
 
// February 2009 by Randall Bohn
17
 
// - Added support for writing to EEPROM (what took so long?)
18
 
// Windows users should consider WinAVR's avrdude instead of the
19
 
// avrdude included with Arduino software.
20
 
//
21
 
// January 2008 by Randall Bohn
22
 
// - Thanks to Amplificar for helping me with the STK500 protocol
23
 
// - The AVRISP/STK500 (mk I) protocol is used in the arduino bootloader
24
 
// - The SPI functions herein were developed for the AVR910_ARD programmer 
25
 
// - More information at http://code.google.com/p/mega-isp
26
 
 
27
 
#include "pins_arduino.h"  // defines SS,MOSI,MISO,SCK
28
 
#define RESET SS
29
 
 
30
 
#define LED_HB 9
31
 
#define LED_ERR 8
32
 
#define LED_PMODE 7
33
 
 
34
 
#define HWVER 2
35
 
#define SWMAJ 1
36
 
#define SWMIN 18
37
 
 
38
 
// STK Definitions
39
 
#define STK_OK 0x10
40
 
#define STK_FAILED 0x11
41
 
#define STK_UNKNOWN 0x12
42
 
#define STK_INSYNC 0x14
43
 
#define STK_NOSYNC 0x15
44
 
#define CRC_EOP 0x20 //ok it is a space...
45
 
 
46
 
void pulse(int pin, int times);
47
 
 
48
 
void setup() {
49
 
  Serial.begin(19200);
50
 
  pinMode(7, OUTPUT);
51
 
  pulse(7, 2);
52
 
  pinMode(8, OUTPUT);
53
 
  pulse(8, 2);
54
 
  pinMode(9, OUTPUT);
55
 
  pulse(9, 2);
56
 
}
57
 
 
58
 
int error=0;
59
 
int pmode=0;
60
 
// address for reading and writing, set by 'U' command
61
 
int here;
62
 
uint8_t buff[256]; // global block storage
63
 
 
64
 
#define beget16(addr) (*addr * 256 + *(addr+1) )
65
 
typedef struct param {
66
 
  uint8_t devicecode;
67
 
  uint8_t revision;
68
 
  uint8_t progtype;
69
 
  uint8_t parmode;
70
 
  uint8_t polling;
71
 
  uint8_t selftimed;
72
 
  uint8_t lockbytes;
73
 
  uint8_t fusebytes;
74
 
  int flashpoll;
75
 
  int eeprompoll;
76
 
  int pagesize;
77
 
  int eepromsize;
78
 
  int flashsize;
79
 
80
 
parameter;
81
 
 
82
 
parameter param;
83
 
 
84
 
// this provides a heartbeat on pin 9, so you can tell the software is running.
85
 
uint8_t hbval=128;
86
 
int8_t hbdelta=8;
87
 
void heartbeat() {
88
 
  if (hbval > 192) hbdelta = -hbdelta;
89
 
  if (hbval < 32) hbdelta = -hbdelta;
90
 
  hbval += hbdelta;
91
 
  analogWrite(LED_HB, hbval);
92
 
  delay(40);
93
 
}
94
 
  
95
 
 
96
 
void loop(void) {
97
 
  // is pmode active?
98
 
  if (pmode) digitalWrite(LED_PMODE, HIGH); 
99
 
  else digitalWrite(LED_PMODE, LOW);
100
 
  // is there an error?
101
 
  if (error) digitalWrite(LED_ERR, HIGH); 
102
 
  else digitalWrite(LED_ERR, LOW);
103
 
  
104
 
  // light the heartbeat LED
105
 
  heartbeat();
106
 
  if (Serial.available()) {
107
 
    avrisp();
108
 
  }
109
 
}
110
 
 
111
 
uint8_t getch() {
112
 
  while(!Serial.available());
113
 
  return Serial.read();
114
 
}
115
 
void readbytes(int n) {
116
 
  for (int x = 0; x < n; x++) {
117
 
    buff[x] = Serial.read();
118
 
  }
119
 
}
120
 
 
121
 
#define PTIME 30
122
 
void pulse(int pin, int times) {
123
 
  do {
124
 
    digitalWrite(pin, HIGH);
125
 
    delay(PTIME);
126
 
    digitalWrite(pin, LOW);
127
 
    delay(PTIME);
128
 
  } 
129
 
  while (times--);
130
 
}
131
 
 
132
 
void spi_init() {
133
 
  uint8_t x;
134
 
  SPCR = 0x53;
135
 
  x=SPSR;
136
 
  x=SPDR;
137
 
}
138
 
 
139
 
void spi_wait() {
140
 
  do {
141
 
  } 
142
 
  while (!(SPSR & (1 << SPIF)));
143
 
}
144
 
 
145
 
uint8_t spi_send(uint8_t b) {
146
 
  uint8_t reply;
147
 
  SPDR=b;
148
 
  spi_wait();
149
 
  reply = SPDR;
150
 
  return reply;
151
 
}
152
 
 
153
 
uint8_t spi_transaction(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
154
 
  uint8_t n;
155
 
  spi_send(a); 
156
 
  n=spi_send(b);
157
 
  //if (n != a) error = -1;
158
 
  n=spi_send(c);
159
 
  return spi_send(d);
160
 
}
161
 
 
162
 
void empty_reply() {
163
 
  if (CRC_EOP == getch()) {
164
 
    Serial.print((char)STK_INSYNC);
165
 
    Serial.print((char)STK_OK);
166
 
  } 
167
 
  else {
168
 
    Serial.print((char)STK_NOSYNC);
169
 
  }
170
 
}
171
 
 
172
 
void breply(uint8_t b) {
173
 
  if (CRC_EOP == getch()) {
174
 
    Serial.print((char)STK_INSYNC);
175
 
    Serial.print((char)b);
176
 
    Serial.print((char)STK_OK);
177
 
  } 
178
 
  else {
179
 
    Serial.print((char)STK_NOSYNC);
180
 
  }
181
 
}
182
 
 
183
 
void get_version(uint8_t c) {
184
 
  switch(c) {
185
 
  case 0x80:
186
 
    breply(HWVER);
187
 
    break;
188
 
  case 0x81:
189
 
    breply(SWMAJ);
190
 
    break;
191
 
  case 0x82:
192
 
    breply(SWMIN);
193
 
    break;
194
 
  case 0x93:
195
 
    breply('S'); // serial programmer
196
 
    break;
197
 
  default:
198
 
    breply(0);
199
 
  }
200
 
}
201
 
 
202
 
void set_parameters() {
203
 
  // call this after reading paramter packet into buff[]
204
 
  param.devicecode = buff[0];
205
 
  param.revision = buff[1];
206
 
  param.progtype = buff[2];
207
 
  param.parmode = buff[3];
208
 
  param.polling = buff[4];
209
 
  param.selftimed = buff[5];
210
 
  param.lockbytes = buff[6];
211
 
  param.fusebytes = buff[7];
212
 
  param.flashpoll = buff[8]; 
213
 
  // ignore buff[9] (= buff[8])
214
 
  //getch(); // discard second value
215
 
  
216
 
  // WARNING: not sure about the byte order of the following
217
 
  // following are 16 bits (big endian)
218
 
  param.eeprompoll = beget16(&buff[10]);
219
 
  param.pagesize = beget16(&buff[12]);
220
 
  param.eepromsize = beget16(&buff[14]);
221
 
 
222
 
  // 32 bits flashsize (big endian)
223
 
  param.flashsize = buff[16] * 0x01000000
224
 
    + buff[17] * 0x00010000
225
 
    + buff[18] * 0x00000100
226
 
    + buff[19];
227
 
 
228
 
}
229
 
 
230
 
void start_pmode() {
231
 
  spi_init();
232
 
  // following delays may not work on all targets...
233
 
  pinMode(RESET, OUTPUT);
234
 
  digitalWrite(RESET, HIGH);
235
 
  pinMode(SCK, OUTPUT);
236
 
  digitalWrite(SCK, LOW);
237
 
  delay(50);
238
 
  digitalWrite(RESET, LOW);
239
 
  delay(50);
240
 
  pinMode(MISO, INPUT);
241
 
  pinMode(MOSI, OUTPUT);
242
 
  spi_transaction(0xAC, 0x53, 0x00, 0x00);
243
 
  pmode = 1;
244
 
}
245
 
 
246
 
void end_pmode() {
247
 
  pinMode(MISO, INPUT);
248
 
  pinMode(MOSI, INPUT);
249
 
  pinMode(SCK, INPUT);
250
 
  pinMode(RESET, INPUT);
251
 
  pmode = 0;
252
 
}
253
 
 
254
 
void universal() {
255
 
  int w;
256
 
  uint8_t ch;
257
 
 
258
 
  for (w = 0; w < 4; w++) {
259
 
    buff[w] = getch();
260
 
  }
261
 
  ch = spi_transaction(buff[0], buff[1], buff[2], buff[3]);
262
 
  breply(ch);
263
 
}
264
 
 
265
 
void flash(uint8_t hilo, int addr, uint8_t data) {
266
 
  spi_transaction(0x40+8*hilo, 
267
 
  addr>>8 & 0xFF, 
268
 
  addr & 0xFF,
269
 
  data);
270
 
}
271
 
void commit(int addr) {
272
 
  spi_transaction(0x4C, (addr >> 8) & 0xFF, addr & 0xFF, 0);
273
 
}
274
 
 
275
 
//#define _current_page(x) (here & 0xFFFFE0)
276
 
int current_page(int addr) {
277
 
  if (param.pagesize == 32) return here & 0xFFFFFFF0;
278
 
  if (param.pagesize == 64) return here & 0xFFFFFFE0;
279
 
  if (param.pagesize == 128) return here & 0xFFFFFFC0;
280
 
  if (param.pagesize == 256) return here & 0xFFFFFF80;
281
 
  return here;
282
 
}
283
 
uint8_t write_flash(int length) {
284
 
  if (param.pagesize < 1) return STK_FAILED;
285
 
  //if (param.pagesize != 64) return STK_FAILED;
286
 
  int page = current_page(here);
287
 
  int x = 0;
288
 
  while (x < length) {
289
 
    if (page != current_page(here)) {
290
 
      commit(page);
291
 
      page = current_page(here);
292
 
    }
293
 
    flash(LOW, here, buff[x++]);
294
 
    flash(HIGH, here, buff[x++]);
295
 
    here++;
296
 
  }
297
 
 
298
 
  commit(page);
299
 
 
300
 
  return STK_OK;
301
 
}
302
 
 
303
 
uint8_t write_eeprom(int length) {
304
 
  // here is a word address, so we use here*2
305
 
  // this writes byte-by-byte,
306
 
  // page writing may be faster (4 bytes at a time)
307
 
  for (int x = 0; x < length; x++) {
308
 
    spi_transaction(0xC0, 0x00, here*2+x, buff[x]);
309
 
    delay(45);
310
 
  } 
311
 
  return STK_OK;
312
 
}
313
 
 
314
 
void program_page() {
315
 
  char result = (char) STK_FAILED;
316
 
  int length = 256 * getch() + getch();
317
 
  if (length > 256) {
318
 
      Serial.print((char) STK_FAILED);
319
 
      return;
320
 
  }
321
 
  char memtype = getch();
322
 
  for (int x = 0; x < length; x++) {
323
 
    buff[x] = getch();
324
 
  }
325
 
  if (CRC_EOP == getch()) {
326
 
    Serial.print((char) STK_INSYNC);
327
 
    if (memtype == 'F') result = (char)write_flash(length);
328
 
    if (memtype == 'E') result = (char)write_eeprom(length);
329
 
    Serial.print(result);
330
 
  } 
331
 
  else {
332
 
    Serial.print((char) STK_NOSYNC);
333
 
  }
334
 
}
335
 
uint8_t flash_read(uint8_t hilo, int addr) {
336
 
  return spi_transaction(0x20 + hilo * 8,
337
 
    (addr >> 8) & 0xFF,
338
 
    addr & 0xFF,
339
 
    0);
340
 
}
341
 
 
342
 
char flash_read_page(int length) {
343
 
  for (int x = 0; x < length; x+=2) {
344
 
    uint8_t low = flash_read(LOW, here);
345
 
    Serial.print((char) low);
346
 
    uint8_t high = flash_read(HIGH, here);
347
 
    Serial.print((char) high);
348
 
    here++;
349
 
  }
350
 
  return STK_OK;
351
 
}
352
 
 
353
 
char eeprom_read_page(int length) {
354
 
  // here again we have a word address
355
 
  for (int x = 0; x < length; x++) {
356
 
    uint8_t ee = spi_transaction(0xA0, 0x00, here*2+x, 0xFF);
357
 
    Serial.print((char) ee);
358
 
  }
359
 
  return STK_OK;
360
 
}
361
 
 
362
 
void read_page() {
363
 
  char result = (char)STK_FAILED;
364
 
  int length = 256 * getch() + getch();
365
 
  char memtype = getch();
366
 
  if (CRC_EOP != getch()) {
367
 
    Serial.print((char) STK_NOSYNC);
368
 
    return;
369
 
  }
370
 
  Serial.print((char) STK_INSYNC);
371
 
  if (memtype == 'F') result = flash_read_page(length);
372
 
  if (memtype == 'E') result = eeprom_read_page(length);
373
 
  Serial.print(result);
374
 
  return;
375
 
}
376
 
 
377
 
void read_signature() {
378
 
  if (CRC_EOP != getch()) {
379
 
    Serial.print((char) STK_NOSYNC);
380
 
    return;
381
 
  }
382
 
  Serial.print((char) STK_INSYNC);
383
 
  uint8_t high = spi_transaction(0x30, 0x00, 0x00, 0x00);
384
 
  Serial.print((char) high);
385
 
  uint8_t middle = spi_transaction(0x30, 0x00, 0x01, 0x00);
386
 
  Serial.print((char) middle);
387
 
  uint8_t low = spi_transaction(0x30, 0x00, 0x02, 0x00);
388
 
  Serial.print((char) low);
389
 
  Serial.print((char) STK_OK);
390
 
}
391
 
//////////////////////////////////////////
392
 
//////////////////////////////////////////
393
 
 
394
 
 
395
 
////////////////////////////////////
396
 
////////////////////////////////////
397
 
int avrisp() { 
398
 
  uint8_t data, low, high;
399
 
  uint8_t ch = getch();
400
 
  switch (ch) {
401
 
  case '0': // signon
402
 
    empty_reply();
403
 
    break;
404
 
  case '1':
405
 
    if (getch() == CRC_EOP) {
406
 
      Serial.print((char) STK_INSYNC);
407
 
      Serial.print("AVR ISP");
408
 
      Serial.print((char) STK_OK);
409
 
    }
410
 
    break;
411
 
  case 'A':
412
 
    get_version(getch());
413
 
    break;
414
 
  case 'B':
415
 
    readbytes(20);
416
 
    set_parameters();
417
 
    empty_reply();
418
 
    break;
419
 
  case 'E': // extended parameters - ignore for now
420
 
    readbytes(5);
421
 
    empty_reply();
422
 
    break;
423
 
 
424
 
  case 'P':
425
 
    start_pmode();
426
 
    empty_reply();
427
 
    break;
428
 
  case 'U':
429
 
    here = getch() + 256 * getch();
430
 
    empty_reply();
431
 
    break;
432
 
 
433
 
  case 0x60: //STK_PROG_FLASH
434
 
    low = getch();
435
 
    high = getch();
436
 
    empty_reply();
437
 
    break;
438
 
  case 0x61: //STK_PROG_DATA
439
 
    data = getch();
440
 
    empty_reply();
441
 
    break;
442
 
 
443
 
  case 0x64: //STK_PROG_PAGE
444
 
    program_page();
445
 
    break;
446
 
    
447
 
  case 0x74: //STK_READ_PAGE
448
 
    read_page();    
449
 
    break;
450
 
 
451
 
  case 'V':
452
 
    universal();
453
 
    break;
454
 
  case 'Q':
455
 
    error=0;
456
 
    end_pmode();
457
 
    empty_reply();
458
 
    break;
459
 
    
460
 
  case 0x75: //STK_READ_SIGN
461
 
    read_signature();
462
 
    break;
463
 
 
464
 
  // expecting a command, not CRC_EOP
465
 
  // this is how we can get back in sync
466
 
  case CRC_EOP:
467
 
    Serial.print((char) STK_NOSYNC);
468
 
    break;
469
 
    
470
 
  // anything else we will return STK_UNKNOWN
471
 
  default:
472
 
    if (CRC_EOP == getch()) 
473
 
      Serial.print((char)STK_UNKNOWN);
474
 
    else
475
 
      Serial.print((char)STK_NOSYNC);
476
 
  }
477
 
}
478