User avatar
ValterFukuoka
Posts: 94
Joined: Sat Oct 01, 2011 11:39 pm
Location: Japan
Contact: Website

Re: Add small cpu for R/C servo controlled

Sun Sep 29, 2013 7:24 am

ValterFukuoka wrote:burnLVP_18FXX(K)XX RasPI GPIO beta version
The code for 18F2550 and 18F14K50 still incomplete (and messy), but it can:
Using RaspberryPI GPIO and Python:

a) bulk erase
b) program memory
c) program config bits

tested on:
1) 18F2550
2) 18F14K50
Temporarily here (PLEASE READ RED TEXT BELOW):
Valter
Hi everybody.
I WANT TO APOLOGIZE ABOUT MY LAST POST.
I should not put the code without warning people that it is just a testing stage and, intended only for people to have a look at the source code...

YES, the code is working, BUT IT CAN BURN INCORRECT VALUES TO THE CONFIG ZONE OF THE PIC18, LEAVING IT "CODE PROTECTED" FOR LOW VOLTAGE PROGRAMMING...

So, please don't try to run the code if you are not sure about what you are doing, otherwise you can "lock" the PIC18 in a state in which it will need a HIGH VOLTAGE RESET (which the RasPI cannot do).

Fortunately I did COMMENT (#) all the calls to the routines, so the code will not work unless the user himself UNLOCK (by removing the '#' sign) the lines...

Sorry about that,
Regards,
Valter

User avatar
ValterFukuoka
Posts: 94
Joined: Sat Oct 01, 2011 11:39 pm
Location: Japan
Contact: Website

Re: Add small cpu for R/C servo controlled

Sun Sep 29, 2013 12:58 pm

Hi.
I just have some announcements to make.

{Pigeon version}
Image
The MicroPICBurner is now running a improved firmware.
It’s now the “pigeon” version (faster than the turtle-version), with improved routines.
Turtle version was taking around 15 minutes to burn a full 18F2550 32k flash… now “pigeon” version can burn it in 2 minutes…
Much more progress can be made on speed but I want to focus on testing and certificate that everything works without problem… also, I want it for Python and C language, so, I need more time to full test all the implicated variables (Linux/Windows, Python/C, host/USB/PIC-Firmware timing, etc)…
If possible, will also run on Raspberry PI using USB... not tested yet...
Better, both versions, “turtle” and “pigeon” can go side by side inside firmware, since there is still free room on the firmware…

{Alive!}
Also, I like to report that I am able to use MicroPICBurner (senior) to burn MicroPICBurner Jr… which means it can self-replicate (it can program itself into a new MCU, which in turn becomes a replica of itself).
I already use uPICBurner Jr to program an 18F2550 with complete success!

Image

{PGM and LVP}
In LVP mode, PGM pin on MicroPICBurner now gets one resistor (weak pull down) so that it can work stable. Without it, it looks like it (the target) enters in “program/verify” mode and cannot run properly, after programming…
It can, potentially affect others 18F series when using LVP…
12F/16F should not have any problem like this, since it uses the “magic sequence” to enter program/verify mode…

Image

“Pigeon” even have its “soundtrack”(lol):
http://www.youtube.com/watch?v=nPzlGklVNb0

Valter

danjperron
Posts: 3312
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: Add small cpu for R/C servo controlled

Mon Sep 30, 2013 3:20 am

I start to change the burnLVP to include the PIC18 familly,


it is not complete and some functions are not fonctionnal!

the code are on my github ( Experimental version).

https://github.com/danjperron/burnLVP

Each PIC family is on a different file and I also use class to override functions. The IO interface as is own file, this way it is easy to change the type of I/O use to program.


I'm testing the PIC18F2580 right now and it is far to be working. This is where I'm right now. Next will be the
pic18F26K80 for the PIC18FXXKXX familly.

I did it that way to simplify the add-on on different cpu.

Daniel

danjperron
Posts: 3312
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: Add small cpu for R/C servo controlled

Tue Oct 01, 2013 5:30 pm

ok I got burnLVPx.py working with
  • pic12/16
    pic18FXX2 family
    pic18F2XXX family
    pic18FXXK80 family
The new pic18FXXK80, like the Pic12 family, doesn't need PGM. And it is possible to program at 3.3V.

Still need to work on the pic18F2XXX config system, but it is operational.

The code is on the github: https://github.com/danjperron/burnLVP

Daniel

User avatar
ValterFukuoka
Posts: 94
Joined: Sat Oct 01, 2011 11:39 pm
Location: Japan
Contact: Website

Re: Add small cpu for R/C servo controlled

Fri Oct 04, 2013 1:45 am

Hi everybody, just want to update the state of the MicroPICBurner...

a) MicroPICBurner now have its own OFFICIAL USB VID and PID numbers...
{right mouse click to see full picture}
Image
Image

b) I now have a handmade "kit" that I will soon like to offer as part of "help support Molec Project" effort (instead of asking for donation I will ask people to support the project by buying these little handmade learning kits).
Image

c) The Compiler/Editor Geany for JAL Programming, here showing the "blink LED for 12F1840".
Image

