Showing posts with label Microchip PIC mcu. Show all posts
Showing posts with label Microchip PIC mcu. Show all posts
Tuesday, December 14, 2010
N6610 LCD 3D Demo Part II
Instead of drawing only the edges of a polyhedron, this time we draw the faces and 'fill' it with corresponding colors. This demo now uses a dsPIC (16-bit and 40MIPS core) for "faster" and "smoother" graphics in the N6610/N6100 LCD (w/ pcf8833 controller). See "lcd6610.h" for the used pinouts.
[埋込みオブジェクト:http://www.youtube.com/v/3hsGie6RX5k?hl=en&fs=1]
There are several ways of "hidden surface removal". The easiest way, and most appropriate for drawing convex polyhedron is the use of Backface culling. "Backface" will determine whether a surface (e.g. triangular face) is need to be drawn or not.
/-----------------------------------------------------------------------------------/
Draw3D routine:
triangle color-fill routine:
(*another version of using dsPIC hardware multiplier/divider is included in the download)
detect whether a triangle is facing backward.
Complete MPLAB+C30 project (dsPIC33FJ16GS504):
n6610lcd_3D_demo_part2.zip
[埋込みオブジェクト:http://www.youtube.com/v/3hsGie6RX5k?hl=en&fs=1]
There are several ways of "hidden surface removal". The easiest way, and most appropriate for drawing convex polyhedron is the use of Backface culling. "Backface" will determine whether a surface (e.g. triangular face) is need to be drawn or not.
/-----------------------------------------------------------------------------------/
Draw3D routine:
triangle color-fill routine:
(*another version of using dsPIC hardware multiplier/divider is included in the download)
detect whether a triangle is facing backward.
Complete MPLAB+C30 project (dsPIC33FJ16GS504):
n6610lcd_3D_demo_part2.zip
Wednesday, December 8, 2010
N6610 LCD 3D Demo
Nokia 6610/6100 LCD 3D projections demo using Microchip's PIC18F25J11.
PIC18F25J11 is clocked at 12MHz external oscillator with 4xPLL enabled.
It's operated at 3.3V supply, same with the LCD (and so, direct connections and higher spi clock rates are possible).
[埋込みオブジェクト:http://www.youtube.com/v/IrXP0mtwpbo?hl=en&fs=1]
The demo is all about simple 3D projection - no rendering, no raycasting, etc., just the plotting of edges/lines. It displays common polyhedrons like tetrahedron, hexahedron(cube), octahedron, square pyramid, and triangular prism.
"3Ddemo.c"
*based on original sources:
Nokia 6100 LCD with CCS C
3D Vector objects in C using the PIC micro
Microchip C18 project: n6610lcd_3D_demo.zip
[埋込みオブジェクト:http://www.youtube.com/v/IrXP0mtwpbo?hl=en&fs=1]
The demo is all about simple 3D projection - no rendering, no raycasting, etc., just the plotting of edges/lines. It displays common polyhedrons like tetrahedron, hexahedron(cube), octahedron, square pyramid, and triangular prism.
"3Ddemo.c"
*based on original sources:
Nokia 6100 LCD with CCS C
3D Vector objects in C using the PIC micro
Microchip C18 project: n6610lcd_3D_demo.zip
Thursday, October 14, 2010
PIC18F USB LC Meter
Inductance and Capacitance Meter using Microchip's PIC18F2550 connected to USB using HID class (Plug-n-Play).
* f1, f2. and f3 are the frequencies defined by the equations stated on Digital LC Meter .
diagram using internal Analog Comparator and Timer Peripherals of PIC18:
download link (HEX and PC app): PIC18F2550_USB-HID_LC-Meter.zip
elab.ph forum link: PIC18F2550 USB LC Meter
# edit (10-20-10)
added "Calibration option" ( same PIC18F firmware )
# edit (08-14-11)
V1.2 -> updated host-side application,
-> should now work both on 32-bit OS and 64-bit OS hosts.
* f1, f2. and f3 are the frequencies defined by the equations stated on Digital LC Meter .
diagram using internal Analog Comparator and Timer Peripherals of PIC18:
schematic with actual values:
*simulation on Proteus 7 is NOT working (particularly the LC oscillator part and internal pull-up on RB0)
download link (HEX and PC app): PIC18F2550_USB-HID_LC-Meter.zip
elab.ph forum link: PIC18F2550 USB LC Meter
# edit (10-20-10)
added "Calibration option" ( same PIC18F firmware )
- reference capacitance range is 1.0nF +/- 5%
- Fosc (20MHz crystal with PLL) frequency range is 48MHz +/- 200ppm
# edit (08-14-11)
V1.2 -> updated host-side application,
-> should now work both on 32-bit OS and 64-bit OS hosts.
Thursday, September 23, 2010
Android Bluetooth Oscilloscope
*This application is tested only with Samsung Galaxy GT-i5700 Spica (rooted Android 2.1 OS, i570EXXJD1 Baseband version).
The transmitter circuit uses Microchip's dsPIC33FJ16GS504 for the analog-to-digital conversion of the input signals on two channels. The processed data on the dsPIC are then transmitted to the phone (for waveform display) via the LMX9838 bluetooth SPP module.
[埋込みオブジェクト:http://www.youtube.com/v/DIDy3PAReXo?fs=1&hl=en_US]
specs/ranges:
- time per division: {5us, 10us, 20us, 50us, 100us, 200us, 500us, 1ms, 2ms, 5ms, 10ms, 20ms, 50ms }
- volt per division: {10mV, 20mV, 50mV, 100mV, 200mV, 500mV, 1V, 2V, GND}
- analog input (depends on external pre-amplifier configuration): {-8V to +8V }
The source codes for the bluetooth communication is based on Bluetooth Chat example from http://developer.android.com. That example contains three java source files. And, I've completely copied the "DeviceListActivity.java", which is used for searching remote bluetooth devices. Then I've modified the "BluetoothChatService.java" to use only the RFCOMM Client functions, and used the well-known UUID "00001101-0000-1000-8000-00805F9B34FB" for the Bluetooth RFCOMM/SPP.
For the plotting of waveforms, I'm using SurfaceView object to draw on its canvas. This tutorial found on www.helloandroid.com helps me a lot for this task: "How to use canvas in your android".
The rest of the job mainly involves porting of my previous Python S60 script to JAVA language. It was too painful on my side, because I had to convert a single script file to multiple java + xml source files! Nonetheless, it was a good experience for me on learning the Android SDK (JAVA programming).
Project source codes for Android and dsPIC (with APK and HEX) :
AndroidBluetoothOscilloscope.zip
Electronicslab.ph forum link : Android Bluetooth Oscilloscope
Here are some interesting projects that are also based on the Bluetooth Chat example:
Bluetooth Controlled Model Car
SPRIME
Special thanks to:
Samdroid Forum for the customized/rooted firmwares for our Spica.
Tipidcp Spica users for sharing their tips and experiences with this android phone.
----------------------------------------------------------------------
#edit (10-15-2010)
Here's now my circuit. Nothing special on it, all are based on existing circuits.
*The dsPIC I have used is most probably NOT the best choice for this project because of the many left unused peripherals (extra pins). But, this is the only part readily available in my bin and it has the fastest ADC (2 x 2MSps) among the chips I have.
*If you prefer to change the input range via the op-amp preamp, the computation is located on the "adc.xmcd" file.
*You can use other SPP bluetooth modules aside from LMX. (accdg to manufacturer, it's already obsolete)
----------------------------------------------------------------------
#edit (9-14-2011)
It's almost a year now, and yet some people are still interested in this project (considered to be obsolete). So I've decided to place the source repository also on Google Code site. You can either Browse or use git to have your own local copy:
git clone https://code.google.com/p/android-bluetooth-oscilloscope/
See also the Changes, if you want also to learn on how to modify the code. I've started the first 'commit' with a simple "hello world" from the SDK project template. And then changes were made until the desired final oscilloscope application is achieved.
Labels:
Android,
instrumentation,
Microchip PIC mcu,
wireless
Saturday, May 22, 2010
PIC18F SD WAV Audio Player
As inspired by Simple SD Audio Player by ChaN, this project uses Microchip's PIC18F2550 to read RIFF WAVE files, and display some file information on the N6610 LCD; And then it will play the audio itself through PIC's PWM with a simple RC filter on the output pin. The hardware actually comes from my previous project, and I just attached a ready-made audio amp (w/ speaker) for the demo.
Schematic:
Due to PIC's peripheral limitations, I only set the PWM frequency to 187.5kHz and not the 250kHz carrier frequency originally used by ChaN, because it's the maximum PWM frequency than can still get an 8-bit resolution of the duty cycles (=48MHz/256). It is also possible to use R-2R ladder in stead of (low-pass) filtering the PWM output since there still enough unused digital output pins for this approach.
On the software part, I wasn't able to make a good data buffering as good as what ChaN did. It's noticeable with WAVE files with higher bit-rates (=SampleRate*NumChannels*BitsPerSample). Nevertheless, it can still support up to 48kHz sampling rate, but with only Mono channel and 8-bits/sample resolution.
demo video:
[埋込みオブジェクト:http://www.youtube.com/v/mRzOwF4bx7c&hl=en_US&fs=1&]
Source code(PICC-18) with and without LCD: PIC18 SD WAV Audio Player
My on-going project: currently porting the code to STM32F103RB for additional features.
Some useful software (shareware) tools:
TextAloud - Text to Speech software
Switch Sound File Converter-multi format audio file converters
Schematic:
Due to PIC's peripheral limitations, I only set the PWM frequency to 187.5kHz and not the 250kHz carrier frequency originally used by ChaN, because it's the maximum PWM frequency than can still get an 8-bit resolution of the duty cycles (=48MHz/256). It is also possible to use R-2R ladder in stead of (low-pass) filtering the PWM output since there still enough unused digital output pins for this approach.
On the software part, I wasn't able to make a good data buffering as good as what ChaN did. It's noticeable with WAVE files with higher bit-rates (=SampleRate*NumChannels*BitsPerSample). Nevertheless, it can still support up to 48kHz sampling rate, but with only Mono channel and 8-bits/sample resolution.
demo video:
[埋込みオブジェクト:http://www.youtube.com/v/mRzOwF4bx7c&hl=en_US&fs=1&]
Source code(PICC-18) with and without LCD: PIC18 SD WAV Audio Player
My on-going project: currently porting the code to STM32F103RB for additional features.
Some useful software (shareware) tools:
TextAloud - Text to Speech software
Switch Sound File Converter-multi format audio file converters
Tuesday, May 11, 2010
PIC SD BMP Reader II
It is similar to my first PIC SD BMP Reader , and almost the same circuit except for the LCD. This time I now use a Nokia 6610 LCD. The LCD is capable of displaying 4096 colors, but for code simplicity I just operate it at 8-bit (256 colors) resolution.
Diagram:
This project is capable of reading bitmap file using common format (24-bit per pixel), with size (width and height) equal to or less than 132 pixels at both side.
demo video:
[埋込みオブジェクト:http://www.youtube.com/v/lrGJ3ZsSoy0&hl=en&fs=1]
Source code + diagram: PIC18 SD BMP Reader 2.rar
similar project at Hack-a-day: How-to: Digital picture frame, 100% DIY
-it uses PIC24FJ64 in stead of pic18f2550
Diagram:
This project is capable of reading bitmap file using common format (24-bit per pixel), with size (width and height) equal to or less than 132 pixels at both side.
demo video:
[埋込みオブジェクト:http://www.youtube.com/v/lrGJ3ZsSoy0&hl=en&fs=1]
Source code + diagram: PIC18 SD BMP Reader 2.rar
similar project at Hack-a-day: How-to: Digital picture frame, 100% DIY
-it uses PIC24FJ64 in stead of pic18f2550
Saturday, May 8, 2010
PIC18 SD BMP Reader
This project uses Microchip's PIC18F2550 and Nokia 3310 LCD to read and display images from BMP files on the SD/MMC cards. Although the display itself is monochrome, it still supports 24-bpp (bits per pixel), 8-bpp, 4-bpp, and 1-bpp (monochrome) Bitmap files (*.BMP) with size of 84x48 pixels. It uses the Petit FAT File System Module by ChaN.
Diagram and simulation:
Actual circuit:
Demo video:
[埋込みオブジェクト:http://www.youtube.com/v/sovl6MoydeA&hl=en&fs=1]
forum link: Petit FAT File System (w/ Proteus ISIS simulation)
Source code(PICC18) + simulation(ISIS) + others: PIC18 SD BMP Reader.rar
references for BMP file format:
Wiki BMP file format
atlc.sourceforge bmp format
MSDN Types of Bitmaps
Diagram and simulation:
Actual circuit:
Demo video:
[埋込みオブジェクト:http://www.youtube.com/v/sovl6MoydeA&hl=en&fs=1]
forum link: Petit FAT File System (w/ Proteus ISIS simulation)
Source code(PICC18) + simulation(ISIS) + others: PIC18 SD BMP Reader.rar
references for BMP file format:
Wiki BMP file format
atlc.sourceforge bmp format
MSDN Types of Bitmaps
Wednesday, January 13, 2010
Nokia LCD Interfacing
Due to their wide availability in the local markets, old Nokia LCDs are the best alternatives for those expensive GLCDs. They can be bought cheaply at many cellphone parts shops (N3310 lcds usually cost only around Php100 each). Interfacing them with microcontrollers can easily be done using serial communication (e.g. SPI protocol).
Nokia 3530/3510i LCD
98x67 pixels , 4096 colors
Nokia 6610/6100 LCD
132x132 pixels, 4096 colors
(good backlights,
but the connector is difficult to use)
Nokia 3310/5110 LCD
84x48 pixels, monochrome
(very common and relatively cheap)
some links for N3310/N5110 LCDs:
Using Nokia 3310 LCD as Display for PIC Projects
Nokia 3310 LCD LPH7779
Nokia 3310 LCD Image Encoder
DIY scope using Z8F0823 and N3310 LCD
Nokia 3530/3510i LCD
98x67 pixels , 4096 colors
Nokia 6610/6100 LCD
132x132 pixels, 4096 colors
(good backlights,
but the connector is difficult to use)
Nokia 3310/5110 LCD
84x48 pixels, monochrome
(very common and relatively cheap)
some links for N3310/N5110 LCDs:
Using Nokia 3310 LCD as Display for PIC Projects
Nokia 3310 LCD LPH7779
Nokia 3310 LCD Image Encoder
DIY scope using Z8F0823 and N3310 LCD
Wednesday, December 16, 2009
Python for PIC MCUs
Python (pseudo) Compiler for PIC12/PIC16 Microcontrollers
It uses pyastra (python assembler translator) and gpasm assembler.
The PyQt GUI has a QScintilla-based editor for easy editing of the python scripts to be compiled.
main.py : (compatible with Portable Eric 4 Python IDE)
Complete Eric4 project : Python for PIC.rar
* already includes pyastra and gpasm
note: Python programming language is really NOT intended for platform/devices with very limited resources, such a microcontroller with a very small memory. For now, C language is still the widely used in microcontroller programming.
forum link: Python Compiler for PIC MCUs
It uses pyastra (python assembler translator) and gpasm assembler.
The PyQt GUI has a QScintilla-based editor for easy editing of the python scripts to be compiled.
main.py : (compatible with Portable Eric 4 Python IDE)
#################################
# Python (pseudo) Compiler for PIC12 and PIC16 devices
# using pyastra and gpasm
# PyQt GUI by yus
#################################
import sys, os
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from PyQt4.Qsci import QsciScintilla, QsciLexerPython
class ScriptEditor(QsciScintilla):
def __init__(self):
QsciScintilla.__init__(self)
self.filename = None
self.filedialog = QFileDialog()
# font
font = QFont()
font.setPointSize(9.5)
# Choose python lexer
lexer = QsciLexerPython()
lexer.setDefaultFont(font)
self.setLexer(lexer)
# Folding visual : we will use boxes
self.setFolding(QsciScintilla.BoxedTreeFoldStyle)
# Braces matching
self.setBraceMatching(QsciScintilla.SloppyBraceMatch)
# Editing line color
self.setCaretLineVisible(True)
self.setCaretLineBackgroundColor(QColor(200, 240, 200))
# line numbers
self.setMarginWidth(0, QFontMetrics(font).width( "00000" ) )
def open(self):
self.filename = self.filedialog.getOpenFileName(None,
'Open Python Script', '.\\',
'python script(*.py);;text file(*.txt);;All files (*)', QString())
try:
f = open(self.filename)
self.setText(f.read())
f.close()
except:
print 'unable to open script.'
def save(self):
if self.filename == None:
self.save_as()
else:
try:
f = open(self.filename, "w")
f.write(str(self.text()))
f.close()
except:
print 'file not save.'
def save_as(self):
self.filename = self.filedialog.getSaveFileName(None,
'Save Python Script', '.\\',
'python script(*.py);;;text file(*.txt);;All files (*)', QString())
if self.filename != None:
self.save()
def get_filename(self):
return self.filename
class AppWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.setWindowTitle('PIC12-PIC16 Python Compiler ( PyQt, PyAsTra and GPASM ) - yus ')
#self.setMinimumSize(700, 320)
#self.move(20, 20)
self.editor = ScriptEditor()
self.open_btn = QPushButton('Open')
self.save_btn = QPushButton('Save As')
self.device_label = QLabel('Select Device:')
self.status_info = QLabel('Select or create a python script first')
self.device_cbox = QComboBox()
self.compile_btn = QPushButton('Compile Script')
self.compile_btn.setEnabled(False) # initially disabled until a script is opened
self.editor_area = QDockWidget('(pic script here)')
self.editor_area.setWidget(self.editor)
self.addDockWidget(Qt.TopDockWidgetArea, self.editor_area)
self.output_info = QTextEdit()
self.output_info.setReadOnly(True) # read only information
self.output_info.setTextColor(Qt.darkBlue)
self.output_info_widget = QDockWidget('Output Information')
self.output_info_widget.setWidget(self.output_info)
self.addDockWidget(Qt.BottomDockWidgetArea, self.output_info_widget)
file_tbar = QToolBar()
file_tbar.addWidget(self.open_btn)
file_tbar.addWidget(self.save_btn)
compile_tbar = QToolBar()
compile_tbar.addWidget(self.device_label)
compile_tbar.addWidget(self.device_cbox)
compile_tbar.addWidget(self.compile_btn)
self.addToolBar(file_tbar)
self.addToolBar(compile_tbar)
self.status = QStatusBar()
self.status.addWidget(QLabel('\t')) # dummy widget
self.status.addWidget(self.status_info, 1)
self.setStatusBar(self.status)
self.update_device_list()
self.connect(self.save_btn, SIGNAL('clicked()'), self.save_script)
self.connect(self.open_btn, SIGNAL('clicked()'), self.open_script)
self.connect(self.compile_btn, SIGNAL('clicked()'), self.compile_script)
def open_script(self):
self.editor.open()
fname = str(self.editor.get_filename())
self.editor_area.setWindowTitle(fname)
if fname != 'None':
self.compile_btn.setEnabled(True)
def save_script(self):
self.editor.save_as()
fname = str(self.editor.get_filename())
self.editor_area.setWindowTitle(fname)
if fname != 'None':
self.compile_btn.setEnabled(True)
def compile_script(self):
self.editor.save() # save changes in the script before compiling
script = str(self.editor.get_filename())
device = str(self.device_cbox.currentText())
# PyAstra (python assymbly translator)
pyastra_command = '.\\pyastra_console.py -p'+device[3:] + ' -S --compile ' + script
msg = ' from pyastra console :\n'
try: # clean/delete previous output files
for ext in ('asm', 'hex', 'lst', 'cod'):
os.remove(script[:-2] + ext)
except:
pass #print 'one or more files not found'
try:
msg += os.popen(pyastra_command).read() # execute pyastra console
self.output_info.setText(msg) #pyastra.py info
except:
self.output_info.append('Error occured while translating the python script')
if msg.find('Program memory usage')>0:
# assemble the generated asm file using gpasm.exe
self.output_info.append('---------------\nExecuting gpasm.exe....')
file_asm = '%s'%self.editor.get_filename()
file_asm = file_asm[:file_asm.find('.py')] + '.asm'
#self.output_info.append( os.popen('.\\gpasm\\gpasm -v').read() ) # show gpasm version
msg = os.popen('.\\gpasm\\gpasm -I .\\gpasm\\header '+file_asm).read()
self.output_info.append(msg)
self.output_info.append('Finished.')
self.status_info.setText('Done')
else:
self.status_info.setText('Please verify the script')
def update_device_list(self):
for root, dirs, files in os.walk('.\\pyastra\\ports\\pic14\\procs'):
for name in files:
device = str(name)
if device[:1]=='1' and device.find('.pyc')<0 and device.find('i')<0:
device = device[:device.find('.')]
self.device_cbox.addItem('pic'+device)
self.device_cbox.setCurrentIndex(127) # initially set to PIC16F876A
if __name__ == '__main__':
app = QApplication(sys.argv)
form = AppWindow()
form.show()
sys.exit(app.exec_())
Complete Eric4 project : Python for PIC.rar
* already includes pyastra and gpasm
note: Python programming language is really NOT intended for platform/devices with very limited resources, such a microcontroller with a very small memory. For now, C language is still the widely used in microcontroller programming.
forum link: Python Compiler for PIC MCUs
Sunday, December 6, 2009
USB-based Oscilloscope (beta)
This is NOT considered as an oscilloscope yet. It's just a preparation of making a real PIC18F USB-based oscilloscope. For my initial testing, I used my PIC18F and PyUSB demo, same hardware and firmware for the 18F2550. The only difference is in the GUI, instead of PyQt QDial, I use PyQwt PlotCurve widget.
the Python script: (compatible with my Portable Eric 4 Python IDE (v2))
Right now, my problem is on the 18F2550 side. I still don't know how to use both the USB and ADC interrupts together. My first modification on PIC's firmware was no success. When I enabled the ADC interrupt routine, the whole program response slows down. I still have to read properly the datasheet(plus application notes), and ask for help of the 'masters'. What I'm currently doing on the code is reading a single byte of ADC value every 200ms (very slow!). From what I've understand, the PIC can (it should) send 64 bytes for every USB interrupt read request. I don't know how fast it is, but it will surely improve the PIC18F USB-based oscilloscope.
the Python script: (compatible with my Portable Eric 4 Python IDE (v2))
#################################
# USB-based oscillpscope (beta)
# using pyUSB and PyQt/PyQwt
#################################
import sys, usb
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.Qwt5 import *
from PyQt4.Qwt5.anynumpy import *
class UsbPic:
def __init__(self, vendor_id, product_id):
busses = usb.busses() # enumerate busses
self.handle = None
for bus in busses:
devices = bus.devices
for dev in devices:
if dev.idVendor==vendor_id and dev.idProduct==product_id: # device matches
self.dev = dev
self.conf = self.dev.configurations[0]
self.intf = self.conf.interfaces[0][0]
self.endpoints = []
for endpoint in self.intf.endpoints:
self.endpoints.append(endpoint)
return
def open(self):
if self.handle:
self.handle = None
try:
self.handle = self.dev.open()
self.handle.detachKernelDriver(0)
self.handle.detachKernelDriver(1)
self.handle.setConfiguration(self.conf)
self.handle.claimInterface(self.intf)
self.handle.setAltInterface(self.intf)
return True
except:
return False
def write(self, ep, buff, timeout = 100):
try:
return self.handle.interruptWrite(ep, buff, timeout) #return bytes written
except:
return 0
def read(self, ep, size, timeout = 100):
try:
return self.handle.interruptRead(ep, size, timeout) # return data read
except:
return []
def getDeviceName(self):
return self.handle.getString(2, 40)
class AmplitudevsTime(QwtPlot):
def __init__(self):
QwtPlot.__init__(self)
self.setTitle("<font size=1 color=darkblue>Potentiometer Position ( 8-bit ADC value )</font>")
self.setCanvasBackground(Qt.black)
#grid
grid = QwtPlotGrid()
#grid.enableXMin(True)
#grid.enableYMin(True)
grid.setMajPen(QPen(Qt.darkGreen, 0, Qt.DotLine))
grid.setMinPen(QPen(Qt.darkGreen, 0 , Qt.DotLine))
grid.attach(self)
# x-axis
self.setAxisTitle(QwtPlot.xBottom, "<font size=1 color=darkred>time (seconds)</font>")
self.timerange = arange(0.0, 60, 0.2) #60 seconds, 200 ms interval
self.amplitudes = zeros(len(self.timerange), Float)
# curve
self.amplitude_plot = QwtPlotCurve('Amplitude')
self.setAxisScale(QwtPlot.yLeft, 0, 255) #amplitude range : 0 to 255
self.setAxisScale(QwtPlot.xBottom, 0, 60) #time range: 0 to 60 seconds
self.amplitude_plot.setPen(QPen(Qt.yellow))
self.amplitude_plot.attach(self)
def updatePlot(self, new_value=0):
# shift amplitude array left and assign new value to z[n-1].
self.amplitudes = concatenate((self.amplitudes[1:], self.amplitudes[:1]), 1)
self.amplitudes[-1] = new_value
self.amplitude_plot.setData(self.timerange, self.amplitudes)
self.replot()
class MyForm(QDialog):
def __init__(self, parent = None):
super(MyForm, self).__init__(parent)
self.setWindowTitle("USB-based Oscilloscope (Beta) - pYUSb + PIC18F2550")
self.setMinimumSize(560, 300)
# create widgets/controls
self.connect_btn = QPushButton('Connect')
self.toggle1_btn = QPushButton('Toggle LED1')
self.toggle2_btn = QPushButton('Toggle LED2')
self.status_label = QLabel('press "Connect" button')
self.update_timer = QTimer()
self.display = AmplitudevsTime()
layout = QGridLayout()
layout.addWidget(self.display, 0, 0, 10, 15)
layout.addWidget(self.toggle1_btn, 2, 15)
layout.addWidget(self.toggle2_btn, 2, 16)
layout.addWidget(self.connect_btn, 7, 15)
layout.addWidget(self.status_label, 4, 15, 2, 2)
self.setLayout(layout)
# widgets initial condition
self.toggle1_btn.setEnabled(False)
self.toggle2_btn.setEnabled(False)
# signals
self.connect(self.connect_btn, SIGNAL("clicked()"), self.DeviceConnect)
self.connect(self.toggle1_btn, SIGNAL("clicked()"), self.toggleLED1)
self.connect(self.toggle2_btn, SIGNAL("clicked()"), self.toggleLED2)
self.connect(self.update_timer, SIGNAL("timeout()"), self.updateDisplay)
def DeviceConnect(self):
self.device = UsbPic(0x04d8, 0x0204) # Microchip Vendor ID and Product ID
if self.device.open():
self.toggle1_btn.setEnabled(True)
self.toggle2_btn.setEnabled(True)
self.update_timer.start(200) # update every 200ms
self.status_label.setText('Connected to:\n %s' %self.device.getDeviceName())
else:
self.toggle1_btn.setEnabled(False)
self.toggle2_btn.setEnabled(False)
self.update_timer.stop()
self.status_label.setText('Warning:\n No Device Found!')
def toggleLED1(self):
self.device.write(1, [0x80], 1000)
def toggleLED2(self):
self.device.write(1, [0x82], 1000)
def updateDisplay(self):
self.device.write(1, [0x81])
byteread = self.device.read(0x81, 64)
if len(byteread)>1:
self.display.updatePlot(byteread[1])
if __name__ == "__main__":
app = QApplication(sys.argv)
form = MyForm()
form.show()
sys.exit(app.exec_())
Right now, my problem is on the 18F2550 side. I still don't know how to use both the USB and ADC interrupts together. My first modification on PIC's firmware was no success. When I enabled the ADC interrupt routine, the whole program response slows down. I still have to read properly the datasheet(plus application notes), and ask for help of the 'masters'. What I'm currently doing on the code is reading a single byte of ADC value every 200ms (very slow!). From what I've understand, the PIC can (it should) send 64 bytes for every USB interrupt read request. I don't know how fast it is, but it will surely improve the PIC18F USB-based oscilloscope.
Labels:
instrumentation,
Microchip PIC mcu,
PC programming,
USB
Saturday, November 21, 2009
PIC18F and PyUSB
I finally got a clearer idea on how to use the PyUSB libray. PyUSB is simply a python binding/wrapper for libusb. There are only few examples of python scripts I found on the net regarding the use of PyUSB. Also, the documentation for PyUSB is not that comprehensive yet.
On the USB device side, fortunately, Microchip has provide a LibUSB example for their PICDEM Full Speed USB demo board. Aside from the firmware for the PIC18F4550 family (includes PIC18F2550), they also provided a simple demo (Windows) application (with source codes for MSVC++ and Qt). It's a good opportunity to study LibUSB library along its generic usb device driver.
After some trial&errors on my python script, I finally made my PyQt GUI program working. (Most of my mistakes on the PyUSB module usage were the incorrect types of arguments used in the pyusb functions).
Below is my proto circuit. Basically it's the same circuit I used in my PIC18F2550 USB HID Mouse project. I only added two LEDs on RB0 and RB1 pins of pic18f2550. I also included a 10k potentiometer on RA0 pin (ADC ANA0).
I made a minimal modification on the LibUSB example firmware by Microchip so that it will be compatible with PyUSB demo python script:
then, the generated hex code for PIC18F2550 device using C18 compiler:
here's my python script for PyUSB (also uses PyQt for the GUI):
And finally, the actual circuit in action:
[フレーム]
additional useful links:
Microchip USB Framework for PIC18, PIC24 & PIC32
LibUSB Win32
On the USB device side, fortunately, Microchip has provide a LibUSB example for their PICDEM Full Speed USB demo board. Aside from the firmware for the PIC18F4550 family (includes PIC18F2550), they also provided a simple demo (Windows) application (with source codes for MSVC++ and Qt). It's a good opportunity to study LibUSB library along its generic usb device driver.
After some trial&errors on my python script, I finally made my PyQt GUI program working. (Most of my mistakes on the PyUSB module usage were the incorrect types of arguments used in the pyusb functions).
Below is my proto circuit. Basically it's the same circuit I used in my PIC18F2550 USB HID Mouse project. I only added two LEDs on RB0 and RB1 pins of pic18f2550. I also included a 10k potentiometer on RA0 pin (ADC ANA0).
I made a minimal modification on the LibUSB example firmware by Microchip so that it will be compatible with PyUSB demo python script:
/*
Filename: main.c
*/
/** INCLUDES *********************/
#include "Compiler.h"
#include "HardwareProfile.h"
#include "GenericTypeDefs.h"
#include "USB/usb_device.h"
#include "USB/usb.h"
#include "USB/usb_function_generic.h"
#include "usb_config.h"
/** CONFIGURATION ****************/
#pragma config PLLDIV = 5 // (20 MHz crystal on PICDEM FS USB board)
#pragma config CPUDIV = OSC1_PLL2
#pragma config USBDIV = 2 // Clock source from 96MHz PLL/2
#pragma config FOSC = HSPLL_HS
#pragma config FCMEN = OFF
#pragma config IESO = OFF
#pragma config PWRT = OFF
#pragma config BOR = ON
#pragma config BORV = 3
#pragma config VREGEN = ON //USB Voltage Regulator
#pragma config WDT = OFF
#pragma config MCLRE = ON
#pragma config LPT1OSC = OFF
#pragma config PBADEN = OFF
#pragma config STVREN = ON
#pragma config LVP = OFF
#pragma config XINST = OFF // Extended Instruction Set
#pragma config CP0 = OFF
#pragma config CP1 = OFF
#pragma config CPB = OFF
#pragma config WRT0 = OFF
#pragma config WRT1 = OFF
#pragma config WRTB = OFF // Boot Block Write Protection
#pragma config WRTC = OFF
#pragma config EBTR0 = OFF
#pragma config EBTR1 = OFF
#pragma config EBTRB = OFF
/** VARIABLES ******************************************************/
#pragma udata USB_VARIABLES=0x500
unsigned char OUTPacket[64]; //User application buffer for receiving and holding OUT packets sent from the host
unsigned char INPacket[64]; //User application buffer for sending IN packets to the host
#pragma udata
USB_HANDLE USBGenericOutHandle;
USB_HANDLE USBGenericInHandle;
#pragma udata
/** PRIVATE PROTOTYPES *********************************************/
static void InitializeSystem(void);
void USBDeviceTasks(void);
void YourHighPriorityISRCode(void);
void YourLowPriorityISRCode(void);
void ProcessIO(void);
/** VECTOR REMAPPING ***********************************************/
#define REMAPPED_RESET_VECTOR_ADDRESS 0x00
#define REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS 0x08
#define REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS 0x18
#pragma code REMAPPED_HIGH_INTERRUPT_VECTOR = REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS
void Remapped_High_ISR (void)
{
_asm goto YourHighPriorityISRCode _endasm
}
#pragma code REMAPPED_LOW_INTERRUPT_VECTOR = REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS
void Remapped_Low_ISR (void)
{
_asm goto YourLowPriorityISRCode _endasm
}
#pragma code
//These are your actual interrupt handling routines.
#pragma interrupt YourHighPriorityISRCode
void YourHighPriorityISRCode()
{
USBDeviceTasks();
} //This return will be a "retfie fast", since this is in a #pragma interrupt section
#pragma interruptlow YourLowPriorityISRCode
void YourLowPriorityISRCode()
{
}
/** DECLARATIONS ***************************************************/
#pragma code
//////////////////////////////////////////////////////////////////////
void main(void)
{
InitializeSystem();
USBDeviceAttach();
while(1)
{
ProcessIO();
}
}
static void InitializeSystem(void)
{
ADCON1 |= 0x0F; // Default all pins to digital
USBGenericOutHandle = 0;
USBGenericInHandle = 0;
InitLEDs();
InitPot();
USBDeviceInit(); //usb_device.c. Initializes USB module SFRs and firmware variables to known states.
}
////////////////////////////////////////////////////////////
void ProcessIO(void)
{
if((USBDeviceState < CONFIGURED_STATE)||(USBSuspendControl==1)) return;
if(!USBHandleBusy(USBGenericOutHandle)) //Check if the endpoint has received any data from the host.
{
switch(OUTPacket[0]) //Data arrived, check what kind of command might be in the packet of data.
{
case 0x80: // toggle LED1 (command from PC application)
LED1 = !LED1;
break;
case 0x82: // toggle LED2
LED2 = !LED2;
break;
case 0x81: //Get potentiometer position
adc_status = 1; // start a/d conversion
INPacket[0] = 0x81;
while(adc_status); // wait for the a/d conversion to complete (or use interrupt)
INPacket[1] = ADRESH; //read only 8-bit adc value (left justified)
if(!USBHandleBusy(USBGenericInHandle))
USBGenericInHandle = USBGenWrite(USBGEN_EP_NUM,(BYTE*)&INPacket,USBGEN_EP_SIZE);
break;
}
USBGenericOutHandle = USBGenRead(USBGEN_EP_NUM,(BYTE*)&OUTPacket,USBGEN_EP_SIZE);
}
}//end ProcessIO
/*********** USB Callback Functions ****************/
void USBCBSuspend(void)
{
}
void USBCBWakeFromSuspend(void)
{
}
void USBCB_SOF_Handler(void)
{
}
void USBCBErrorHandler(void)
{
}
void USBCBCheckOtherReq(void)
{
}
void USBCBStdSetDscHandler(void)
{
}
void USBCBInitEP(void)
{
USBEnableEndpoint(USBGEN_EP_NUM,USB_OUT_ENABLED|USB_IN_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
USBGenericOutHandle = USBGenRead(USBGEN_EP_NUM,(BYTE*)&OUTPacket,USBGEN_EP_SIZE);
}
void USBCBSendResume(void)
{
static WORD delay_count;
USBResumeControl = 1; // Start RESUME signaling
delay_count = 1800U; // Set RESUME line for 1-13 ms
do{
delay_count--;
}while(delay_count);
USBResumeControl = 0;
}
BOOL USER_USB_CALLBACK_EVENT_HANDLER(USB_EVENT event, void *pdata, WORD size)
{
switch(event)
{
case EVENT_CONFIGURED:
USBCBInitEP();
break;
case EVENT_SET_DESCRIPTOR:
USBCBStdSetDscHandler();
break;
case EVENT_EP0_REQUEST:
USBCBCheckOtherReq();
break;
case EVENT_SOF:
USBCB_SOF_Handler();
break;
case EVENT_SUSPEND:
USBCBSuspend();
break;
case EVENT_RESUME:
USBCBWakeFromSuspend();
break;
case EVENT_BUS_ERROR:
USBCBErrorHandler();
break;
case EVENT_TRANSFER:
Nop();
break;
default:
break;
}
return TRUE;
}
then, the generated hex code for PIC18F2550 device using C18 compiler:
:020000040000FA
:060000008AEF0AF0120075
:0600080073EF08F0120086
:06001800BEEF08F012002B
:02002A000000D4
:04002C00D9CFE6FF43
:10003000E1CFD9FFE6526A6A686A160E6F6E9F0EAC
:100040006B6E7B0E696E6D8C6E6A000EE66EE66AF4
:10005000E66A710EE66E0F0EE66E70EC0AF00B6E3D
:10006000050EE15E0B506D9CDF6ADF500B6E0C6A73
:10007000080E0B5C000E0C5810E2DF50040DF3CF9D
:10008000E9FFF4CFEAFF000EE926040EEA22EE6A49
:10009000EE6AEE6AEE6ADF2AE8D7160E706E68A680
:1000A0000CD0030EE66E680EE66E0F0EE66E39ECAF
:1000B00008F0E552E552E552F2D70001736B786B18
:1000C000796B7A6B6D98080E6B6F040E6C6F616BB9
:1000D000606BE552E552E7CFD9FF1200D9CFE6FFBA
:1000E000E1CFD9FFE6520001600507E16DBA05D006
:1000F000686A69806988020E606F6850040B0FE0BF
:100100006950040B0CE0020EE66E680EE66E0F0EF0
:10011000E66E39EC08F0E552E552E552E9D86DA2F9
:1001200002D0A19AA1D06850010B1BE06950010BCD
:1001300018E07CDF0001040E606F0401200E026FE6
:10014000040E036F080E016F006B8C0E0013E66A3D
:10015000680EE66E0F0EE66E39EC08F0E552E552D9
:10016000E5526850100B0FE06950100B0CE0A4D85A
:10017000040EE66E680EE66E0F0EE66E39EC08F0C1
:10018000E552E552E5526850400B1DE06950400BC6
:100190001AE0010EE66EE66A000EE66EE66A020EF0
:1001A000E66EE66A7DEC09F00B6E060EE15E0B5022
:1001B000060EE66E680EE66E0F0EE66E39EC08F07F
:1001C000E552E552E5526850200B04E06950200BDF
:1001D00001E04FD86850020B12E06950020B0FE0AB
:1001E000010EE66EE66A000EE66EE66AE668E6680E
:1001F0007DEC09F00B6E060EE15E0B506A6A040E90
:100200000001605D02E2A19A2FD069A62CD0DF6ABE
:10021000040EDF5C28E268A625D06CCF80F0030EC8
:10022000E66E680EE66E0F0EE66E39EC08F0E552EB
:10023000E552E552780E0001801502E178D810D021
:10024000000EE66EE66A800EE66E000EE66E010EA9
:10025000E66EE66A7DEC09F00B6E060EE15E0B5071
:10026000DF2AD6D700D0A19AE552E552E7CFD9FFD1
:10027000120070A015D063C0E9FF64C0EAFFEF5020
:1002800080080DE16BC0E9FF6CC0EAFFEF50840805
:1002900006E163C0E9FF64C0EAFF8C0EEF6E709068
:1002A000050EE66E680EE66E0F0EE66E39EC08F08F
:1002B000E552E552E55212006984040EE66E680EBE
:1002C000E66E0F0EE66E39EC08F0E552E552E552A7
:1002D0006D82000EE66EE66AE66EE66A040EE66E73
:1002E000E66A7DEC09F00B6E060EE15E0B50120023
:1002F000000EE66EE66AE66EE66A030EE66EE66AF3
:100300007DEC09F00B6E060EE15E0B506D92699468
:1003100068A40CD0020EE66E680EE66E0F0EE66E56
:1003200039EC08F0E552E552E552F2D71200D9CF88
:10033000E6FFE1CFD9FFE652FD0E000180155AE13C
:100340007E0E8015E8407F0B040DF3CF63F0F4CFF1
:1003500064F0000E6327040E642363C065F064C07C
:1003600066F0657563C0E9FF64C0EAFFEF503C0BBF
:10037000E842E8420D083CE163C0E9FF64C0EAFFDF
:10038000020EE926000EEA22EECF0BF0EFCF0CF0C2
:10039000280E0B1802E1040E0C1828E163C0E9FFD7
:1003A00064C0EAFF020EE926000EEA22200EEE6E7D
:1003B000040EED6EDF6ADF500B6E0C6A080E0B5CEC
:1003C000000E0C5813E2DF50EA6A280FE96E040EA3
:1003D000EA22EF50E66EDF50EA6A200FE96E040E63
:1003E000EA22E552E750EF6EDF2AE5D70DD801D0BB
:1003F0002ED805D0FD0E8015040801E14ED8E55237
:10040000E552E7CFD9FF12006BC0E9FF6CC0EAFFED
:10041000EF50800B05E06BC0E9FF6CC0EAFFEF6AAC
:1004200000016F6B706B746B756B736BB6D8000EDD
:10043000E66EE66AE66EE66A170EE66EE66A7DEC42
:1004400009F00B6E060EE15E0B5079EF04F0020E20
:100450000001705D02E1ADDB1FD06CD8000181515D
:100460001AE165C0E9FF66C0EAFFEE52080EEF6EC2
:1004700065C0E9FF66C0EAFF020EE926000EEA2227
:10048000200EEE6E040EED6E65C0E9FF66C0EAFF59
:100490008C0EEF6E01D0816B1200D9CFE6FFE1CF59
:1004A000D9FFE6526BC0E9FF6CC0EAFFEF50400B8A
:1004B00001E0010EDF6E00016B75080E605D0AE160
:1004C00022C46EFF6E50000803E2100E606F02D06F
:1004D000040E606F700528E16BC0E9FF6CC0EAFF95
:1004E000020EE926000EEA22280EEE6E040EED6ED4
:1004F000D5DA020E00016F5D07E16BC0E9FF6CC049
:10050000EAFF840EEF6E0FD0DF5007E16BC0E9FF0A
:100510006CC0EAFFC80EEF6E06D06BC0E9FF6CC07E
:10052000EAFF880EEF6E01D005D8E552E552E7CF1D
:10053000D9FF1200D9CFE6FFE1CFD9FF020EE126A5
:100540000001706B6BC0E9FF6CC0EAFFEF6A040E3C
:100550006B190B6E6CC00CF00BC0DEFF0CC0DDFF26
:10056000DECFE9FFDDCFEAFFEF6A78AF0CD07B5139
:100570007C1107E005D07CC0FAFF00017B51F96EC9
:10058000FADF0001789F020EE15C02E2E16AE552C7
:10059000E16EE552E7CFD9FF120004012051600B54
:1005A000E842E842E842E842E842000901E058D067
:1005B00021510C0A54E00B0A43E00C0A35E0010A11
:1005C00026E00B0A22E0020A20E0030A1CE0080AE7
:1005D00010E0010A0CE00F0A08E0030A01E03FD036
:1005E0000001738F080E606F3BD0C8D839D07FDB15
:1005F00037D00001610E716F000E726F7381010EB2
:10060000746F738F2DD014D92BD02BD829D02451AF
:100610000001716F726B620E7127000E722373817D
:10062000010E746F738F1CD00001738F040124516D
:10063000EA6A620FE96E000EEA2222C4EFFF10D0D0
:10064000000EE66EE66AE66EE66A160EE66EE66A8C
:100650007DEC09F00B6E060EE15E0B5001D000D070
:100660001200D9CFE6FFE1CFD9FF040EE126040145
:10067000220510E120511F0B00090CE10001738FCE
:10068000030E0401215D04E10001010E7F6F02D021
:1006900000017F6B0401225167E120511F0B02080A
:1006A00063E124510F0B00095FE00001738F040127
:1006B00024BF10D024510F0BE96EEA6AD890E936B6
:1006C000EA36670EE926000EEA22EECFDEFFEDCF16
:1006D000DDFF0FD024510F0BE96EEA6AD890E9369E
:1006E000EA366B0EE926000EEA22EECFDEFFEDCFF2
:1006F000DDFF030E215D07E1DECFE9FFDDCFEAFF7D
:10070000840EEF6E31D024510F0B0C6A700F0B6EFC
:100710000F0E0C22020E0BC0DBFF030E0CC0DBFF22
:10072000020EDBCFE9FF030EDBCFEAFFEE90ED52C6
:1007300024AF0DD0DECFE9FFDDCFEAFFEF6ADF7433
:10074000DECFE9FFDDCFEAFF400EEF6E0DD0DECF4A
:10075000E9FFDDCFEAFF880EEF6EDF74DECFE9FF41
:10076000DDCFEAFFC80EEF6E040EE15C02E2E16A43
:10077000E552E16EE552E7CFD9FF1200800E040189
:10078000205D55E10001C00E736F04012351030A7F
:100790002EE0010A0EE0030A03E00001736B47D06C
:1007A0000001900E716F130E726F120E746F756BE5
:1007B0003ED02251F66EF76AD890F636F7363A0EEA
:1007C000F626140EF7220900F5CF71F00A00F5CFD6
:1007D00072F0020E0001F76A7125F66E7251F7226F
:1007E0000900F5CF74F00A00F5CF75F020D0030EA4
:1007F000225D1AE22251F66EF76AD890F636F73685
:100800003C0EF626140EF7220900F5CF71F00A000F
:10081000F5CF72F071C0F6FF72C0F7FF0800F55017
:100820000001746F756B02D00001736B00D0120071
:10083000D9CFE6FFE1CFD9FF020EE1260401286BF4
:10084000296B20511F0B020A12E0030A0DE0010A76
:1008500001E03BD00001738F0401288100017F0576
:1008600002E10401288331D00001738F2ED00001F2
:10087000738F040124BF10D024510F0BE96EEA6A74
:10088000D890E936EA36670EE926000EEA22EECF66
:10089000DEFFEDCFDDFF0FD024510F0BE96EEA6ACA
:1008A000D890E936EA366B0EE926000EEA22EECF42
:1008B000DEFFEDCFDDFFDECFE9FFDDCFEAFFEF505A
:1008C000040B02E0010E286F00D0000173AF07D0C7
:1008D000280E716F040E726F7381020E746F020E18
:1008E000E15C02E2E16AE552E16EE552E7CFD9FF51
:1008F00012006D98000173BF4AD078AF28D0020E65
:10090000706F6BC0E9FF6CC0EAFFEE52EF6A6BC01C
:10091000E9FF6CC0EAFFC80EEF6E65C0E9FF66C074
:10092000EAFFEE52080EEF6E65C0E9FF66C0EAFF0F
:10093000020EE926000EEA22280EEE6E040EED6E7F
:1009400065C0E9FF66C0EAFFC80EEF6E1FD065C044
:10095000E9FF66C0EAFFEE52080EEF6E65C0E9FFE0
:1009600066C0EAFF020EE926000EEA22200EEE6EB5
:10097000040EED6E65C0E9FF66C0EAFF8C0EEF6EF7
:100980006BC0E9FF6CC0EAFF840EEF6E86D078BFC3
:1009900084D0040120AF59D0000174510401265DB8
:1009A000000175510401275904E226C474F027C4DC
:1009B00075F074D80001010E706F65C0E9FF66C064
:1009C000EAFFEE52080EEF6E65C0E9FF66C0EAFF6F
:1009D000020EE926000EEA22200EEE6E040EED6EE7
:1009E00065C0E9FF66C0EAFF800EEF6E816B63C0F1
:1009F000E9FF64C0EAFFEE52080EEF6E63C0E9FF44
:100A000064C0EAFF020EE926000EEA22200EEE6E16
:100A1000040EED6E63C0E9FF64C0EAFF840EEF6E62
:100A2000010E816F6BC0E9FF6CC0EAFF020EE92680
:100A3000000EEA22280EEE6E040EED6E6BC0E9FF8A
:100A40006CC0EAFFC80EEF6E28D00001020E706F76
:100A50006BC0E9FF6CC0EAFFEE52EF6A6BC0E9FFC2
:100A60006CC0EAFFC80EEF6E65C0E9FF66C0EAFF22
:100A7000EE52080EEF6E65C0E9FF66C0EAFF020E97
:100A8000E926000EEA22280EEE6E040EED6E65C019
:100A9000E9FF66C0EAFFC80EEF6E1200D9CFE6FF8D
:100AA000E1CFD9FF020EE1260001080E745D000EB1
:100AB00075590EE274C0DEFF75C0DDFF6F5103E1B2
:100AC000010E6F6F04D06F0502E1020E6F6F03D04D
:100AD000080EDE6EDD6A6BC0E9FF6CC0EAFFEF92C4
:100AE0006BC0E9FF6CC0EAFFEF906BC0E9FF6CC020
:100AF000EAFF010EDB50EF126BC0E9FF6CC0EAFFAA
:100B0000EE52DFCFEFFF000EDB50745F010EDB50C3
:100B1000755B280E7D6F040E7E6F73B121D0D9CF27
:100B2000E9FFDACFEAFFEE50ED1019E071C0F6FFF1
:100B300072C0F7FF712B000E72230800F550E66EAD
:100B40007DC0E9FF7EC0EAFF7D2B000E7E23E552CB
:100B5000E750EF6EDF06010E01E2DB06E0D71FD0A3
:100B6000D9CFE9FFDACFEAFFEE50ED1018E071C0FF
:100B7000E9FF72C0EAFF712B000E7223EF50E66EA0
:100B80007DC0E9FF7EC0EAFF7D2B000E7E23E5528B
:100B9000E750EF6EDF06010E01E2DB06E1D7020E41
:100BA000E15C02E2E16AE552E16EE552E7CFD9FF8E
:100BB0001200D9CFE6FFE1CFD9FF020EE12663C0D4
:100BC000E9FF64C0EAFFEE52EFCFDFFFDFCF0BF0AB
:100BD0000B500001795D000E7A5903E279C0DFFF06
:100BE00009D0DF500B6E0C6A0B50795D796F0C5099
:100BF0007A597A6F010EDB6ADF50F36E010EDBCF9C
:100C0000F4FFF350F45C16E2010EDB50EA6A280FA1
:100C1000E96E040EEA22EF50E66E76C0E9FF77C077
:100C2000EAFF762B000E7723E552E750EF6E010EB8
:100C3000DB2AE2D7000ED8807955000E7A5528E2DB
:100C400065C0E9FF66C0EAFFEE52080EEF6E65C0B0
:100C5000E9FF66C0EAFF020EE926000EEA22280E2E
:100C6000EE6E040EED6E63C0E9FF64C0EAFFEF5064
:100C7000400B07E165C0E9FF66C0EAFFC80EEF6EF2
:100C800006D065C0E9FF66C0EAFF880EEF6E25D08A
:100C900065C0E9FF66C0EAFFEE52080EEF6E65C060
:100CA000E9FF66C0EAFF020EE926000EEA22200EE6
:100CB000EE6E040EED6E65C0E9FF66C0EAFF840EBD
:100CC000EF6E7B517C1107E005D07CC0FAFF00017C
:100CD0007B51F96EFADF0001789F020EE15C02E2BF
:100CE000E16AE552E16EE552E7CFD9FF120000015B
:100CF000738F000EE66EE66AE66A710EE66E0F0E00
:100D0000E66E70EC0AF00B6E050EE15E0B50010E04
:100D1000E66EE66AE66A620EE66E000EE66E70EC5D
:100D20000AF00B6E050EE15E0B5022C461F0040167
:100D3000225104E10001100E606F11D00001200E5D
:100D4000606F000EE66EE66AE66EE66A150EE66E07
:100D5000E66A7DEC09F00B6E060EE15E0B501200A8
:100D6000D9CFE6FFE1CFD9FF020EE126000EDE6EFD
:100D7000040EDD6EFD0EDB50E8240D6EFE0EDB5022
:100D8000040DF3500D24040DF3500B6E0C6A020E8B
:100D90000F0B05E0D8900C320B32E806FBE1D8903F
:100DA0000B360C36D8900B360C36D9CFE9FFDACF9C
:100DB000EAFF0B50EE260C50ED22DECFE9FFDDCF2F
:100DC000EAFFEF9EFD0EDB500FE1FE0EEA6ADB3418
:100DD000FE0BEA36E96E670EE926000EEA22DECF48
:100DE000EEFFDDCFEDFF0ED0FE0EEA6ADB34FE0B28
:100DF000EA36E96E6B0EE926000EEA22DECFEEFF40
:100E0000DDCFEDFFDECFE9FFDDCFEAFFEF9CDECFE8
:100E1000E9FFDDCFEAFF040EE926000EEA22EF8C9F
:100E2000020EE15C02E2E16AE552E16EE552E7CFD3
:100E3000D9FF1200D9CFE6FFE1CFD9FF020EE1269C
:100E4000FE0EDB500C6A700F0B6E0F0E0C220BC0E7
:100E5000DEFF0CC0DDFFDECFE9FFDDCFEAFFFD0ED8
:100E6000DBCFEFFFDBA407D0E66AFE0EDBCFE6FFA9
:100E700077DFE552E552FD0EDBA208D0010EE66EEB
:100E8000FE0EDBCFE6FF6CDFE552E552020EE15CC1
:100E900002E2E16AE552E16EE552E7CFD9FF1200C6
:100EA000D9CFE6FFE1CFD9FF020EE126FE0EDB50DF
:100EB00020E165C0E9FF66C0EAFFEE52080EEF6E62
:100EC00065C0E9FF66C0EAFF020EE926000EEA22CD
:100ED000200EEE6E040EED6E65C0E9FF66C0EAFFFF
:100EE0008C0EEF6E6BC0E9FF6CC0EAFF840EEF6EF4
:100EF0003DD0FD0EDB50E8240D6EFE0EDB50040DE0
:100F0000F3500D24040DF3CF0BF0F4CF0CF0000ED2
:100F10000B26040E0C220BC0DEFF0CC0DDFF840E7E
:100F20000B6EDECFE9FFDDCFEAFF0B50EF12FD0EB7
:100F3000DB50E8240D6EFE0EDB50040DF3500D2443
:100F4000010F040DF3CF0BF0F4CF0CF0000E0B26C5
:100F5000040E0C220BC0DEFF0CC0DDFF840E0B6EF6
:100F6000DECFE9FFDDCFEAFF0B50EF12020EE15CAE
:100F700002E2E16AE552E16EE552E7CFD9FF1200E5
:100F8000D9CFE6FFE1CFD9FF020EE126FD0EDB50FF
:100F90000FE0FE0EEA6ADB34FE0BEA36E96E6B0EFA
:100FA000E926000EEA22EECFDEFFEDCFDDFF0ED008
:100FB000FE0EEA6ADB34FE0BEA36E96E670EE926BE
:100FC000000EEA22EECFDEFFEDCFDDFFDECFE9FF40
:100FD000DDCFEAFF020EE926000EEA22FB0EDBCF90
:100FE000EEFFFC0EDBCFEDFFDECFE9FFDDCFEAFF4A
:100FF000EE52FA0EDBCFEFFF400E0B6EDECFE9FFB5
:10100000DDCFEAFF0B50EF16880E0B6EDECFE9FF47
:10101000DDCFEAFF0B50EF12FD0EDB500CE0FE0EB1
:10102000EA6ADB34FE0BEA36E96E6B0EE926000E47
:10103000EA22EF740BD0FE0EEA6ADB34FE0BEA36CE
:10104000E96E670EE926000EEA22EF74DECF0BF0A0
:10105000DDCF0CF00BC0F3FF0CC0F4FF020EE15C1F
:1010600003E200D0E16AE552E16EE552E7CFD9FF35
:101070001200D9CFE6FFE1CFD9FF010EF36EFC0ECF
:10108000DB5004E0D890F336E806FCE1F350E81CAE
:101090000B6EFD0EDBCFE9FFFE0EDBCFEAFF0B5040
:1010A000EF16E552E7CFD9FF120005D06D6A696AE5
:1010B0000001606B00D012000001605113E16D6A05
:1010C000696A160E6F6E9F0E6B6E7B0E696ED08E08
:1010D000A28AA08AF28E6DB602D06D86FCD700017E
:0610E000010E606F12001A
:0A10E600DACFE4FFE2CFDAFFE9CF32
:1010F000E4FFEACFE4FFF6CFE4FFF7CFE4FFF5CF5C
:10110000E4FFF3CFE4FFF4CFE4FFFACFE4FF00EE17
:1011100000F00B0EE80403E3EECFE4FFFBD700EE94
:101120000BF0030EE80403E3EECFE4FFFBD7E65237
:101130006EEC00F0E55200EE0DF0030EE80403E360
:10114000E5CFEDFFFBD700EE0AF00B0EE80403E35A
:10115000E5CFEDFFFBD7E5CFFAFFE5CFF4FFE5CF15
:10116000F3FFE5CFF5FFE5CFF7FFE5CFF6FFE5CFDE
:10117000EAFFE5CFE9FFE5CFDAFF1100D8CFE4FFC2
:10118000E0CFE4FFE46EDACFE4FFE2CFDAFFE6522D
:10119000E552E5CFDAFFE550E5CFE0FFE5CFD8FF38
:1011A000100005D85CEC08F014D8FED712000F0E22
:1011B000C1120001906B916B926B936BFC0E8A16BF
:1011C000931692800E0EC16EC06E010EC26E16EFA7
:1011D00000F0200E0001605D03E36D50020B01E0A2
:1011E0005BD000019051911102E1000E08D090C037
:1011F000E9FF91C0EAFFEF50800B01E0010E00090A
:101200004BE105010051810A09E0030A05E0020AE9
:1012100001E02FD08A702DD08A722BD0C282810E2D
:10122000406FC2B2FED7C4CF41F500019251931175
:1012300002E1000E08D092C0E9FF93C0EAFFEF5030
:10124000800B01E0010E000913E1400EE66E400E36
:10125000E66E050EE66E010EE66EE66EC0EC07F079
:101260000B6E050EE15E0B50F3CF92F0F4CF93F0CE
:1012700000D0400EE66E000EE66E050EE66EE66AE3
:10128000010EE66EC0EC07F00B6E050EE15E0B5032
:10129000F3CF90F0F4CF91F0120012001200120080
:1012A0001200120012001E0EE66E010EE66E1AEC1F
:1012B00007F0E552E552400EE66E000EE66E050EB2
:1012C000E66EE66A010EE66EC0EC07F00B6E050EE8
:1012D000E15E0B50F3CF90F0F4CF91F012006D84EB
:1012E0000001080E946F070E956F9407000E955B32
:1012F00094519511FAE16D941200D9CFE6FFE1CF38
:10130000D9FFFD0EDBCF06F0FE0EDBCF07F0010E9E
:10131000061801E1075033E0E868061802E1E868C2
:1013200007182BE0030E061801E1075024E0040E15
:10133000061801E107501DE0020E061801E10750F2
:1013400016E0170E061801E107500FE0160E0618FA
:1013500001E1075008E0150E061801E1075001E011
:1013600010D0A1DF0FD09EDF0DD09BDF0BD097DF19
:1013700009D093DF07D092DF05D092DF03D00000C1
:1013800001D000D0010E00D0E552E7CFD9FF120006
:101390001201000200000008D8040402000001024B
:1013A000000109022000010100C03209040000020E
:1013B000FFFFFF0007050102400001070581024011
:1013C00000010403090434034D0069006300720046
:1013D0006F00630068006900700020005400650021
:1013E000630068006E006F006C006F00670079009A
:1013F000200049006E0063002E0040034D0069008C
:10140000630072006F0063006800690070002000D4
:101410004C00690062007500730062002000450006
:10142000780061006D0070006C00650020004400D1
:1014300065007600690063006500A213C213C6133D
:02144000FA139D
:0E1442002A0EF66E000EF76E000EF86E000118
:101450000900F5508B6F0900F5508C6F03E18B6725
:1014600001D03DD00900F550866F0900F550876F17
:101470000900F550886F09000900F550E96E090070
:10148000F550EA6E090009000900F550896F09005E
:10149000F5508A6F09000900F6CF8DF0F7CF8EF076
:1014A000F8CF8FF086C0F6FF87C0F7FF88C0F8FF3F
:1014B0000001895302E18A5307E00900F550EE6EFE
:1014C0008907F8E28A07F9D78DC0F6FF8EC0F7FFCB
:1014D0008FC0F8FF00018B07000E8C5BBFD7120096
:1014E000FE0EE3CFE9FFFF0EE3CFEAFFE9CFF3FF04
:1014F000EACFF4FFFB0EE35003E1FC0EE35009E0FA
:10150000FB0EE30602E2FC0EE306FD0EE350EE6E78
:04151000F1D71200FD
:0C15140013EE00F023EE00F0F86A0A9CD1
:1015200021EC0AF098EC0AF0D1EC08F0FBD712009D
:021530001200A7
:020000040030CA
:0100000024DB
:010001000EF0
:010002003FBE
:010003001EDE
:010005008179
:010006008178
:010008000FE8
:01000900C036
:01000A000FE6
:01000B00E014
:01000C000FE4
:01000D0040B2
:00000001FF
here's my python script for PyUSB (also uses PyQt for the GUI):
###########################################
# PyUSB and PIC18F2550 demo (first revision) #
# Julius 'yus' Constante Nov. 21, 2009 #
###########################################
import sys, usb
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class UsbPic:
def __init__(self, vendor_id, product_id):
busses = usb.busses() # enumerate busses
self.handle = None
for bus in busses:
devices = bus.devices
for dev in devices:
if dev.idVendor==vendor_id and dev.idProduct==product_id: # device matches
self.dev = dev
self.conf = self.dev.configurations[0]
self.intf = self.conf.interfaces[0][0]
self.endpoints = []
for endpoint in self.intf.endpoints:
self.endpoints.append(endpoint)
return
def open(self):
if self.handle:
self.handle = None
try:
self.handle = self.dev.open()
self.handle.detachKernelDriver(0)
self.handle.detachKernelDriver(1)
self.handle.setConfiguration(self.conf)
self.handle.claimInterface(self.intf)
self.handle.setAltInterface(self.intf)
return True
except:
return False
def write(self, ep, buff, timeout = 100):
try:
return self.handle.interruptWrite(ep, buff, timeout) #return bytes written
except:
return 0
def read(self, ep, size, timeout = 100):
try:
return self.handle.interruptRead(ep, size, timeout) # return data read
except:
return []
def getDeviceName(self):
return self.handle.getString(2, 40)
class SimpleForm(QDialog):
def __init__(self, parent = None):
super(SimpleForm, self).__init__(parent)
self.setWindowTitle('PIC18F and PyUSB')
self.setMinimumSize(270, 180)
# create widgets/controls
self.connect_btn = QPushButton('Connect')
self.toggle1_btn = QPushButton('Toggle LED1')
self.toggle2_btn = QPushButton('Toggle LED2')
self.pot_position = QDial()
self.pot_label = QLabel('Potentiometer Position')
self.status_label = QLabel(' press "Connect" button')
self.update_timer = QTimer()
# form layout and widgets location
layout = QGridLayout()
layout.addWidget(self.connect_btn, 9, 0, 2, 1)
layout.addWidget(self.pot_position, 0, 0, 8, 7)
layout.addWidget(self.pot_label, 8, 0, 1, 7)
layout.addWidget(self.toggle1_btn, 4, 7)
layout.addWidget(self.toggle2_btn, 5, 7)
layout.addWidget(self.status_label, 9, 1, 2, 7)
self.setLayout(layout)
# widgets initial condition
self.toggle1_btn.setEnabled(False)
self.toggle2_btn.setEnabled(False)
self.pot_position.setEnabled(False) #read only
self.pot_position.setNotchesVisible(True)
self.pot_position.setRange(0, 255) # for PIC 8-bit ADC value
self.pot_label.setAlignment(Qt.AlignHCenter)
# signals
self.connect(self.connect_btn, SIGNAL("clicked()"), self.DeviceConnect)
self.connect(self.toggle1_btn, SIGNAL("clicked()"), self.toggleLED1)
self.connect(self.toggle2_btn, SIGNAL("clicked()"), self.toggleLED2)
self.connect(self.update_timer, SIGNAL("timeout()"), self.updatePotPosition)
def DeviceConnect(self):
self.device = UsbPic(0x04d8, 0x0204) # Microchip Vendor ID and Product ID
if self.device.open():
self.toggle1_btn.setEnabled(True)
self.toggle2_btn.setEnabled(True)
self.update_timer.start(200) # update every 200ms
self.status_label.setText('Connected to:\n %s' %self.device.getDeviceName())
else:
self.toggle1_btn.setEnabled(False)
self.toggle2_btn.setEnabled(False)
self.update_timer.stop()
self.status_label.setText('Warning:\n No Device Found!')
def toggleLED1(self):
self.device.write(1, [0x80], 1000)
def toggleLED2(self):
self.device.write(1, [0x82], 1000)
def updatePotPosition(self):
self.device.write(1, [0x81])
byteread = self.device.read(0x81, 64)
if len(byteread)>1:
self.pot_position.setValue(byteread[1])
if __name__ == '__main__':
app = QApplication(sys.argv)
form = SimpleForm()
form.show()
sys.exit(app.exec_())
And finally, the actual circuit in action:
[フレーム]
additional useful links:
Microchip USB Framework for PIC18, PIC24 & PIC32
LibUSB Win32
Sunday, November 15, 2009
PIC18F2550 USB HID Mouse
As my first step in learning on how to interface on PC USB ports, I copied the example source code for usb hid mouse by CCS C compiler. It's just a simple demo, moving the mouse pointer into a circular pattern, but it already gave me enough confidence because this example code works on my simple circuit. Since there's no problem with the circuit, I've continued with the next step which is the familiarization with the code routines/functions by modifying them (i.e. experimenting with the example code).
CCS C uses the usb_put_packet() command to send one packet to the usb host(PC), e.g. usb_put_packet(1, out_data, 4, USB_DTS_TOGGLE). The out_data parameter is an array of 4 elements (i.e. int8 out_data[4]). The first byte of out_data correspond to the state of mouse buttons, the second and third are for the x and y directions, while the last byte is for mouse wheel.
After experimenting with the usb_put_packet() function, I came up with this modified demo code for usb hib mouse. Instead of only moving the mouse pointer, I've configured it to 'draw some lines' on Microsoft Paint. And this was the result:
[フレーム]
Here's the code used in that demo video:
then the HEX file generated using CCS Microchip C PCH v4.088 compiler:
Also, the first hex code that worked on my circuit
(mouse pointer in circular movement):
CCS C uses the usb_put_packet() command to send one packet to the usb host(PC), e.g. usb_put_packet(1, out_data, 4, USB_DTS_TOGGLE). The out_data parameter is an array of 4 elements (i.e. int8 out_data[4]). The first byte of out_data correspond to the state of mouse buttons, the second and third are for the x and y directions, while the last byte is for mouse wheel.
After experimenting with the usb_put_packet() function, I came up with this modified demo code for usb hib mouse. Instead of only moving the mouse pointer, I've configured it to 'draw some lines' on Microsoft Paint. And this was the result:
[フレーム]
Here's the code used in that demo video:
// USB HID Mouse draws "usb pic18F2550" on MS Paint
#include <18F2550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=48000000)
#define USB_HID_DEVICE TRUE
#define USB_EP1_TX_ENABLE USB_ENABLE_INTERRUPT
#define USB_EP1_TX_SIZE 8
#include <pic18_usb.h>
#include <usb_desc_mouse.h>
#include <usb.c>
#define delay 20
#define scale 17
void draw_vertical(int8 direction)
{
int8 data[4], count = 0;
data[0] = 1;
data[1] = 0;
data[2] = direction;
data[3] = 0;
while(count<scale){
if(usb_put_packet(1, data,4,USB_DTS_TOGGLE)) count++;
delay_ms(delay);
}
}
void draw_horizontal(int8 direction)
{
int8 data[4], count = 0;
data[0] = 1;
data[1] = direction;
data[2] = 0;
data[3] = 0;
while(count<scale){
if(usb_put_packet(1, data,4,USB_DTS_TOGGLE)) count++;
delay_ms(delay);
}
}
void move_pointer(int8 x_direction, int8 y_direction)
{
int8 data[4], count = 0;
data[0] = 0;
data[1] = x_direction;
data[2] = y_direction;
data[3] = 0;
while(count<scale){
if(usb_put_packet(1, data,4,USB_DTS_TOGGLE)) count++;
delay_ms(delay);
}
}
void main(void)
{
usb_init_cs();
while (TRUE) {
usb_task();
if (usb_enumerated())
{
// 'u'
draw_vertical(5);
draw_horizontal(4);
draw_vertical(-5);
// 's'
move_pointer(1,5);
draw_horizontal(5);
draw_vertical(-3);
draw_horizontal(-4);
draw_vertical(-3);
draw_horizontal(4);
// 'b'
move_pointer(2,-4);
draw_vertical(8);
draw_horizontal(4);
draw_vertical(-5);
draw_horizontal(-4);
// 'p'
move_pointer(7,4);
draw_horizontal(4);
draw_vertical(-3);
draw_horizontal(-4);
draw_vertical(6);
// 'i'
move_pointer(5,-3);
draw_vertical(-4);
// 'c'
move_pointer(4,3);
draw_horizontal(-3);
draw_vertical(-3);
draw_horizontal(3);
// '1'
move_pointer(2,-4);
draw_vertical(6);
// '8'
move_pointer(2,-3);
draw_vertical(-3);
draw_horizontal(3);
draw_vertical(3);
draw_horizontal(-3);
draw_vertical(3);
draw_horizontal(3);
draw_vertical(-3);
// 'F'
move_pointer(2,4);
draw_vertical(-7);
draw_horizontal(4);
move_pointer(-1,3);
draw_horizontal(-3);
// '2'
move_pointer(4,-1);
draw_horizontal(3);
draw_vertical(3);
draw_horizontal(-3);
draw_vertical(3);
draw_horizontal(3);
// '5'
move_pointer(2,0);
draw_horizontal(3);
draw_vertical(-3);
draw_horizontal(-3);
draw_vertical(-3);
draw_horizontal(3);
// '5'
move_pointer(5,0);
draw_horizontal(-3);
draw_vertical(3);
draw_horizontal(3);
draw_vertical(3);
draw_horizontal(-3);
// '0'
move_pointer(5,0);
draw_vertical(-5);
draw_horizontal(3);
draw_vertical(5);
draw_horizontal(-3);
// line
move_pointer(0,7);
draw_horizontal(-22);
draw_vertical(2);
draw_horizontal(22);
delay_ms(5000);
}
}
}
then the HEX file generated using CCS Microchip C PCH v4.088 compiler:
:020000040000FA
:040000005EEF07F0B8
:08000800056ED8CF06F0E0CF31
:1000100007F00001E9CF0DF0EACF08F0E1CF09F0D9
:10002000E2CF0AF0D9CF0BF0DACF0CF0F3CF14F017
:10003000F4CF15F0FACF16F000C00FF001C010F0A9
:1000400002C011F003C012F004C013F0A0AA2CEFFC
:1000500000F0A1BA2EEF06F00FC000F010C001F0C2
:1000600011C002F012C003F013C004F00DC0E9FF8C
:1000700008C0EAFF088E09C0E1FF0AC0E2FF0BC01A
:10008000D9FF0CC0DAFF14C0F3FF15C0F4FF16C08F
:10009000FAFF055007C0E0FF06C0D8FF1000F76A5E
:1000A000AE0FF66E000EF7220900F55012000403A1
:1000B0000000000000000000000000000000F76ADF
:1000C000CE0FF66E000EF7220900F5501200040064
:1000D0000000000000000000000000000000F76ABF
:1000E000EE0FF66E000EF7220900F55012004000E8
:1000F00008000000000000000000000000000000F8
:100100000000000000000000000000000000F76A8E
:100110001E0FF66E010EF7220900F5501200400086
:1001200000000000000000000000000000000000CF
:100130000000000000000000000000000000F76A5E
:100140004E0FF66E010EF7220900F5501200050160
:100150000902A1010901A1000509190129031500DE
:100160002501950375018102950175058101050140
:100170000930093109381581257F750895038106F5
:10018000C0C0F76A920FF66E010EF7220900F55013
:1001900012000000F76AA40FF66E010EF7220900A4
:1001A000F55012003400F76AB60FF66E010EF72212
:1001B0000900F550120009022200010100C03209B5
:1001C00004000001030102000921000100012234A2
:1001D000000705810308000AF76AE80FF66E010EB2
:1001E000F7220900F55012000100F76AFA0FF66EC7
:1001F000010EF7220900F550120012011001000053
:10020000004061042200000101020001F76A1C0F96
:10021000F66E020EF7220900F550120000040C00E1
:10022000F76A300FF66E020EF7220900F550120041
:100230000403090408034300430053001C03430064
:1002400043005300200055005300420020004D00A1
:100250006F007500730065006D926994689439EFC2
:1002600006F06A6A689242EF06F03E6A3E520AE180
:10027000036A3E50240FE96E000E0320EA6EEF6A17
:100280003E2AF4D71A6A010E1B6E196A000C010E81
:10029000476E47500F080EE3700E4724016E0F0E95
:1002A000036ED8B0032A01C0E9FF03C0EAFFEF6A7A
:1002B000472AEFD71E6A1D6A000C400E0401016F29
:1002C000050E036F026B880E006F046B050E076F3F
:1002D000400E066F0001000C6A6A686A9F0E6B6E22
:1002E000390E696E6E6AC1DFD2DF160E706E68A6B7
:1002F00002D06896FCD76D98E0DF030E1F6E48EFC2
:1003000006F0698468986D824EEF06F0689C54EFA1
:1003100006F070A002D0D1DF7090689A5AEF06F014
:1003200042C020F0000CFF0E206E000C406A2352E9
:100330003EE040503F083BE31C50FC0F2BE2040F13
:10034000E1EF01F0036A2250F2CF42F0F29E2BDF80
:1003500042BEF28E416E1ED0036A2250F2CF42F0AE
:10036000F29EEDDE42BEF28E416E14D0036A225040
:10037000F2CF42F0F29E54DF42BEF28E416E0AD0BE
:10038000036A2250F2CF42F0F29E2FDF42BEF28E7D
:10039000416E00D0222A23064050402A036A400FB3
:1003A000E96E050E0320EA6E41C0EFFFC0D723526D
:1003B00004E14050400801E0196A40C042F0B0DF5B
:1003C000000CE824F76AF736DD0FF66E030EF7220D
:1003D0000A00F550FA6E0800F550F96E4403580310
:1003E0006C038003226A1C6A05010351010A0001A3
:1003F00009E0030A0CE0010A0DE0220A22E0030AE8
:1004000032E058D0120E236E030E1C6E55D0220E11
:10041000236E52D0020E1C6E036A05010251F2CF08
:1004200040F0F29E0001F2DE40BEF28E226E036AC0
:100430002250F2CF40F0F29EF3DE40BEF28E236EE9
:100440003BD0120E226E223C01D00BD0036A225008
:10045000F2CF40F0F29EA7DE40BEF28E236E2CD08B
:1004600002D061DF35D0D89005010435036AF2CFA0
:1004700040F0F29E000185DE0900F5CF03F040BE9A
:10048000F28E226E223C01D013D0010E1C6ED89049
:1004900005010435036AF2CF40F0F29E00017ADED6
:1004A0000900F5CF03F040BEF28E236E05D002D0D6
:1004B0003ADF0ED038DF0CD00501075305E1235099
:1004C000065D02E206C523F0010E196E00012EDF63
:1004D000000C3F5204E1040E1F6ED9DEC1D0050EA0
:1004E0001F6E426E800E416E010E406E40500F082E
:1004F000D8A0B6D0436A036A4050F2CF47F0F29ECC
:10050000DEDD47BEF28E000A51E0040E436ED89045
:100510004034036AF2CF47F0F29EF9DD0900F5CFCF
:1005200003F047BEF28E446E03C045F04050080D04
:10053000F350010F016E040E036ED8B0032A01C000
:10054000E9FF03C0EAFF44C0EFFF4050080DF3503D
:10055000020F016E040E036ED8B0032A01C0E9FF3A
:1005600003C0EAFF42C0ECFFED5241C0EFFFD8905C
:100570004034036AF2CF47F0F29EC9DD0900F5CF9F
:1005800003F047BEF28E412603504222880E466E8B
:1005900045B0468045B246824050080DF3CF01F089
:1005A000040E01C0E9FFEA6E46C0EFFF036A405047
:1005B000F2CF47F0F29E73DD47BEF28E000A31E0C3
:1005C00043824050080DF350060F016E040E036E77
:1005D000D8B0032A01C0E9FF03C0EAFF42C0ECFF24
:1005E000ED5241C0EFFFD8904034036AF2CF47F09C
:1005F000F29E75DD0900F5CF03F047BEF28E41266D
:10060000035042224050080DF350040F016E040EB7
:10061000036ED8B0032A01C0E9FF03C0EAFF400E11
:10062000EF6E4350060802E10E0E436E036A40501F
:10063000F2CF47F0F29E33DD47BEF28E020801E0B2
:100640004388700E4024016E0F0E036ED8B0032A4B
:1006500001C0E9FF03C0EAFF43C0EFFF402A46D7CD
:100660007CEF03F00501015100010DE0010A14E0E7
:10067000020A1EE0060A27E0030A2CE00E0A2CE01C
:10068000010A30E03DD01BC040F50501416B020E70
:10069000426E000145DE36D00501022D06D0010E66
:1006A0001B16426A00013CDE02D000013CDE2AD06B
:1006B0000501022D05D01B82426A000131DE02D005
:1006C000000131DE1FD0020E196E02C521F0426A10
:1006D00027DE18D087DE16D01AC040F5010E426E14
:1006E0001FDE10D005010251010808E302C51AF00F
:1006F00002C53FF00001EDD6426A12DE000102D0D1
:1007000012DE00D0B2EF04F01AC03FF00501015133
:10071000000107E00A0A0DE0010A2DE00D0A3DE0A4
:100720003ED00501406B416B020E426E0001F8DDC8
:1007300038D03F521EE0010E3F5C036AF2CF40F01A
:10074000F29E4ADD40BEF28E016E0501045DD8A026
:1007500002D000010ED0036A0451240FE96E000E8E
:100760000320EA6EEFCF40F5010E426E0001D8DDA6
:1007700001D0D9DD16D03F520EE0036A05010451C5
:10078000240FE96E000E0320EA6E02C5EFFF426AF5
:100790000001C6DD01D0C7DD04D024DE02D0C3DDF8
:1007A00000D0B2EF04F040903FBE40803F9E40A09A
:1007B00010D0036A3F50F2CF41F0F29E70DC41BE90
:1007C000F28E000A02E1000E01D0010E016E10D07F
:1007D0000FD0036A3F50F2CF41F0F29E70DC41BE71
:1007E000F28E000A02E1000E01D0010E016E00D06F
:1007F0006AEF04F040903FBE40803F9E40A010D082
:100800003F50080DF350040F016E040E036ED8B074
:10081000032A01C0E9FF03C0EAFF880EEF6E09D08A
:100820003F50080DF3CF01F0040E01C0E9FFEA6E5E
:10083000EF6A79EF04F040903FBE40803F9E40A0B9
:1008400010D03F50080DF350040F016E040E036EDC
:10085000D8B0032A01C0E9FF03C0EAFF840EEF6E9F
:100860000AD03F50080DF3CF01F0040E01C0E9FF9C
:10087000EA6E840EEF6E7FEF04F040903FBE408042
:100880003F9E40A010D03F50080DF350040F016E62
:10089000040E036ED8B0032A01C0E9FF03C0EAFFCB
:1008A000EFCF41F00AD03F50080DF3CF01F0040E16
:1008B00001C0E9FFEA6EEFCF41F041AE02D041B492
:1008C00002D0000E01D0010E016E89EF04F004C5C4
:1008D0003FF069D7015229E005010151010A0001E9
:1008E00005E0020A09E0030A0DE01DD004C53FF04F
:1008F00081D7426A15DD19D004C53FF09CD7426A02
:100900000FDD13D00501406B416B04C53FF00001C2
:10091000B4D7015204E0010E0501406F0001020E40
:10092000426EFEDC02D0FFDC00D0B2EF04F0050125
:10093000015100D00001F7DC00D0B2EF04F0196AD9
:10094000050100517F0B000107E0010A06E0030AE0
:1009500005E0230A04E004D085D6D6D6B8D7E7D779
:10096000E2DC00D0D9EF05F03F50080DF3CF01F0E5
:10097000040E01C0E9FFEA6EEFCF41F040500208DB
:1009800006E141AC02D0406A02D0010E406E4050F8
:10099000030812E1840E416E3F50080DF350040F1E
:1009A000016E040E036ED8B0032A01C0E9FF03C034
:1009B000EAFF840EEF6E09D0402C03D0C80E416EC2
:1009C00004D0405202E1880E416E036A010E026EAD
:1009D0003F50006E05E0D89002360336002EFBD75C
:1009E0000250FF0A006EFF0E031A00501D1603503E
:1009F0001E16D8903F34036AF2CF44F0F29E87EC83
:100A000000F00900F5CF03F044BEF28E426E03C041
:100A100043F03F50080DF350010F016E040E036EBA
:100A2000D8B0032A01C0E9FF03C0EAFF42C0EFFFCC
:100A300043B0418043B241823F50080DF3CF01F0F3
:100A4000040E01C0E9FFEA6E41C0EFFF000C3F5009
:100A5000080DF350040F016E040E036ED8B0032A84
:100A600001C0E9FF03C0EAFFEFCF43F043BE5BD014
:100A70003F50080DF350050F016E040E036ED8B001
:100A8000032A01C0E9FF03C0EAFF40C0EFFF425064
:100A9000020816E13F50080DF350040F016E040EDA
:100AA000036ED8B0032A01C0E9FF03C0EAFFEFCF0D
:100AB00043F043AC02D0426A02D0010E426E13D022
:100AC0004250040810E13F50080DF3CF01F0040E2E
:100AD00001C0E9FFEA6EEFCF43F043AC03D0010E53
:100AE000426E01D0426A422C03D0C80E436E04D03D
:100AF000425202E1880E436E41B0438041B24382CC
:100B00003F50080DF350040F016E040E036ED8B071
:100B1000032A01C0E9FF03C0EAFF43C0EFFF010E53
:100B2000016E03D000D0000E016E000C3F5203E1B5
:100B30005DEC01F00FD0036A010E026E3F50006EB3
:100B400005E0D89002360336002EFBD702501D1266
:100B500003501E12000C40C06EFF405203E0040E12
:100B60001F6E02D0020E1F6EBBEF05F01A6A196AE3
:100B700021C040F0F0D7C8EF05F03F5209E1192C31
:100B800003D096EC01F004D01950020801E1EED731
:100B9000000C6C303E6E3E323E321F0E3E166C52E2
:100BA0003BE1040100513C0B34081BE1046B0001E4
:100BB000C6D6203C05D03F6A030E406ED5DE0ED06F
:100BC0003F6A020E406ED0DE2050FE0807E03F6A0A
:100BD000416A20C040F0040E426E39DF6D9819D092
:100BE000040100513C0B040815E13F6A00019EDF3F
:100BF0003F6A020E406EB8DE2050FE080AE0203C3C
:100C000001D007D03F6A416A20C040F0010E426E19
:100C10001EDF040120D000016C50040812E1FF0E19
:100C2000206E3F6AAADF203C01D008D03F6A416AAB
:100C300020C040F0020E426E0ADF02D05DEC01F0EF
:100C400009D06CB404D03EC03FF070DF03D03EC08A
:100C50003FF093DF040100015FEF06F01F5201E156
:100C60002FD068522DE068A404D069A402D02CEFE4
:100C700001F06DA201D024D068A204D069A202D0F4
:100C800031EF01F068A004D069A002D06CEF01F050
:100C900068A804D069A802D081EF01F068AC04D044
:100CA00069AC02D086EF01F068AA04D069AA02D02C
:100CB00089EF01F068A604D069A602D06AD76896C9
:100CC000A19A2CEF00F06D6A696A080E6F6E94505D
:100CD0003009946E1F6A186AF2BE188EF29E35ECC7
:100CE00001F018BEF28E1E6A1D6A6CEF07F0186ADA
:100CF000F2BE188EF29E35EC01F018BEF28E6D6ACF
:100D0000140E6F6E696A6D86010E1F6E8BEF06F012
:100D10006DB601D0ECD71F2C0BD06DBA09D0686A24
:100D2000696AA08AC00EF212110E696E020E1F6E61
:100D30006DEF07F02C50080DF350040F016E040EF8
:100D4000036ED8B0032A01C0E9FF03C0EAFFEFCF6A
:100D500034F034BE45D02C50080DF350060F016E10
:100D6000040E036ED8B0032A01C0E9FF03C0EAFFF6
:100D7000ECCF03F0ED52EFCF35F003C036F0336A1D
:100D8000326A3350305C1AE303E12F50325C16E2D2
:100D90002DC0E9FF2EC0EAFFEFCF39F036C0EAFFE1
:100DA00035C0E9FF39C0EFFF352AD8B4362A2D2ADD
:100DB000D8B42E2A322AD8B4332AE3D7186AF2BE1E
:100DC000188EF29E2CC03FF030C041F02FC040F092
:100DD00031C042F03CDE18BEF28E015003D000D08C
:100DE000000E016E000CEA6A2C0EE96EEF500EE068
:100DF0000F0E016E006A002EFED7012EFBD78F0E5C
:100E0000006E002EFED70000EF2EF2D7000C2A6AEB
:100E1000010E266E276A25C028F0296A2A5010087C
:100E200012E3010E2C6E2E6A260E2D6E306A040E11
:100E30002F6E020E316E7EDF0152D8A42A2A140EC4
:100E40002C6ED1DFEBD7000C2A6A010E266E25C06E
:100E500027F0286A296A2A50100812E3010E2C6E26
:100E60002E6A260E2D6E306A040E2F6E020E316E23
:100E700061DF0152D8A42A2A140E2C6EB4DFEBD7FE
:100E8000000C2B6A276A25C028F026C029F02A6AA0
:100E90002B50100812E3010E2C6E2E6A270E2D6EB9
:100EA000306A040E2F6E020E316E44DF0152D8A458
:100EB0002B2A140E2C6E97DFEBD7000CF86AD09E0D
:100EC000088EEA6AE96AC150C00B0F09C16E070EAD
:100ED000B46E1F6A236AF7D61BD71A52D8B4E8D06B
:100EE000050E256E94DF040E256EAEDFFB0E256E1B
:100EF0008EDF010E256E050E266EC3DF050E256EF4
:100F0000A3DFFD0E256E83DFFC0E256E9DDFFD0E3B
:100F1000256E7DDF040E256E97DF020E256EFC0E1A
:100F2000266EAFDF080E256E72DF040E256E8CDF95
:100F3000FB0E256E6CDFFC0E256E86DF070E256E20
:100F4000040E266E9EDF040E256E7EDFFD0E256EDE
:100F50005EDFFC0E256E78DF060E256E58DF050E6F
:100F6000256EFD0E266E8DDFFC0E256E50DF040E05
:100F7000256E030E266E85DFFD0E256E65DFFD0EE8
:100F8000256E45DF030E256E5FDF020E256EFC0E1B
:100F9000266E77DF060E256E3ADF020E256EFD0EF9
:100FA000266E6FDFFD0E256E32DF030E256E4CDFE1
:100FB000030E256E2CDFFD0E256E46DF030E256E1B
:100FC00026DF030E256E40DFFD0E256E20DF020EAC
:100FD000256E040E266E55DFF90E256E18DF040E01
:100FE000256E32DFFF0E256E030E266E4ADFFD0EE4
:100FF000256E2ADF040E256EFF0E266E42DF030EDD
:10100000256E22DF030E256E02DFFD0E256E1CDF2E
:10101000030E256EFCDE030E256E16DF020E256E16
:10102000266A2FDF030E256E0FDFFD0E256EEFDE25
:10103000FD0E256E09DFFD0E256EE9DE030E256E21
:1010400003DF050E256E266A1CDFFD0E256EFCDE15
:10105000030E256EDCDE030E256EF6DE030E256E16
:10106000D6DEFD0E256EF0DE050E256E266A09DF42
:10107000FB0E256ECCDE030E256EE6DE050E256E1C
:10108000C6DEFD0E256EE0DE256A070E266EF9DE51
:10109000EA0E256ED9DE020E256EB9DE160E256E1D
:1010A000D3DE140E256EFA0E2C6E9DDE252EFBD798
:0410B00013D703004F
:020000040030CA
:0E000000240E3E1E008381000FC00FE00F4053
:00000001FF
;PIC18F2550
;CRC=1458 CREATED="15-Nov-09 13:45"
Also, the first hex code that worked on my circuit
(mouse pointer in circular movement):
:020000040000FA
:040000001EEF07F0F8
:08000800056ED8CF06F0E0CF31
:1000100007F00001E9CF0DF0EACF08F0E1CF09F0D9
:10002000E2CF0AF0D9CF0BF0DACF0CF0F3CF14F017
:10003000F4CF15F0FACF16F000C00FF001C010F0A9
:1000400002C011F003C012F004C013F0A0AA2CEFFC
:1000500000F0A1BA43EF06F00FC000F010C001F0AD
:1000600011C002F012C003F013C004F00DC0E9FF8C
:1000700008C0EAFF088E09C0E1FF0AC0E2FF0BC01A
:10008000D9FF0CC0DAFF14C0F3FF15C0F4FF16C08F
:10009000FAFF055007C0E0FF06C0D8FF1000F76A5E
:1000A000AE0FF66E000EF7220900F55012000403A1
:1000B0000000000000000000000000000000F76ADF
:1000C000CE0FF66E000EF7220900F5501200040064
:1000D0000000000000000000000000000000F76ABF
:1000E000EE0FF66E000EF7220900F55012004000E8
:1000F00008000000000000000000000000000000F8
:100100000000000000000000000000000000F76A8E
:100110001E0FF66E010EF7220900F5501200400086
:1001200000000000000000000000000000000000CF
:100130000000000000000000000000000000F76A5E
:100140004E0FF66E010EF7220900F5501200050160
:100150000902A1010901A1000509190129031500DE
:100160002501950375018102950175058101050140
:100170000930093109381581257F750895038106F5
:10018000C0C0F76A920FF66E010EF7220900F55013
:1001900012000000F76AA40FF66E010EF7220900A4
:1001A000F55012003400F76AB60FF66E010EF72212
:1001B0000900F550120009022200010100C03209B5
:1001C00004000001030102000921000100012234A2
:1001D000000705810308000AF76AE80FF66E010EB2
:1001E000F7220900F55012000100F76AFA0FF66EC7
:1001F000010EF7220900F550120012011001000053
:10020000004061042200000101020001F76A1C0F96
:10021000F66E020EF7220900F550120000040C00E1
:10022000F76A300FF66E020EF7220900F550120041
:100230000403090408034300430053001C03430064
:1002400043005300200055005300420020004D00A1
:100250006F00750073006500F2CF0EF0F29EF76A32
:10026000720FF66E020EF7220900F5500EBEF28EE6
:100270001200000103040404030100FFFDFCFCFC68
:10028000FDFF6D92699468944EEF06F06A6A689279
:1002900057EF06F03E6A3E520AE1036A3E50240FD1
:1002A000E96E000E0320EA6EEF6A3E2AF4D71A6A5E
:1002B000010E1B6E196A000C010E476E47500F08A5
:1002C0000EE3700E4724016E0F0E036ED8B0032AA2
:1002D00001C0E9FF03C0EAFFEF6A472AEFD71E6AB1
:1002E0001D6A000C400E0401016F050E036F026BC6
:1002F000880E006F046B050E076F400E066F00013D
:10030000000C6A6A686A9F0E6B6E390E696E6E6ABF
:10031000C1DFD2DF160E706E68A602D06896FCD7D9
:100320006D98E0DF030E1F6E5DEF06F0698468983C
:100330006D8263EF06F0689C69EF06F070A002D052
:10034000D1DF7090689A6FEF06F042C020F0000C89
:10035000FF0E206E000C406A23523EE040503F08E2
:100360003BE31C50FC0F2BE2040FF6EF01F0036A95
:100370002250F2CF42F0F29E16DF42BEF28E416E64
:100380001ED0036A2250F2CF42F0F29ED8DE42BE67
:10039000F28E416E14D0036A2250F2CF42F0F29EE8
:1003A0003FDF42BEF28E416E0AD0036A2250F2CF86
:1003B00042F0F29E1ADF42BEF28E416E00D0222A37
:1003C00023064050402A036A400FE96E050E0320C1
:1003D000EA6E41C0EFFFC0D7235204E1405040080D
:1003E00001E0196A40C042F0B0DF000CE824F76A6F
:1003F000F736070FF66E040EF7220A00F550FA6E74
:100400000800F550F96E6E0382039603AA03226A70
:100410001C6A05010351010A000109E0030A0CE00E
:10042000010A0DE0220A22E0030A32E058D0120E3F
:10043000236E030E1C6E55D0220E236E52D0020E78
:100440001C6E036A05010251F2CF40F0F29E0001DA
:10045000DDDE40BEF28E226E036A2250F2CF40F003
:10046000F29EDEDE40BEF28E236E3BD0120E226E76
:10047000223C01D00BD0036A2250F2CF40F0F29E12
:1004800092DE40BEF28E236E2CD002D061DF35D0DA
:10049000D89005010435036AF2CF40F0F29E0001C6
:1004A00070DE0900F5CF03F040BEF28E226E223CD2
:1004B00001D013D0010E1C6ED89005010435036ADB
:1004C000F2CF40F0F29E000165DE0900F5CF03F0A7
:1004D00040BEF28E236E05D002D03ADF0ED038DF58
:1004E0000CD00501075305E12350065D02E206C565
:1004F00023F0010E196E00012EDF000C3F5204E1C3
:10050000040E1F6ED9DEC1D0050E1F6E426E800E26
:10051000416E010E406E40500F08D8A0B6D0436A1D
:10052000036A4050F2CF47F0F29EC9DD47BEF28E1B
:10053000000A51E0040E436ED8904034036AF2CFB3
:1005400047F0F29EE4DD0900F5CF03F047BEF28EDE
:10055000446E03C045F04050080DF350010F016E8A
:10056000040E036ED8B0032A01C0E9FF03C0EAFFFE
:1005700044C0EFFF4050080DF350020F016E040E0F
:10058000036ED8B0032A01C0E9FF03C0EAFF42C0EE
:10059000ECFFED5241C0EFFFD8904034036AF2CF38
:1005A00047F0F29EB4DD0900F5CF03F047BEF28EAE
:1005B000412603504222880E466E45B0468045B221
:1005C00046824050080DF3CF01F0040E01C0E9FF50
:1005D000EA6E46C0EFFF036A4050F2CF47F0F29E4A
:1005E0005EDD47BEF28E000A31E043824050080DC6
:1005F000F350060F016E040E036ED8B0032A01C03B
:10060000E9FF03C0EAFF42C0ECFFED5241C0EFFF3B
:10061000D8904034036AF2CF47F0F29E60DD0900C3
:10062000F5CF03F047BEF28E4126035042224050E0
:10063000080DF350040F016E040E036ED8B0032AA8
:1006400001C0E9FF03C0EAFF400EEF6E4350060809
:1006500002E10E0E436E036A4050F2CF47F0F29E65
:100660001EDD47BEF28E020801E04388700E402472
:10067000016E0F0E036ED8B0032A01C0E9FF03C05C
:10068000EAFF43C0EFFF402A46D791EF03F0050190
:10069000015100010DE0010A14E0020A1EE0060A01
:1006A00027E0030A2CE00E0A2CE0010A30E03DD0DE
:1006B0001BC040F50501416B020E426E000145DE94
:1006C00036D00501022D06D0010E1B16426A00012C
:1006D0003CDE02D000013CDE2AD00501022D05D00F
:1006E0001B82426A000131DE02D0000131DE1FD0E0
:1006F000020E196E02C521F0426A27DE18D087DE8D
:1007000016D01AC040F5010E426E1FDE10D0050152
:100710000251010808E302C51AF002C53FF00001CA
:10072000EDD6426A12DE000102D012DE00D0C7EF21
:1007300004F01AC03FF005010151000107E00A0A68
:100740000DE0010A2DE00D0A3DE03ED00501406BB1
:10075000416B020E426E0001F8DD38D03F521EE0C0
:10076000010E3F5C036AF2CF40F0F29E35DD40BEE1
:10077000F28E016E0501045DD8A002D000010ED0FA
:10078000036A0451240FE96E000E0320EA6EEFCFD6
:1007900040F5010E426E0001D8DD01D0D9DD16D042
:1007A0003F520EE0036A05010451240FE96E000E6A
:1007B0000320EA6E02C5EFFF426A0001C6DD01D0E8
:1007C000C7DD04D024DE02D0C3DD00D0C7EF04F0C3
:1007D00040903FBE40803F9E40A010D0036A3F50F3
:1007E000F2CF41F0F29E5BDC41BEF28E000A02E1E4
:1007F000000E01D0010E016E10D00FD0036A3F50E1
:10080000F2CF41F0F29E5BDC41BEF28E000A02E1C3
:10081000000E01D0010E016E00D07FEF04F0409079
:100820003FBE40803F9E40A010D03F50080DF35087
:10083000040F016E040E036ED8B0032A01C0E9FF55
:1008400003C0EAFF880EEF6E09D03F50080DF3CFCA
:1008500001F0040E01C0E9FFEA6EEF6A8EEF04F0CA
:1008600040903FBE40803F9E40A010D03F50080DBA
:10087000F350040F016E040E036ED8B0032A01C0BA
:10088000E9FF03C0EAFF840EEF6E0AD03F50080D67
:10089000F3CF01F0040E01C0E9FFEA6E840EEF6EA3
:1008A00094EF04F040903FBE40803F9E40A010D0A7
:1008B0003F50080DF350040F016E040E036ED8B0C4
:1008C000032A01C0E9FF03C0EAFFEFCF41F00AD0DD
:1008D0003F50080DF3CF01F0040E01C0E9FFEA6EAE
:1008E000EFCF41F041AE02D041B402D0000E01D0B2
:1008F000010E016E9EEF04F004C53FF069D701526E
:1009000029E005010151010A000105E0020A09E0A0
:10091000030A0DE01DD004C53FF081D7426A15DD02
:1009200019D004C53FF09CD7426A0FDD13D00501F2
:10093000406B416B04C53FF00001B4D7015204E0A5
:10094000010E0501406F0001020E426EFEDC02D076
:10095000FFDC00D0C7EF04F00501015100D0000119
:10096000F7DC00D0C7EF04F0196A050100517F0BD6
:10097000000107E0010A06E0030A05E0230A04E09B
:1009800004D085D6D6D6B8D7E7D7E2DC00D0EEEFD4
:1009900005F03F50080DF3CF01F0040E01C0E9FF50
:1009A000EA6EEFCF41F04050020806E141AC02D0C0
:1009B000406A02D0010E406E4050030812E1840EDE
:1009C000416E3F50080DF350040F016E040E036E8C
:1009D000D8B0032A01C0E9FF03C0EAFF840EEF6E1E
:1009E00009D0402C03D0C80E416E04D0405202E121
:1009F000880E416E036A010E026E3F50006E05E0E4
:100A0000D89002360336002EFBD70250FF0A006E44
:100A1000FF0E031A00501D1603501E16D8903F34C7
:100A2000036AF2CF44F0F29E87EC00F00900F5CFA4
:100A300003F044BEF28E426E03C043F03F50080DF7
:100A4000F350010F016E040E036ED8B0032A01C0EB
:100A5000E9FF03C0EAFF42C0EFFF43B0418043B269
:100A600041823F50080DF3CF01F0040E01C0E9FFB1
:100A7000EA6E41C0EFFF000C3F50080DF350040F29
:100A8000016E040E036ED8B0032A01C0E9FF03C053
:100A9000EAFFEFCF43F043BE5BD03F50080DF35069
:100AA000050F016E040E036ED8B0032A01C0E9FFE2
:100AB00003C0EAFF40C0EFFF4250020816E13F507A
:100AC000080DF350040F016E040E036ED8B0032A14
:100AD00001C0E9FF03C0EAFFEFCF43F043AC02D00F
:100AE000426A02D0010E426E13D04250040810E157
:100AF0003F50080DF3CF01F0040E01C0E9FFEA6E8C
:100B0000EFCF43F043AC03D0010E426E01D0426AF6
:100B1000422C03D0C80E436E04D0425202E1880E2C
:100B2000436E41B0438041B243823F50080DF350C1
:100B3000040F016E040E036ED8B0032A01C0E9FF52
:100B400003C0EAFF43C0EFFF010E016E03D000D0E7
:100B5000000E016E000C3F5203E172EC01F00FD069
:100B6000036A010E026E3F50006E05E0D890023617
:100B70000336002EFBD702501D1203501E12000C2C
:100B800040C06EFF405203E0040E1F6E02D0020E02
:100B90001F6ED0EF05F01A6A196A21C040F0F0D735
:100BA000DDEF05F03F5209E1192C03D0ABEC01F069
:100BB00004D01950020801E1EED7000C6C303E6EF3
:100BC0003E323E321F0E3E166C523BE10401005194
:100BD0003C0B34081BE1046B0001C6D6203C05D059
:100BE0003F6A030E406ED5DE0ED03F6A020E406EA5
:100BF000D0DE2050FE0807E03F6A416A20C040F086
:100C0000040E426E39DF6D9819D0040100513C0B7F
:100C1000040815E13F6A00019EDF3F6A020E406E44
:100C2000B8DE2050FE080AE0203C01D007D03F6A21
:100C3000416A20C040F0010E426E1EDF040120D048
:100C400000016C50040812E1FF0E206E3F6AAADF1B
:100C5000203C01D008D03F6A416A20C040F0020E1B
:100C6000426E0ADF02D072EC01F009D06CB404D0FD
:100C70003EC03FF070DF03D03EC03FF093DF040181
:100C8000000174EF06F01F5201E12FD068522DE0F1
:100C900068A404D069A402D041EF01F06DA201D094
:100CA00024D068A204D069A202D046EF01F068A067
:100CB00004D069A002D081EF01F068A804D069A82F
:100CC00002D096EF01F068AC04D069AC02D09BEF83
:100CD00001F068AA04D069AA02D09EEF01F068A6CC
:100CE00004D069A602D06AD76896A19A2CEF00F0CA
:100CF0006D6A696A080E6F6E94503009946E1F6AAF
:100D0000186AF2BE188EF29E4AEC01F018BEF28EFE
:100D10001E6A1D6A30EF07F0186AF2BE188EF29E46
:100D20004AEC01F018BEF28E6D6A140E6F6E696A9D
:100D30006D86010E1F6EA0EF06F06DB601D0ECD7E8
:100D40001F2C0BD06DBA09D0686A696AA08AC00EE0
:100D5000F212110E696E020E1F6E31EF07F02C5069
:100D6000080DF350040F016E040E036ED8B0032A71
:100D700001C0E9FF03C0EAFFEFCF34F034BE45D035
:100D80002C50080DF350060F016E040E036ED8B000
:100D9000032A01C0E9FF03C0EAFFECCF03F0ED52E4
:100DA000EFCF35F003C036F0336A326A3350305C2F
:100DB0001AE303E12F50325C16E22DC0E9FF2EC08A
:100DC000EAFFEFCF39F036C0EAFF35C0E9FF39C09E
:100DD000EFFF352AD8B4362A2D2AD8B42E2A322A43
:100DE000D8B4332AE3D7186AF2BE188EF29E2CC00C
:100DF0003FF030C041F02FC040F031C042F03CDE47
:100E000018BEF28E015003D000D0000E016E54EFD8
:100E100007F0EA6A2C0EE96EEF500EE00F0E016E3D
:100E2000006A002EFED7012EFBD78F0E006E002E1B
:100E3000FED70000EF2EF2D768EF07F0F86AD09ED9
:100E4000088EEA6AE96AC150C00B0F09C16E070E2D
:100E5000B46E1F6A236A296A2A6A040E2B6E48D769
:100E60006CD71A5235E0256A036A2A50F2CF2CF06B
:100E7000F29E2CEC01F02CBEF28E266E036A2B50F3
:100E8000F2CF2CF0F29E2CEC01F02CBEF28E276EED
:100E9000286A010E2C6E2E6A250E2D6E306A040E05
:100EA0002F6E020E316E5BD7015201E0292A2950C4
:100EB0000A080BE22A2A2A500F08D8A02A6A2B2AED
:100EC0002B500F08D8A02B6A296A0A0E2C6EA1D7C6
:040ED000C7D703007D
:020000040030CA
:0E000000240E3E1E008381000FC00FE00F4053
:00000001FF
;PIC18F2550
;CRC=A06D CREATED="15-Nov-09 11:02"
Subscribe to:
Comments (Atom)