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:
 /*   
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:
 // 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"

Saturday, November 7, 2009

Scrolling Message Display on a DMM

Recently, I came across this Python package for GPIB interfacing. It's called PyVISA, and it's relatively easy to use even if you don't have backgrounds on Python programming language. As part of my experiments on Python PC interfacing, I managed to borrow an equiptment having a GPIB port.The Agilent (HP)34410A Digital Multimeter (DMM), it's one of the commonly used equipments in our workplace. While reading the 'remote programming' manual of this DMM, I found out that it is capable of displaying text (e.g. alphanumerics) on its front panel display. The GPIB command is fairly simple, just send DISPlay:TEXT + the qouted message. (e.g. DISP:TEXT "hello" ). The message to be displayed is up to 12 characters long.


the PyVISA python script for scrolling message:
 import visa, time  

hp = visa.Instrument('GPIB::2')

def display(msg):
hp.write('DISP:TEXT ' + '"' + msg + '"')

message = ' scrolling message display on Agilent HP34410A using Python PyVISA. by yus Electronicslab.ph'

for count in range(100):
for i in range( len(message)):
#display(message[i:(i+12)])
display(message[i:(i+12)].upper())
time.sleep(0.3)


demo:


forum link: GPIB (General Purpose Interface Bus, IEEE-488)

Monday, November 2, 2009

PySerial DTR and RTS Manipulation

Another application using (Python) PyQt and PySerial: a simple serial port LED blinker program.

two LEDs connected to DTR and RTS of a COM port (pins 4 and 7 of DB9):

simple python py script:
 import sys, serial  
from PyQt4.QtGui import *
from PyQt4.QtCore import *

class MyForm(QDialog):
def __init__(self, parent = None):
super(MyForm, self).__init__(parent)
self.setWindowTitle('PySerial DTR and RTS Manipulation')
self.setMinimumSize(300, 100)
# widgets
DTRlabel, RTSlabel = QLabel(), QLabel()
self.DTRbutton = QPushButton('set to Logic "True"')
self.RTSbutton = QPushButton('set to Logic "True"')
self.DTRcheckbox = QCheckBox('continuous toggle')
self.RTScheckbox = QCheckBox('continuous toggle')
# layout
layout = QGridLayout()
layout.addWidget(DTRlabel, 0, 0)
layout.addWidget(RTSlabel, 0, 1)
layout.addWidget(self.DTRbutton, 1, 0)
layout.addWidget(self.RTSbutton, 1, 1)
layout.addWidget(self.DTRcheckbox, 2, 0)
layout.addWidget(self.RTScheckbox, 2, 1)
self.setLayout(layout)
# serial port
self.port = serial.Serial('COM1')
DTRlabel.setText("<font size = 5 color = darkred><b> " +self.port.name + " DTR pin:</b></font>")
RTSlabel.setText("<font size = 5 color = darkred><b> " +self.port.name + " RTS pin:</b></font>")
self.DTRlogic, self.RTSlogic = False, False
self.port.setDTR(self.DTRlogic)
self.port.setRTS(self.RTSlogic)
# events
self.connect(self.DTRbutton, SIGNAL('clicked()'), self.toggleDTR)
self.connect(self.RTSbutton, SIGNAL('clicked()'), self.toggleRTS)
self.DTRtimer , self.RTStimer = QTimer(), QTimer()
self.connect(self.DTRtimer, SIGNAL('timeout()'), self.eventDTRtimer)
self.DTRtimer.start(250) # in milliseconds
self.connect(self.RTStimer, SIGNAL('timeout()'), self.eventRTStimer)
self.RTStimer.start(100) # in milliseconds

def toggleDTR(self):
self.DTRbutton.setText('set to Logic "' + str(self.DTRlogic) + '"')
self.DTRlogic = not self.DTRlogic # invert logic
self.port.setDTR(self.DTRlogic)
def toggleRTS(self):
self.RTSbutton.setText('set to Logic "' + str(self.RTSlogic) + '"')
self.RTSlogic = not self.RTSlogic # invert logic
self.port.setRTS(self.RTSlogic)
def eventDTRtimer(self):
if self.DTRcheckbox.isChecked():
self.toggleDTR()
def eventRTStimer(self):
if self.RTScheckbox.isChecked():
self.toggleRTS()

if __name__ == '__main__':
app = QApplication(sys.argv)
form = MyForm()
form.show()
sys.exit(app.exec_())


demo:

*the 'blink' rate depends on QTimer timeout period

forum link: serial port LED blinker

Saturday, October 24, 2009

Portable Eric 4 Python IDE

Portable ERIC Integrated Development Environment for the Python programming language. Eric 4.3.8 (r3477)

What is Eric?
Eric is a full featured Python and Ruby editor and IDE, written in python. It is based on the cross platform Qt gui toolkit, integrating the highly flexible Scintilla editor control. It is designed to be usable as everdays' quick and dirty editor as well as being usable as a professional project management tool integrating many advanced features Python offers the professional coder. eric4 includes a plugin system, which allows easy extension of the IDE functionality with plugins downloadable from the net.




download link: Portable Eric 4 Python IDE
*includes Eric 4 (w/ necessary plugins) + Python 2.6.3 + PyQt (Qt v4.5.2) + pyserial 2.5
*tested on Windows XP SP3


sample usage: PyCute Timer (PyQt + PySerial example)

Wednesday, October 7, 2009

Parallel Two Resistors

I made a small and simple application for finding a pair of resistors (with standard values) together having an equivalent resistance (to be connected in parallel) with the desired resistance value.

This one is created in Python S60 language. I'm using a Nokia 6120c operating at Symbian OS (S60v3).

Python S60 source code (PyS60 script):
 ####################################  
# parallel two resistors v1.05 #
# yus projectproto.blogspot.com/ #
####################################
import appuifw
from appuifw import *
import e32
from graphics import *
decades_E24 = u"1.0,1.1,1.2,1.3,1.5,1.6,1.8,2.0,2.2,2.4,2.7,3.0,3.3,3.6,3.9,4.3,4.7,5.1,5.6,6.2,6.8,7.5,8.2,9.1"
decades_E12 = u"1.0, 1.2, 1.5, 1.8, 2.2, 2.7, 3.3, 3.9, 4.7, 5.6, 6.8, 8.2"
decades = decades_E12 #initial, set to E12 series
excluded_parts = u"" #initial, no excluded parts
#define colors: black, brown, red, orange, yellow, green, blue, violet, grey, white, gold, silver
colors = [0x000000, 0x804040, 0xff0000, 0xff8000, 0xffff00, 0x008000, 0x0000ff, 0x800080, 0xc0c0c0, 0xffffff,
0x808040, 0x808080]
Rdesired = u"12.3" #initial desired value
excludeds = appuifw.Text()
excludeds.font = (None, 20, None)
excludeds.add(excluded_parts)
base = appuifw.Text()
base.font = (None, 20, None)
base.set(decades)
# define an initial image (white)
img = Image.new((240,320)) #(horizontal, vertical)
# define your redraw function (that redraws the picture on and on)
def main_handle_redraw(rect):
main_canvas.blit(img) # redraw the image named img using the blit function
# define the canvas, include the redraw callback function
main_canvas = appuifw.Canvas(event_callback=None, redraw_callback=main_handle_redraw)
def initialize():
appuifw.app.screen='normal' # set the screen size to large
main_canvas_setup()
appuifw.app.exit_key_handler = quit
main_canvas_setup()
img.clear(0x0080f0)
appuifw.app.menu = [] #create the menu
appuifw.app.menu.append((u"input resistance",get_desired_resistance))
appuifw.app.menu.append((u"select decades set", decades_setup))
appuifw.app.menu.append((u"add excluded parts", excluded_parts_setup))
appuifw.app.menu.append((u"about", about))
appuifw.app.menu.append((u"exit", quit))
img.text((5,70), u"press 'options'->'input resistance'", 0xfff000, font=(None,12,FONT_BOLD))
img.text((5,90), u"then, type the desired resistance value", 0xfff000, font=(None,12,FONT_BOLD))
img.text((170,200), u"'yus 09", 0xff8040, font=(None,18,FONT_BOLD))
main_canvas.blit(img)
def about():
appuifw.note(u"Parallel 2R v1.04\n by: 'yus", 'info')
def main_canvas_setup():
appuifw.app.title = u"Parallel 2R"
appuifw.app.body = main_canvas
appuifw.app.exit_key_handler = quit
def decades_setup():
global decades
appuifw.app.title = u"decade values"
options = [u"E12 series", u"E24 series", u"customize"]
decades_select = appuifw.popup_menu(options, u"Select decade series:")
if decades_select == 0:
decades = decades_E12
if decades_select == 1:
decades = decades_E24
if decades_select == 2:
appuifw.app.body = base
decades = base.get()
appuifw.app.exit_key_handler = main_canvas_setup
base.set(decades)
def excluded_parts_setup():
global excluded_parts
global excludeds
appuifw.app.title = u"excuded parts"
appuifw.app.body = excludeds
excluded_parts = excludeds.get()
appuifw.app.exit_key_handler = main_canvas_setup
def get_desired_resistance():
global Rdesired
global decades
global excluded_parts
global ex_parts
global excludeds
decades = base.get()
excluded_parts = excludeds.get()
ex_parts = (u"0,0" + excluded_parts).split(",")
main_canvas_setup()
Rdesired = appuifw.query(u"desired resistance (\u03A9)", 'text', Rdesired) # u"\u03A9" -> ohm symbol
R1_base, R1_multiplier, R2_base, R2_multiplier = find_equivalent_2R()
R1 = float(R1_base)* float(10**int(R1_multiplier))
img.clear(0x0080f0)
img.text((10,40), u"desired R = " + Rdesired + u" \u03A9", 0xfff000, font=(None,18,FONT_BOLD))
img.text((20,65), u"R1 = " + u"%.1f" % R1 + u" \u03A9", 0xfff000, font=(None,18,FONT_BOLD))
color_code(0, R1_base, R1_multiplier)
if R2_base == u"open":
R_equivalent = R1
error = compute_error(R1*2, R1*2)*100
else:
R2 = float(R2_base)* float(10**int(R2_multiplier))
R_equivalent = (R1*R2)/(R1+R2)
error = compute_error(R1, R2)*100
img.text((20,135), u"R2 = " + u"%.1f" % R2 + u" \u03A9", 0xfff000, font=(None,18,FONT_BOLD))
color_code(1, R2_base, R2_multiplier)
img.text((10,200), u"Req = " + u"%.5f" % R_equivalent + u" \u03A9", 0xfff000, font=(None,18,FONT_BOLD))
img.text((10,225), u"error = " + u"%.7f" % error + u" %", 0xfff000, font=(None,18,FONT_BOLD))
def find_equivalent_2R():
global Rdesired
global decades
ex_parts = (u"0,0" + excluded_parts).split(",")
r1_base = r2_base = u"1.0" #initial values
r1_multiplier = r2_multiplier = u"-2"
r1 = r2 = 0.0001
e = compute_error(r1, r2)
decade_values = decades.split(",")
for i in decade_values:
for j in range(-2,7):
r1 = float(i) * float(10**j) # i * (10^j)
if pwede(r1) == False:
continue
elif r1 == float(Rdesired):
r1_base, r1_multiplier, r2_base, r2_multiplier = i, j, u"open", u"open"
return r1_base, r1_multiplier, r2_base, r2_multiplier # _r2 is open
elif compute_error(r1*2, r1*2) < e:
r1_base, r1_multiplier, r2_base, r2_multiplier = i, j, u"open", u"open"
e = compute_error(r1*2, r1*2)
for m in decade_values:
for n in range(-2,7):
r2 = float(m) * float(10**n) # m * (10^n)
if r2 < r1:
continue
elif compute_error(r1, r2) < e and pwede(r2):
r1_base, r1_multiplier, r2_base, r2_multiplier = i, j, m, n
e = compute_error(r1, r2)
return r1_base, r1_multiplier, r2_base, r2_multiplier
def compute_error(R1, R2):
global Rdesired
Rin = float(Rdesired)
Req = (R1 * R2)/(R1 + R2)
error = (Req - Rin)/Rin
if error < 0:
error *= -1 #absolute value
return (error)
def pwede(value):
global ex_parts
valid = True
for i in ex_parts:
#if value == float(i): #having problems with "float" variables precision
diff = (float(i)-value)/value
if diff < 0:
diff *= -1 #absolute value
if diff < 0.0000000001: #tolerance for precision error
valid = False
return (valid)
def color_code(pos, base, multiplier):
global colors
digits = base.split(".")
band1 = colors[int(digits[0])]
band2 = colors[int(digits[1])]
multiplier -= 1
if multiplier == -3:
band3 = None
elif multiplier == -2:
band3 = colors[11]
elif multiplier == -1:
band3 = colors [10]
else:
band3 = colors[int(multiplier)]
band4 = colors[10] # gold (default tolerance)
#'draw' a typical resistor
img.rectangle((40,85 +pos*70,210,95 +pos*70), fill=colors[8]) # terminals
img.rectangle((100,70 +pos*70,160,110 +pos*70), fill=(250,200,120)) # body
img.ellipse((75,67 +pos*70,110,113 +pos*70), fill=(250,200,120)) # left edge
img.ellipse((147,67 +pos*70,182,113 +pos*70), fill=(250,200,120)) # right edge
#color bands
img.rectangle((100,70 +pos*70,110,110 +pos*70), fill=band1) # 1st digit
img.rectangle((113,70 +pos*70,123,110 +pos*70), fill=band2) # 2nd digit
img.rectangle((126,70 +pos*70,136,110 +pos*70), fill=band3) # 'zeroes'
img.rectangle((148,70 +pos*70,158,110 +pos*70), fill=band4) # tolerance
# create an exit handler
def quit():
app_lock.signal()
initialize()
app_lock = e32.Ao_lock()
app_lock.wait()


.. don't have a symbian phone? try an S60 Emulator:

I also have a PC(Windows) version created in MS Visual C# (*requires dotNET Framework):
download: parallel 2R.rar
forum link: parallel two resistors

Saturday, October 3, 2009

USB-based Loader circuit for DS89C4x0

Here's an alternative flash loader/programmer circuit for Maxim's DS89C4x0 microcontrollers. Most of the circuit parts came from a cheap Nokia data cable bought at CDR-King.

from the conventional "Serial Load Hardware Configuration":
to this one:*uses PL2303 from this cable: CHEAP USB-serial interface cable for our MCU projects!
*completely USB-powered
*no other addtional IC (e.g 74xx125)
**but still need to place the external crystal on the DS89C4x0


inside the cdrking's nokia data cable:
connections (tapping of wires):
actual circuit:*has a pull-up on P3.7 pin (only for some batches of ds89c420 as indicated in their errata)

the 40-pin DIP DS89C420 (obsolete part):
the MTK (Loader software):*the actual hardware is not working with version 2.4.10
*works also with Loader420 and hyperterminal..
dalsemi.com/microcontroller/dev_tool_software/mtk/obsolete/

demo ("classic" LED blinker program):

SDCC code:Compiled using M-IDE with SDCC