I am now working on the SETUP PACKAGE, so that the user only have to download 1 file and run it to setup all the necessary software into its correct place... almost there...

Regards all,
Valter

User avatar
ValterFukuoka
Posts: 94
Joined: Sat Oct 01, 2011 11:39 pm
Location: Japan
Contact: Website

Re: Add small cpu for R/C servo controlled

Tue Oct 08, 2013 11:45 pm

Hi, I am putting some time on some basic graphical user interface tools for programming the target MCUs…
Now it is possible to create, edit and burn programs all done by using basic GUI tools…
It is being testing on Win7 and XP, but the code should work on any Linux and RasPI as well with minor adaptations…
Since RasPI version is already running, and RasPI don’t need this special edition, I am centered on making it stable on Win7 and XP at first, then going to Linux and RasPI after that…

Code Editor (Geany)
Image

Editor invoking the MicroPICBurner Interface
Image

The MicroPICBurner Interface (created with FreePascal/Lazarus – should work on RasPI without problem… not tested yet)
Image

Valter

User avatar
ValterFukuoka
Posts: 94
Joined: Sat Oct 01, 2011 11:39 pm
Location: Japan
Contact: Website

Re: Add small cpu for R/C servo controlled

Tue Oct 29, 2013 2:17 am

Hi Daniel and everybody, apologies for some delays…
I am preparing the materials for release the whole project for the general public, it took me some time to sort all the stuff and to get a “clear picture” about how to do it better (at least this is my version of “what to do now”)…

I will be sharing here all the steps as I create them… I like to start with some raw material for the first “helloworld” demonstration using the Molec and the MicroPICBurner Programmer… (raw video and presentation slides)

I should have the final edited version of the video soon…


Here are the links to Youtube videos (not listed public yet, need these links to watch):

[video compile, upload]
http://youtu.be/Q0zdwH4V1Mg

[video clear memory]
http://youtu.be/3JMPzz7e_PM

[video change blinking time]
http://youtu.be/Wmf5yWWK4-k


And here some future PDF presentation, on Google Docs:

[Presentation - building better]
https://docs.google.com/presentation/d/ ... sp=sharing

[Presentation - soft revolution]
https://docs.google.com/presentation/d/ ... sp=sharing

[Presentation - why participate]
https://docs.google.com/presentation/d/ ... sp=sharing

Regards all,
Valter

danjperron
Posts: 3312
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: Add small cpu for R/C servo controlled

Tue Oct 29, 2013 4:00 am

Hi Valter,


very nice!

I did receive some PIC18F14K50 . I will implement it on burnLVPx very soon.

Daniel

User avatar
ValterFukuoka
Posts: 94
Joined: Sat Oct 01, 2011 11:39 pm
Location: Japan
Contact: Website

Re: Add small cpu for R/C servo controlled

Tue Oct 29, 2013 11:44 am

Hi.
The final edited version of the videos will be something like these, with legends and video overlays...

video 1 - programming the 12F1822
http://youtu.be/aeE-DWGPq0k


video 2 erase the 12F1822
http://youtu.be/2U7MluvBEtw


The GUI for the burnlvp.py is done in FreePascal/Lazarus, so, it can run on Linux, Raspberry PI, Windows and Macs...
Also, I think Pascal will make things easy for the beginners...

These are listed public on Youtube...
Valter

User avatar
ValterFukuoka
Posts: 94
Joined: Sat Oct 01, 2011 11:39 pm
Location: Japan
Contact: Website

Re: Add small cpu for R/C servo controlled

Wed Oct 30, 2013 2:54 am

Hi, Daniel, I forgot to tell that I manage to get the 14K50, 2550, 4550 working...

Using that first modules you did with a little modification I was able to make a temporary working code, so that we can use it for the first release of the MicroPICBurner...

The code is little messy right now, I need to streamline it to publish... it is in messy-hacking stage now...
But, I did lots of tests and it is working well...
As a temporary solution it is ok.

Valter

User avatar
ValterFukuoka
Posts: 94
Joined: Sat Oct 01, 2011 11:39 pm
Location: Japan
Contact: Website

Re: Add small cpu for R/C servo controlled

Thu Oct 31, 2013 5:42 am

Just want to show a little video about installing the software to run the MicroPICBurner (burnLVP) in a Windows Desktop machine… I am trying to be as “cross platform” as possible, so everything can go well on desktop PCs and RasPIs…

I manage to put all the necessary software into a package, so that the installation process can become simple for the end user…

Now, Windows users can just download the software package and run the install scripts, I did a little video showing how to do:
[setup software]
http://youtu.be/f88kj_BmcJM

[open a sample]
http://youtu.be/szzskjHTFoA

Valter

watchdogtimer
Posts: 7
Joined: Sun Dec 08, 2013 10:50 am

Re: Add small cpu for R/C servo controlled

Sun Dec 08, 2013 11:24 am

