source: ISPProgrammer/PRESTO/UPrestoDLL.pas

Last change on this file was 363, checked in by chronos, 13 years ago
  • Added: Package ISPProgrammer for in-system programming of various chips. Supports Dallas ISP protocol, Presto, Rabbit RFU and some others Atmel devices.
File size: 13.7 KB
Line 
1// Object implementation of presto library
2// Documentation: http://tools.asix.net/prg_presto_download_dll.htm
3//
4// Features:
5// * Switching SPI data MSB or LSB first bit
6// * Block read/write/writeread operations
7// * Library runtime or compile time bindings
8//
9// Date: 2011-08-19
10
11unit UPrestoDLL;
12
13{$mode delphi}
14
15{$DEFINE LIBRARY_RUNTIME}
16//{$DEFINE LIBRARY_COMPILETIME}
17
18interface
19
20{$IFDEF Windows}
21
22uses
23 Windows, Classes, SysUtils;
24
25const
26 PrestoLibName = 'presto.dll';
27
28 // QSetPins()
29 PINS_HI = 3;
30 PINS_LO = 2;
31 PINS_HIZ = 1;
32 PINS_D_BIT = 0;
33 PINS_C_BIT = 2;
34 PINS_P_BIT = 4;
35 PINS_L_BIT = 6;
36
37 // QShiftByte()/QShiftByte_OutIn()
38 SHIFT_OUTIN_PIND = 0; // InputPin value
39 SHIFT_OUTIN_PINL = 1;
40 SHIFT_OUTIN_PINP = 2;
41 SHIFT_OUTIN_PINI = 3;
42 SHIFT_MODE1 = 1; //mode value
43 SHIFT_MODE3 = 3;
44
45 // QSetPrestoSpeed()
46 PRESTO_CLK1 = 0; // 3MHz - default value
47 PRESTO_CLK2 = 1; // 1.5MHz
48 PRESTO_CLK4 = 2; // 750kHz
49 PRESTO_CLK32 = 3; // 93.75kHz
50
51 OPEN_OK = $100;
52 OPEN_NOTFOUND = $101;
53 OPEN_CANNOTOPEN = $102;
54 OPEN_ALREADYOPEN = $103;
55 CLOSE_OK = $200;
56 CLOSE_CANNOTCLOSE = $201;
57 POWERON_OK = $300;
58 POWERON_OCURR = $301;
59 GETPINS_CODE = $400;
60 GETPINS_PIND = $01;
61 GETPINS_PINL = $02;
62 GETPINS_PINP = $04;
63 GETPINS_PINI = $08;
64 NOT_OPENED = $501;
65 SHIFT_BYTE_OUTIN_CODE = $600;
66 SUPPLY_VOLTAGE_CODE = $700;
67 SUPPLY_VOLTAGE_0V = $00;
68 SUPPLY_VOLTAGE_2V = $01;
69 SUPPLY_VOLTAGE_5V = $03; {1 or 2}
70 VPP_OK = $800;
71 VPP_OCURR = $801;
72 GO_BUTTON_NOT_PRESSED = $900;
73 GO_BUTTON_PRESSED = $901;
74
75 FATAL_OVERCURRENTVDD = $01;
76 FATAL_OVERCURRENTVPP = $02;
77 FATAL_OVERVOLTAGEVDD = $04;
78
79type
80 ENoAnswer = class(Exception);
81 EWrongAnswer = class(Exception);
82
83 TPrestoSpeed = (psClk1, psClk2, psClk4, psClk32);
84 TPrestoSPIMode = (smMode1, smMode3);
85 TPrestoPin = (spD, spL, spP, spI);
86 TPinState = (psNoChange, psHighZ, psLow, psHigh);
87 TSPIDataOrder = (doLSBFirst, doMSBFirst);
88
89 { TPresto }
90
91 TPresto = class
92 private
93 FOpenned: Boolean;
94 FPrestoSpeed: TPrestoSpeed;
95 FSerialNumber: Integer;
96 FPowerOnVddDelay: Integer; // us
97 FSPIDataOrder: TSPIDataOrder;
98 FSPIMode: TPrestoSPIMode;
99 FSPIInputPin: TPrestoPin;
100 function ReadAnswer: Integer;
101 function ReadAnswerBlocking: Integer;
102 function GetGoButtonState: Boolean;
103 procedure SetActiveLED(AValue: Boolean);
104 procedure SetDPullUp(AValue: Boolean);
105 procedure SetOpenned(AValue: Boolean);
106 procedure SetPowerVdd(AValue: Boolean);
107 procedure SetPowerVpp13V(AValue: Boolean);
108 procedure SetPrestoSpeed(AValue: TPrestoSpeed);
109 procedure SetSerialNumber(AValue: Integer);
110 function ReverseByte(Value: Byte): Byte;
111 public
112 constructor Create;
113 procedure WriteByte(Data: Byte);
114 function ReadWriteByte(Data: Byte): Byte;
115 function ReadByte: Byte;
116 procedure ReadWriteBlock(WriteData, ReadData: TStream);
117 procedure WriteBlock(WriteData: TStream);
118 procedure ReadBlock(ReadData: TStream);
119 procedure Delay(Duration: Integer);
120 procedure SetPin(Pin: TPrestoPin; Value: TPinState);
121 function GetPin(Pin: TPrestoPin): Boolean;
122 procedure Open;
123 procedure Close;
124 property Openned: Boolean read FOpenned write SetOpenned;
125 property ActiveLED: Boolean write SetActiveLED;
126 property PowerVdd: Boolean write SetPowerVdd;
127 property PowerVpp13V: Boolean write SetPowerVpp13V;
128 property SerialNumber: Integer read FSerialNumber write SetSerialNumber;
129 property PowerOnVddDelay: Integer read FPowerOnVddDelay
130 write FPowerOnVddDelay;
131 property GoButtonState: Boolean read GetGoButtonState;
132 property Speed: TPrestoSpeed read FPrestoSpeed write SetPrestoSpeed;
133 property DPullUp: Boolean write SetDPullUp;
134 property SPIMode: TPrestoSPIMode read FSPIMode write FSPIMode;
135 property SPIInputPin: TPrestoPin read FSPIInputPin write FSPIInputPin;
136 property SPIDataOrder: TSPIDataOrder read FSPIDataOrder write FSPIDataOrder;
137 end;
138
139const
140 SPIModeValue: array[TPrestoSPIMode] of Integer = (SHIFT_MODE1, SHIFT_MODE3);
141
142{$IFDEF LIBRARY_COMPILETIME}
143function AGet(var answer: integer): LongBool; stdcall; external PrestoLibName;
144procedure QSetActiveLED(led: LongBool); stdcall; external PrestoLibName;
145procedure QOpenPresto(sn: integer); stdcall; external PrestoLibName;
146procedure QClosePresto; stdcall; external PrestoLibName;
147procedure QPoweronVdd(delayus: integer); stdcall; external PrestoLibName;
148procedure QPoweroffVdd; stdcall; external PrestoLibName;
149function AGetBlocking: integer; stdcall; external PrestoLibName;
150procedure QSetPins(pins: cardinal); stdcall; external PrestoLibName;
151procedure QGetPins; stdcall; external PrestoLibName;
152procedure QShiftByte(databyte:integer; mode:integer); stdcall; external PrestoLibName;
153procedure QShiftByte_OutIn(databyte:integer; mode:integer; InputPin:integer); stdcall; external PrestoLibName;
154procedure QCheckSupplyVoltage; stdcall; external PrestoLibName;
155procedure QPoweronVpp13V; stdcall; external PrestoLibName;
156procedure QPoweroffVpp13V; stdcall; external PrestoLibName;
157procedure QSetDPullup(dpullup_on: LongBool); stdcall; external PrestoLibName;
158procedure QCheckGoButton; stdcall; external PrestoLibName;
159procedure QSetPrestoSpeed(speed:cardinal); stdcall; external PrestoLibName;
160procedure QDelay(delayus: integer); stdcall; external PrestoLibName;
161{$ENDIF}
162
163{$IFDEF LIBRARY_RUNTIME}
164var
165 LibraryLoaded: Boolean;
166 AGet: function (out answer: integer): LongBool; stdcall;
167 QSetActiveLED: procedure (led: LongBool); stdcall;
168 QOpenPresto: procedure (sn: integer); stdcall;
169 QClosePresto: procedure ; stdcall;
170 QPoweronVdd: procedure (delayus: integer); stdcall;
171 QPoweroffVdd: procedure ; stdcall;
172 AGetBlocking: function : integer; stdcall;
173 QSetPins: procedure (pins: cardinal); stdcall;
174 QGetPins: procedure ; stdcall;
175 QShiftByte: procedure (databyte:integer; mode:integer); stdcall;
176 QShiftByte_OutIn: procedure (databyte:integer; mode:integer; InputPin:integer); stdcall;
177 QCheckSupplyVoltage: procedure ; stdcall;
178 QPoweronVpp13V: procedure ; stdcall;
179 QPoweroffVpp13V: procedure ; stdcall;
180 QSetDPullup: procedure (dpullup_on: LongBool); stdcall;
181 QCheckGoButton: procedure ; stdcall;
182 QSetPrestoSpeed: procedure (speed:cardinal); stdcall;
183 QDelay: procedure (delayus: integer); stdcall;
184{$ENDIF}
185
186{$ENDIF}
187
188implementation
189
190{$IFDEF Windows}
191
192{$IFDEF LIBRARY_RUNTIME}
193var
194 DLLHandle: HModule;
195{$ENDIF}
196
197resourcestring
198 SNoAnswer = 'Presto no answer';
199 SWrongAnswer = 'Presto wrong answer';
200 SPowerVddError = 'Presto power Vdd error';
201 SPowerVpp13VError = 'Presto power Vpp 13V error';
202 SOpenError = 'Presto open error: %s';
203 SCloseError = 'Presto close error';
204
205{$IFDEF LIBRARY_RUNTIME}
206procedure LoadLibraries;
207begin
208 if not LibraryLoaded then begin
209 DLLHandle := LoadLibrary(PrestoLibName);
210 if DLLHandle <> 0 then begin
211 @AGet := GetProcAddress(DLLHandle, 'AGet');
212 @QSetActiveLED := GetProcAddress(DLLHandle, 'QSetActiveLED');
213 @QOpenPresto := GetProcAddress(DLLHandle, 'QOpenPresto');
214 @QClosePresto := GetProcAddress(DLLHandle, 'QClosePresto');
215 @QPoweronVdd := GetProcAddress(DLLHandle, 'QPoweronVdd');
216 @QPoweroffVdd := GetProcAddress(DLLHandle, 'QPoweroffVdd');
217 @AGetBlocking := GetProcAddress(DLLHandle, 'AGetBlocking');
218 @QSetPins := GetProcAddress(DLLHandle, 'QSetPins');
219 @QGetPins := GetProcAddress(DLLHandle, 'QGetPins');
220 @QShiftByte := GetProcAddress(DLLHandle, 'QShiftByte');
221 @QShiftByte_OutIn := GetProcAddress(DLLHandle, 'QShiftByte_OutIn');
222 @QCheckSupplyVoltage := GetProcAddress(DLLHandle, 'QCheckSupplyVoltage');
223 @QPoweronVpp13V := GetProcAddress(DLLHandle, 'QPoweronVpp13V');
224 @QPoweroffVpp13V := GetProcAddress(DLLHandle, 'QPoweroffVpp13V');
225 @QSetDPullup := GetProcAddress(DLLHandle, 'QSetDPullup');
226 @QCheckGoButton := GetProcAddress(DLLHandle, 'QCheckGoButton');
227 @QSetPrestoSpeed := GetProcAddress(DLLHandle, 'QSetPrestoSpeed');
228 @QDelay := GetProcAddress(DLLHandle, 'QDelay');
229 end else raise Exception.Create('Missing library presto.dll');
230 LibraryLoaded := True;
231 end;
232end;
233
234procedure FreeLibraries;
235begin
236 if DLLHandle <> 0 then FreeLibrary(DLLHandle);
237 LibraryLoaded := False;
238end;
239{$ENDIF}
240
241{ TPresto }
242
243procedure TPresto.SetActiveLED(AValue: Boolean);
244begin
245 QSetActiveLED(AValue);
246end;
247
248procedure TPresto.SetDPullUp(AValue: Boolean);
249begin
250 QSetDPullup(AValue);
251end;
252
253function TPresto.ReadAnswer: Integer;
254begin
255 if not AGet(Result) then
256 raise ENoAnswer.Create(SNoAnswer);
257end;
258
259function TPresto.ReadAnswerBlocking: Integer;
260begin
261 while not AGet(Result) do ;
262end;
263
264function TPresto.ReverseByte(Value: Byte): Byte;
265begin
266 Value := ((Value shr 1) and $55) or ((Value and $55) shl 1);
267 Value := ((Value shr 2) and $33) or ((Value and $33) shl 2);
268 Value := ((Value shr 4) and $f) or ((Value and $f) shl 4);
269 Result := Value;
270end;
271
272function TPresto.GetGoButtonState: Boolean;
273begin
274 QCheckGoButton;
275 Result := ReadAnswer = GO_BUTTON_PRESSED;
276end;
277
278procedure TPresto.SetOpenned(AValue: Boolean);
279begin
280 if AValue then begin
281 Open;
282 end else begin
283 Close;
284 end;
285end;
286
287procedure TPresto.SetPowerVdd(AValue: Boolean);
288begin
289 if AValue then begin
290 QPoweronVdd(FPowerOnVddDelay);
291 if ReadAnswer <> POWERON_OK then
292 raise Exception.Create(SPowerVddError);
293 end else QPoweroffVdd;
294end;
295
296procedure TPresto.SetPowerVpp13V(AValue: Boolean);
297begin
298 if AValue then begin
299 QPoweronVpp13V;
300 if ReadAnswer <> VPP_OK then
301 raise Exception.Create(SPowerVpp13VError);
302 end else QPoweroffVpp13V;
303end;
304
305procedure TPresto.SetPrestoSpeed(AValue: TPrestoSpeed);
306begin
307 if FPrestoSpeed = AValue then Exit;
308 FPrestoSpeed := AValue;
309 if FOpenned then QSetPrestoSpeed(Integer(AValue));
310end;
311
312procedure TPresto.SetSerialNumber(AValue: Integer);
313begin
314 if FSerialNumber = AValue then Exit;
315 FSerialNumber := AValue;
316 Openned := False;
317 Openned := True;
318end;
319
320constructor TPresto.Create;
321begin
322 FSerialNumber := -1;
323 FPowerOnVddDelay := 10000;
324 FSPIMode := smMode1;
325 FSPIDataOrder := doLSBFirst;
326 FSPIInputPin := spI;
327 FPrestoSpeed := psClk1;
328end;
329
330procedure TPresto.WriteByte(Data: Byte);
331begin
332 if FSPIDataOrder = doMSBFirst then Data := ReverseByte(Data);
333 QShiftByte(Data, SPIModeValue[FSPIMode]);
334end;
335
336function TPresto.ReadWriteByte(Data: Byte): Byte;
337var
338 Answer: Integer;
339begin
340 if FSPIDataOrder = doMSBFirst then Data := ReverseByte(Data);
341 QShiftByte_OutIn(Data, SPIModeValue[FSPIMode], Integer(FSPIInputPin));
342 Answer := ReadAnswerBlocking;// AGetBlocking;
343 if (Answer and $ff00) <> SHIFT_BYTE_OUTIN_CODE then
344 raise EWrongAnswer.Create(SWrongAnswer);
345 Result := Answer and $ff;
346 if FSPIDataOrder = doMSBFirst then Result := ReverseByte(Result);
347end;
348
349function TPresto.ReadByte: Byte;
350begin
351 Result := ReadWriteByte(0);
352end;
353
354procedure TPresto.ReadWriteBlock(WriteData, ReadData: TStream);
355var
356 Answer: Integer;
357 I: Integer;
358begin
359 WriteData.Position := 0;
360 for I := 0 to WriteData.Size - 1 do
361 QShiftByte_OutIn(WriteData.ReadByte, SPIModeValue[FSPIMode], Integer(FSPIInputPin));
362
363 ReadData.Position := 0;
364 while ReadData.Position < ReadData.Size do begin
365 Answer := ReadAnswerBlocking; // AGetBlocking;
366 if (Answer and $ff00) <> SHIFT_BYTE_OUTIN_CODE then
367 raise EWrongAnswer.Create(SWrongAnswer);
368 ReadData.WriteByte(ReverseByte(Answer and $ff));
369 end;
370end;
371
372procedure TPresto.WriteBlock(WriteData: TStream);
373begin
374 WriteData.Position := 0;
375 while WriteData.Position < WriteData.Size do begin
376 WriteByte(WriteData.ReadByte);
377 end;
378end;
379
380procedure TPresto.ReadBlock(ReadData: TStream);
381var
382 Answer: Integer;
383 I: Integer;
384begin
385 ReadData.Position := 0;
386 for I := 0 to ReadData.Size - 1 do begin
387 QShiftByte_OutIn(0, SPIModeValue[FSPIMode], Integer(FSPIInputPin));
388 end;
389
390 ReadData.Position := 0;
391 while ReadData.Position < ReadData.Size do begin
392 Answer := ReadAnswerBlocking; // AGetBlocking;
393 if (Answer and $ff00) <> SHIFT_BYTE_OUTIN_CODE then
394 raise EWrongAnswer.Create(SWrongAnswer);
395 ReadData.WriteByte(ReverseByte(Answer and $ff));
396 end;
397end;
398
399procedure TPresto.Delay(Duration: Integer);
400begin
401 QDelay(Duration);
402end;
403
404procedure TPresto.SetPin(Pin: TPrestoPin; Value: TPinState);
405begin
406 QSetPins(Integer(Value) shl (Integer(Pin) * 2));
407end;
408
409function TPresto.GetPin(Pin: TPrestoPin): Boolean;
410var
411 Answer: Integer;
412begin
413 QGetPins;
414 Answer := ReadAnswerBlocking;
415 if (Answer and $ff00) <> GETPINS_CODE then
416 raise EWrongAnswer.Create(SWrongAnswer);
417 Result := ((Answer shr Integer(Pin)) and 1) = 1;
418end;
419
420procedure TPresto.Open;
421var
422 Answer: Integer;
423begin
424 if not FOpenned then begin
425 {$IFDEF LIBRARY_RUNTIME}
426 if not LibraryLoaded then LoadLibraries;
427 {$ENDIF}
428 while AGet(Answer) do ; // Flush input buffer
429 QOpenPresto(SerialNumber);
430 Answer := AGetBlocking;
431 if Answer <> OPEN_OK then
432 raise Exception.Create(Format(SOpenError, [IntToHex(Answer, 4)]));
433 if FPrestoSpeed <> psClk1 then QSetPrestoSpeed(Integer(FPrestoSpeed));
434 FOpenned := True;
435 end;
436end;
437
438procedure TPresto.Close;
439var
440 Answer: Integer;
441begin
442 if FOpenned then begin
443 while AGet(Answer) do ; // Flush receive buffer
444 QClosePresto;
445 //if ReadAnswer <> CLOSE_OK then
446 // raise Exception.Create(SCloseError);
447 FOpenned := False;
448 end;
449end;
450
451initialization
452
453{$IFDEF LIBRARY_RUNTIME}
454LibraryLoaded := False;
455//LoadLibraries;
456{$ENDIF}
457
458finalization
459
460{$IFDEF LIBRARY_RUNTIME}
461if LibraryLoaded then FreeLibraries;
462{$ENDIF}
463
464{$ENDIF}
465
466end.
467
Note: See TracBrowser for help on using the repository browser.