I am wondering how difficult it would be to apply your bit-banging method to some of the newer 18F chips like the 18F25K50 and 18F27J53 chips that can communicate via USB. These chips use the same 'magic' 32-bit sequence to enter ICSP LVP programming mode as the K80 series. To do this, would I just need to add the device ID and code size to the list in CpuPIC18FXXK80.py ? What would I need to do to program the bootloader, too? My thinking is that you could load a bootloader on the chip first using your method, then (re-)program it as many times as you want later via USB.

-Jim

danjperron
Posts: 3312
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: Add small cpu for R/C servo controlled

Sun Dec 08, 2013 1:04 pm

Hi Jim,

Yes this is how I do it. First you read the literature about it and compare what has to be done.

Check the burn18.py on the github

https://github.com/danjperron/burnLVP

I know that Valter Fukuoka did the code for the PIC18F14K50. I did bought some for that purpose.

But I never took the time to create the code in the github.

The difference between burnLVP and burn18 is the object oriented method. This way it is easy to add cpu and change what is needed to accommodate the cpu.

I could look to it but if you think you could do it I will grant you access to the github.

Daniel
Last edited by danjperron on Sun Dec 08, 2013 2:04 pm, edited 1 time in total.

watchdogtimer
Posts: 7
Joined: Sun Dec 08, 2013 10:50 am

Re: Add small cpu for R/C servo controlled

Sun Dec 08, 2013 1:55 pm

Thanks, Daniel. I'll give it a try, and if I can get it to work, I'll send you a pull request.

-Jim

danjperron
Posts: 3312
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: Add small cpu for R/C servo controlled

Sun Dec 08, 2013 2:04 pm

Perfect !

Thanks Jim


Daniel

User avatar
ValterFukuoka
Posts: 94
Joined: Sat Oct 01, 2011 11:39 pm
Location: Japan
Contact: Website

Re: Add small cpu for R/C servo controlled

Sun Dec 08, 2013 3:09 pm

Hi Jim,
watchdogtimer wrote:I am wondering how difficult it would be to apply your bit-banging method to some of the newer 18F chips like the 18F25K50 and 18F27J53 chips that can communicate via USB. These chips use the same 'magic' 32-bit sequence to enter ICSP LVP programming mode as the K80 series. To do this, would I just need to add the device ID and code size to the list in CpuPIC18FXXK80.py ? What would I need to do to program the bootloader, too? My thinking is that you could load a bootloader on the chip first using your method, then (re-)program it as many times as you want later via USB.

-Jim
the code that Daniel is referring (14K50) is here on this old post (page 4 on this thread):
http://www.raspberrypi.org/phpBB3/viewt ... 96#p428796

The 2550 code works for the 4550 also, the 14K50 just have a (one) difference in the "bulk erase" timing...
It was based on the Daniel's "first draft" for the 18F series...

That one is the last that I did test on RaspberryPI and 18F...

Regards,
Valter

PS. There is another code, using PC (not Rasp), I am testing, using basically the same routines there. I hope to release it soon and will be trying to "fuse" the PC and Rasp versions into one...

User avatar
nroff-man
Posts: 23
Joined: Mon Jul 30, 2012 7:31 pm
Location: /usr/bin

Re: Add small cpu for R/C servo controlled

Mon Dec 09, 2013 4:20 pm

Hi

The pic18J series have a few more differences than just erase timing.

For example, these devices have `volatile configuration' which means
that the configuration registers are in RAM and not flash. Also, they
have no IDLOC. This doesn't really have a great impact though, because
instead of programming the configuration area as with PIC18, programming
now occurs at the end of program flash instead and IDLOC is just
ignored. They also have much larger erase blocks if you were curious to
know.

In the summer I done quite a few tests with a PIC18LF27J53 (LF) in
my own programming project found here:
http://dev.kewl.org/k8048/Doc/
This works on the R-PI and should work fine with latest tarball here:
http://dev.kewl.org/k8048/k8048-2.16-dev.tar.gz

This project is very old now and imperfect is many ways, however,
it works well on the R-PI with a PGC of around 1MHz in operation.

PS. The latest tarball also includes support for PIC24/dsPIC devices
and a hex file with some instructions for creating a breadboard
bus-pirate (PIC24FJ64GA002). This is work-in-progress yet you may
find it interesting. I will make a thread about this when fully tested.

watchdogtimer
Posts: 7
Joined: Sun Dec 08, 2013 10:50 am

Re: Add small cpu for R/C servo controlled

Tue Dec 10, 2013 10:57 am

Outstanding work, nroff-man! Thanks for bringing it to my attention.

I see you tested an 18LF27J53. Did you do so using a Raspberry Pi and the breadboard method? I'm curious how long it takes given the large amount of memory this chip has compared to most others....

User avatar
nroff-man
Posts: 23
Joined: Mon Jul 30, 2012 7:31 pm
Location: /usr/bin

Re: Add small cpu for R/C servo controlled

Tue Dec 10, 2013 12:21 pm

Good day.
watchdogtimer wrote:Outstanding work, nroff-man! Thanks for bringing it to my attention.

I see you tested an 18LF27J53. Did you do so using a Raspberry Pi and the breadboard method? I'm curious how long it takes given the large amount of memory this chip has compared to most others....
Thanks for your comments.

PIC18J devices can only be programmed at 3V3, they will not support a higher
voltage on VDD or VPP and in the case of the LF devices, they also need a
2.5V external regulator for VCAP/VDDCORE. Both F and LF devices need a low
E.S.R. tantalum capacitor connected to ground on this pin.

You should refer to the Microchip document 01021a.pdf for more information.

I have updated the test demo for this device to include some timing information
for your attention (scroll down to program timings).
http://dev.kewl.org/k8048/Src/asm/test/pic18lf27j53.asm

In the worst case (programming 128KB flash) it takes 4.6 seconds. This is fast
enough in my opinion.

In the examples you may notice one of the configuration words in flash
reading back as 0xF7, this is to be expected.

For these tests, the device was connected to the R-PI like this:
http://dev.kewl.org/k8048/Images/pic18lf27j53.jpg

In case you were wondering about choice of VDDCORE regulator, then it's
purely what's available at CPC in through-hole or DIL packaging that
determines my selection.

Good luck, bye-bye.

User avatar
ValterFukuoka
Posts: 94
Joined: Sat Oct 01, 2011 11:39 pm
Location: Japan
Contact: Website

Re: Add small cpu for R/C servo controlled

Sat Jan 18, 2014 2:43 pm

Hi everybody, just want to report the first beta release of PC version of the burnLVP programmer, the “pcBurnLVP” which runs on a regular PC and uses a USB programmer (picture)…
Image


To help beginners we did a complete “package” with all components and its related install scripts that you can download and install…
Image


[How to use]
This small video here shows how to start using it...
https://www.youtube.com/watch?v=aeE-DWGPq0k

[Beta / Testing]
Current stage is beta/testing, so, please expect a lot of small changes that we will be issuing on its components parts. Releasing it now and issuing small changes is the best way for us to do, instead of expecting to correct everything and then releasing, which inevitably will take much more time... our apologies for using this approach but this is the one that is possible for us now...

Current version is known to work (tested) with Win7 and XP, and the current this package itself is good for Windows platform only...

[Please cooperate]
So, please, if you want to test and find some issues, help us by reporting the trouble...

[Documentation]
More documentation will be provided, we just have minimalist docs to date...

[Making it easier...]
We hope to make it easy to setup and run, so, there may be change in the future releases if we find better ways to accomplish the same goal...

[Get it here]
https://sites.google.com/site/physicalsoftwareclub/

Regards all,
Valter Fukuoka
2014, January 18

User avatar
ukscone
Forum Moderator
Forum Moderator
Posts: 4044
Joined: Fri Jul 29, 2011 2:51 pm
Contact: Website

Re: Add small cpu for R/C servo controlled

Tue Jun 03, 2014 7:14 pm

I know this is an old thread but I need a way to LVP a PIC16F876A using a raspberry pi. do you think BurnLVP & the schematic will work for that chip?

danjperron
Posts: 3312
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: Add small cpu for R/C servo controlled

Tue Jun 03, 2014 7:30 pm

The pic16 will be in the CpuPIC12.py file , but it is not implemented. I will see what I could do but I won't be able work on it before next week and I will need you to check the code since I don't have the i.c.

If you know python, it is easy to modify it and I think it is simple enough to figure out what it does.

Are you ready to be my tester?

User avatar
ukscone
Forum Moderator
Forum Moderator
Posts: 4044
Joined: Fri Jul 29, 2011 2:51 pm
Contact: Website

Re: Add small cpu for R/C servo controlled

Tue Jun 03, 2014 7:58 pm

of course :)

my main question is actually the original circuit diagram. the wire that I assume is for the PGM pin is going to one that seems to be labeled with the HVP pin label. I'm assuming that is just a pin naming difference?

danjperron
Posts: 3312
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: Add small cpu for R/C servo controlled

Tue Jun 03, 2014 8:41 pm

In LVP mode , RB3 can't be used. Is it okay with you?

Put RB3 to vdd.

I didn't check if the MCLR need to stay high.

SendMagic function has to be disabled


In the CpuList table we will need to add

0x09E0 : [ 'PIC16F876' , 8192] ,

PIC_CLK GPIO4 pin 7=> RB6
PIC_DATA GPIO8 pin 24=> RB7
PIC_MCLR GPIO9 pin 21=> MCLR
and
Vdd => RB3


and give it a try and tell me what went wrong.

Daniel

danjperron
Posts: 3312
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: Add small cpu for R/C servo controlled

Tue Jun 03, 2014 9:03 pm

Simpler.

try this python BurnLVP.py code and tell me what went wrong

I disable SendMagic.

I swap Set/Release_LVP to Set/Release_VPP

Code: Select all

#!/usr/bin/env python

################################
#
# burnLVP.py  
#
#
# Program to burn pic12F1840 using LVP mode with a Rasberry Pi
#
#
# programmer : Daniel Perron
# Date       : June 30, 2013
# Version    : 1.0
#
# source code:  https://github.com/danjperron/A2D_PIC_RPI
#
#


#////////////////////////////////////  MIT LICENSE ///////////////////////////////////
#	The MIT License (MIT)
#
#	Copyright (c) 2013 Daniel Perron
#
#	Permission is hereby granted, free of charge, to any person obtaining a copy of
#	this software and associated documentation files (the "Software"), to deal in
#	the Software without restriction, including without limitation the rights to
#	use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
#	the Software, and to permit persons to whom the Software is furnished to do so,
#	subject to the following conditions:
#
#	The above copyright notice and this permission notice shall be included in all
#	copies or substantial portions of the Software.
#
#	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
#	FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
#	COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
#	IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
#	CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.



from time import sleep
import RPi.GPIO as GPIO
import sys, termios, atexit
from intelhex import IntelHex
from select import select   


#set io pin

#CLK GPIO 4 
PIC_CLK = 7

#DATA GPIO 8
PIC_DATA = 24

#MCLR GPIO 9
PIC_MCLR = 21


#compatible PIC id

PIC12F1840 = 0x1b80
PIC16F1847 = 0x1480
PIC12LF1840 = 0x1bc0
PIC16LF1847 = 0x14A0

PIC16F1826  = 0x2780
PIC16F1827  = 0x27A0
PIC16LF1826 = 0x2880
PIC16LF1827 = 0x28A0
PIC16F1823  = 0x2720
PIC16LF1823 = 0x2820
PIC12F1822  = 0x2700
PIC12LF1822 = 0x2800
PIC16F1824  = 0x2740
PIC16LF1824 = 0x2840
PIC16F1825  = 0x2760
PIC16LF1825 = 0x2860
PIC16F1828  = 0x27C0
PIC16LF1828 = 0x28C0
PIC16F1829  = 0x27E0
PIC16LF1829 = 0x28E0
PIC16F876   = 0x09E0




# command definition
C_LOAD_CONFIG = 0
C_LOAD_PROGRAM = 2 
C_LOAD_DATA   =  3
C_READ_PROGRAM = 4
C_READ_DATA    = 5
C_INC_ADDRESS = 6
C_RESET_ADDRESS = 0x16
C_BEGIN_INT_PROG = 8
C_BEGIN_EXT_PROG = 0x18
C_END_EXT_PROG = 0xa
C_BULK_ERASE_PROGRAM = 9
C_BULK_ERASE_DATA = 0xB

def Release_VPP():
   GPIO.setup(PIC_DATA, GPIO.IN)
   GPIO.setup(PIC_CLK,  GPIO.IN)
   GPIO.output(PIC_MCLR, False)
   print "VPP OFF"


def Set_VPP():
   print "VPP OFF"
   #held MCLR Low
   GPIO.setup(PIC_MCLR,GPIO.OUT)
   GPIO.output(PIC_MCLR,False)
   sleep(0.1)
   #ok PIC_CLK=out& HIGH, PIC_DATA=out & LOW
   GPIO.setup(PIC_CLK, GPIO.OUT)
   GPIO.output(PIC_CLK,False)
 
   #MCLR LOW 
   GPIO.setup(PIC_DATA, GPIO.OUT)
   GPIO.output(PIC_DATA,False)
   print "VPP ON"
   GPIO.output(PIC_MCLR,True)
   sleep(0.1)

def Set_LVP():
   #held MCLR HIGH
   GPIO.setup(PIC_MCLR,GPIO.OUT)
   GPIO.output(PIC_MCLR,True)
   sleep(0.1)
   #ok PIC_CLK=out& HIGH, PIC_DATA=out & LOW
   GPIO.setup(PIC_CLK, GPIO.OUT)
   GPIO.output(PIC_CLK,False)

   #MCLR LOW 
   GPIO.setup(PIC_DATA, GPIO.OUT)
   GPIO.output(PIC_DATA,False)
   print "LVP ON"
   GPIO.output(PIC_MCLR,False)
   sleep(0.3)

def Release_LVP():
   GPIO.setup(PIC_DATA,GPIO.IN)
   GPIO.setup(PIC_CLK,GPIO.IN)
   GPIO.output(PIC_MCLR,True)
   print "LVP OFF"

def SendMagic():
   magic = 0x4d434850
   GPIO.setup(PIC_DATA, GPIO.OUT)
   for loop in range(33):
      GPIO.output(PIC_CLK,True)
      GPIO.output(PIC_DATA,(magic & 1) == 1)
#  use pass like a delay
      pass
      GPIO.output(PIC_CLK,False)
      pass
      magic = magic >> 1


def SendCommand(Command):
   GPIO.setup(PIC_DATA, GPIO.OUT)
   for loop in range(6):
     GPIO.output(PIC_CLK,True)
     GPIO.output(PIC_DATA,(Command & 1)==1)
     pass
     GPIO.output(PIC_CLK,False)
     pass
     Command = Command >> 1;


def ReadWord():
    GPIO.setup(PIC_DATA,GPIO.IN)
    Value = 0
    for loop in range(16):
      GPIO.output(PIC_CLK,True)
      pass
      if GPIO.input(PIC_DATA):
        Value =  Value + (1 << loop)
      GPIO.output(PIC_CLK,False)
      pass
    Value = (Value >> 1) & 0x3FFF;
    return Value;
        

def LoadWord(Value):
  GPIO.setup(PIC_DATA,GPIO.OUT)
  Value = (Value << 1) & 0x7FFE
  for loop in range(16):
     GPIO.output(PIC_CLK,True)
     GPIO.output(PIC_DATA,(Value & 1)==1)
     pass
     GPIO.output(PIC_CLK,False)
     pass
     Value = Value >> 1;



def Pic12_BulkErase():
   print "Bulk Erase Program",
   SendCommand(C_RESET_ADDRESS)
   SendCommand(C_LOAD_CONFIG)
   LoadWord(0x3fff)
   SendCommand(C_BULK_ERASE_PROGRAM)
   sleep(0.1)
   print ", Data.",
   SendCommand(C_BULK_ERASE_DATA)
   sleep(0.1)
   print ".... done."


def Pic12_ProgramBlankCheck(program_size):
   print "Program blank check",
   SendCommand(C_RESET_ADDRESS)
   for l in range(program_size):
     SendCommand(C_READ_PROGRAM)
     Value = ReadWord()
     if  Value != 0x3fff :
       print "*** CPU program at Address ", hex(l), " = ", hex(Value), " Failed!"
       return False
     if (l % 128)==0 :
       sys.stdout.write('.')
       sys.stdout.flush()
     SendCommand(C_INC_ADDRESS)
   print "Passed!"
   return True

def Pic12_DataBlankCheck(data_size):
   print "Data Blank check",
   SendCommand(C_RESET_ADDRESS)
   for l in range(data_size):
     SendCommand(C_READ_DATA)
     Value = ReadWord()
     if  Value != 0xff :
        print "*** CPU eeprom data  at Address ", hex(l), " = ", hex(Value), "Failed!"
        return False
     if (l % 32)==0 :
       sys.stdout.write('.')
       sys.stdout.flush()
     SendCommand(C_INC_ADDRESS)
   print "Passed!"
   return True


def Pic12_ProgramBurn(pic_data, program_base, program_size):
   print "Writing Program",
   SendCommand(C_RESET_ADDRESS)
   for l in range( program_size):
      if pic_data.get(l*2+ program_base) != None :
        if pic_data.get(l*2+ program_base+1) != None :
          Value = pic_data.get(l*2+ program_base) + ( 256 * pic_data.get(l*2+ program_base+1))
          Value = Value & 0x3fff
          SendCommand(C_LOAD_PROGRAM)
          LoadWord(Value)
          SendCommand(C_BEGIN_INT_PROG)
          sleep(0.005)
          SendCommand(C_READ_PROGRAM)
          RValue = ReadWord()
          if Value != RValue :
            print "Program address:", hex(l) , " write ", hex(Value), " read ", hex(RValue), " Failed!"
            return False
      if (l % 128)==0 :
        sys.stdout.write('.')
        sys.stdout.flush()
      SendCommand(C_INC_ADDRESS)
   print "Done."
   return True

def Pic12_DataBurn(pic_data, data_base, data_size):
   print "Writing Data",
   SendCommand(C_RESET_ADDRESS)
   for l in range( data_size):
     if pic_data.get(l*2 + data_base) != None:
      if pic_data.get(l*2 + data_base+1) != None :
        Value = pic_data.get(l*2 + data_base)
        SendCommand(C_LOAD_DATA)
        LoadWord(Value)
        SendCommand(C_BEGIN_INT_PROG)
        sleep(0.003)
        SendCommand(C_READ_DATA)
        RValue = ReadWord()
        if Value != RValue :
          print "Data address:", hex(l) , " write ", hex(Value), " read ", hex(RValue), " Failed!"
          return False
      if (l % 32)==0 :
        sys.stdout.write('.')
        sys.stdout.flush()
      SendCommand(C_INC_ADDRESS)
   print "Done."
   return True

def Pic12_ProgramCheck(pic_data, program_base, program_size):
   print "Program check ",
   SendCommand(C_RESET_ADDRESS)
   for l in range(program_size):
      if pic_data.get(l*2+ program_base) != None :
        if pic_data.get(l*2+ program_base+1) != None :
          Value = pic_data.get(l*2+ program_base) + ( 256 * pic_data.get(l*2+ program_base+1))
          Value = Value & 0x3fff
	  SendCommand(C_READ_PROGRAM)
          RValue = ReadWord()
          if Value != RValue :
            print "Program address:", hex(l) , " write ", hex(Value), " read ", hex(RValue)
            return False
      if (l % 128)==0 :
        sys.stdout.write('.')
        sys.stdout.flush()
      SendCommand(C_INC_ADDRESS)
   print "Passed!"
   return True



def Pic12_DataCheck(pic_data, data_base, data_size):
   print "Data check ",
   SendCommand(C_RESET_ADDRESS)
   for l in range(data_size):
     if pic_data.get(l*2 + data_base) != None:
      if pic_data.get(l*2 + data_base+1) != None :
        Value = pic_data.get(l*2+data_base)
        SendCommand(C_READ_DATA)
        RValue = ReadWord()
        if Value != RValue :
           print "Data address:", hex(l) , " write ", hex(Value), " read ", hex(RValue)
           return False
      if (l % 32)==0 :
        sys.stdout.write('.')
        sys.stdout.flush()
      SendCommand(C_INC_ADDRESS)
   print "Passed!"
   return True


def Pic12_ConfigBurn(pic_data, config_base):
   print "Writing Config",
   SendCommand(C_RESET_ADDRESS)
   SendCommand(C_LOAD_CONFIG)
   LoadWord(0x3fff)
   #user id first
   for l in range(4):
      if pic_data.get(l*2+ config_base) != None :
        if pic_data.get(l*2+ config_base+1) != None :
          Value = pic_data.get(l*2+ config_base) + ( 256 * pic_data.get(l*2+ config_base+1))
          Value = Value & 0x3fff
          SendCommand(C_LOAD_PROGRAM)
          LoadWord(Value)
          SendCommand(C_BEGIN_INT_PROG)
          sleep(0.005)
          SendCommand(C_READ_PROGRAM)
          RValue = ReadWord()
          if Value != RValue :
            print "User Id Location:", hex(l) , " write ", hex(Value), " read ", hex(RValue), " Failed!"
            return False
        sys.stdout.write('.')
        sys.stdout.flush()
      SendCommand(C_INC_ADDRESS)
   #ok we are at 08004
   #skip 0x8004 .. 0x8006
   SendCommand(C_INC_ADDRESS)
   SendCommand(C_INC_ADDRESS)
   SendCommand(C_INC_ADDRESS)
   # now the configuration word 1& 2  at 0x8007 ( hex file at 0x1000E)
   for l in range(7,9):
      if pic_data.get(l*2+ config_base) != None :
        if pic_data.get(l*2+ config_base+1) != None :
          Value = pic_data.get(l*2+ config_base) + ( 256 * pic_data.get(l*2+ config_base+1))
          Value = Value & 0x3fff
          SendCommand(C_LOAD_PROGRAM)
          if l is 8:
            #catch21 force LVP programming to be always ON
            Value = Value | 0x2000
          LoadWord(Value)
          SendCommand(C_BEGIN_INT_PROG)
          sleep(0.005)
          SendCommand(C_READ_PROGRAM)
          RValue = ReadWord()
          if Value != RValue :
            print "Config Word ", l-6 , " write ", hex(Value), " read ", hex(RValue), " Failed!"
            return False
        sys.stdout.write('.')
        sys.stdout.flush()
      SendCommand(C_INC_ADDRESS)
   print "Done."
   return True

def Pic12_ConfigCheck(pic_data, config_base):
   print "Config Check",
   SendCommand(C_RESET_ADDRESS)
   SendCommand(C_LOAD_CONFIG)
   LoadWord(0x3fff)
   #user id first
   for l in range(4):
      if pic_data.get(l*2+ config_base) != None :
        if pic_data.get(l*2+ config_base+1) != None :
          Value = pic_data.get(l*2+ config_base) + ( 256 * pic_data.get(l*2+ config_base+1))
          Value = Value & 0x3fff 
          SendCommand(C_READ_PROGRAM)
          RValue = ReadWord()
          if Value != RValue :
            print "User Id Location:", hex(l) , " write ", hex(Value), " read ", hex(RValue), " Failed!"
            return False
        sys.stdout.write('.')
        sys.stdout.flush()
      SendCommand(C_INC_ADDRESS)
   #ok we are at 08004
   #skip 0x8004 .. 0x8006
   SendCommand(C_INC_ADDRESS)
   SendCommand(C_INC_ADDRESS)
   SendCommand(C_INC_ADDRESS)
   # now the configuration word 1& 2  at 0x8007 ( hex file at 0x1000E)
   for l in range(7,9):
      if pic_data.get(l*2+ config_base) != None :
        if pic_data.get(l*2+ config_base+1) != None :
          Value = pic_data.get(l*2+ config_base) + ( 256 * pic_data.get(l*2+ config_base+1))
          Value = Value & 0x3fff
          if l is 8:
            #catch21 force LVP programming to be always ON
            Value = Value | 0x2000
          SendCommand(C_READ_PROGRAM)
          RValue = ReadWord()
          if Value != RValue :
            print "Config Word ", l-6 , " write ", hex(Value), " read ", hex(RValue), " Failed!"
            return False
        sys.stdout.write('.')
        sys.stdout.flush()
      SendCommand(C_INC_ADDRESS)
   print "Passed!"
   return True


#just check if the user forget to set LVP flag enable
#if not just give a warning since we force LVP enable

def Pic12_CheckLVP(pic_data, config_base):
  #specify config word2
  l=8 
  if pic_data.get(l*2+ config_base) != None :
    if pic_data.get(l*2+ config_base+1) != None :
      Value = pic_data.get(l*2+ config_base) + ( 256 * pic_data.get(l*2+ config_base+1))
      Value = Value & 0x3fff
      return((Value & 0x2000)== 0x2000)
  return True
   

#============ MAIN ==============

if __name__ == '__main__':
  if len(sys.argv) is 2:
    HexFile = sys.argv[1]
  elif len(sys.argv) is 1:
    HexFile = ''
  else:
    print 'Usage: %s file.hex' % sys.argv[0]
    quit()


## load hex file if it exist
FileData =  IntelHex()
if len(HexFile) > 0 :
   try:
     FileData.loadhex(HexFile)
   except IOError:
     print 'Error in file "', HexFile, '"'
     quit()

PicData = FileData.todict()       
print 'File "', HexFile, '" loaded'
#set GPIO MODE

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)



GPIO.setup(PIC_MCLR,GPIO.OUT)
GPIO.setup(PIC_CLK,GPIO.IN)
GPIO.setup(PIC_DATA,GPIO.IN)


#enter Program Mode

Set_VPP()
#sleep(0.1)
#get cpu id
#Set_LVP()
#SendMagic()
SendCommand(0)
LoadWord(0x3fff)
for l in range(6):
   SendCommand(C_INC_ADDRESS)
SendCommand(C_READ_PROGRAM)
CpuId  = ReadWord()
CpuRevision = CpuId & 0x1f
CpuId = CpuId & 0x3FE0

#define default Program and EEPROM data size
ProgramSize = 0
DataSize    = 256
ProgramBase = 0
DataBase    = 0x1e000
ConfigBase  = 0x10000


print "Cpu :", hex(CpuId), " :",
if CpuId == PIC12F1840:
   print "PIC12F1840",
   ProgramSize = 4096
   DataSize    = 256 
elif CpuId == PIC16F1847:
   print "PIC16F1847",
   ProgramSize = 8192
   DataSize    = 256
elif CpuId == PIC16LF1847:
   print "PIC16LF1847",
   ProgramSize = 8192
   DataSize    = 256
elif CpuId == PIC12LF1840:
   print "PIC12LF1840",
   ProgramSize = 4096
   DataSize    = 256
elif CpuId == PIC16F1826:
   print "PIC16F1826",
   ProgramSize = 2048
elif CpuId == PIC16F1827:
   print "PIC16F1827",
   ProgramSize = 4096
elif CpuId == PIC16LF1826:
   print "PIC16LF1826",
   ProgramSize = 2048
elif CpuId == PIC16LF1827:
   print "PIC16LF1827",
   ProgramSize = 4096
elif CpuId == PIC16F1823:
   print "PIC16F1823",
   ProgramSize = 2048
elif CpuId == PIC16LF1823:
   print "PIC16LF1823",
   ProgramSize = 2048
elif CpuId == PIC12F1822:
   print "PIC16F1822",
   ProgramSize = 2048
elif CpuId == PIC12LF1822:
   print "PIC16LF1822",
   ProgramSize = 2048
elif CpuId == PIC16F1824:
   print "PIC16F1824",
   ProgramSize = 4096
elif CpuId == PIC16LF1824:
   print "PIC16LF1824",
   ProgramSize = 4096
elif CpuId == PIC16F1825:
   print "PIC16F1825",
   ProgramSize = 8192
elif CpuId == PIC16LF1825:
   print "PIC16LF1825",
   ProgramSize = 8192
elif CpuId == PIC16F1828:
   print "PIC16F1828",
   ProgramSize = 4095
elif CpuId == PIC16LF1828:
   print "PIC16LF1828",
   ProgramSize = 4095
elif CpuId == PIC16F1829:
   print "PIC16F1829",
   ProgramSize = 8192
elif CpuId == PIC16LF1829:
   print "PIC16LF1829",
   ProgramSize = 8192
elif CpuId == PIC16F876:
   print "PIC16F876",
   ProgramSize = 8192
   
else:
   print "Invalid"
   Release_VPP()
#   Release_LVP()
   quit()
print "Revision ", hex(CpuRevision)

print "ProgramSize =", hex(ProgramSize)
print "DataSize    =", hex(DataSize)


#if(CpuId == PIC12F1840 or CpuId == PIC12LF1840 or CpuId == PIC16F1847 or CpuId == PIC16LF1847):
if ProgramSize > 0 : 
  Pic12_BulkErase()
  if Pic12_ProgramBlankCheck(ProgramSize):
    if Pic12_DataBlankCheck(DataSize):
      if Pic12_ProgramBurn(PicData,ProgramBase,ProgramSize):
        if Pic12_ProgramCheck(PicData,ProgramBase,ProgramSize):
          if Pic12_DataBurn(PicData,DataBase,DataSize):
            if Pic12_DataCheck(PicData,DataBase,DataSize):
              if Pic12_ConfigBurn(PicData,ConfigBase):
                if Pic12_ConfigCheck(PicData,ConfigBase):
                  if not Pic12_CheckLVP(PicData,ConfigBase):
                     print " *** Warning ***   LVP not set in Hex file. LVP was force!"
                  print "No Error.   All Done!"

#elif (cpuid == ???):
# put other cpu type here
# and burning method here

#Release_LVP()   



Return to “Automation, sensing and robotics”