#include #include #include // RTS is connected to PGC for clock // CTS is connected to PGD for reading back data // TXD is also connected to PGD via a 4.7k resistor for sending data // SETBREAK makes PGD low // SETRTS makes PGC low typedef unsigned short U16; typedef unsigned char U8; char *_pszPort="COM1"; HANDLE _hComm=INVALID_HANDLE_VALUE; static void SetPGC(int n) { EscapeCommFunction(_hComm,n ? CLRRTS : SETRTS); } static void SetPGD(int n) { EscapeCommFunction(_hComm,n ? CLRBREAK : SETBREAK); } static void Prompt(char *psz) { printf("\n%s. Hit any key to continue.",psz); getch(); while (kbhit()) { getch(); } } static void BitSend(int n) { SetPGD(n & 1); SetPGC(1); SetPGC(0); } static int BitRead(void) { DWORD dw; SetPGC(1); GetCommModemStatus(_hComm,&dw); SetPGC(0); return (dw & MS_CTS_ON) ? 0 : 1; } static void CmdSend(U8 u8) { int n; u8&=0x3F; for (n=0;n<6;n++) { BitSend(u8); u8>>=1; } } static void DataSend(U16 u16) { int n; u16<<=1; u16&=0x7FFE; for (n=0;n<16;n++) { BitSend(u16 & 0x01); u16>>=1; } } static U16 DataRead(void) { int n; U16 u16=0; for (n=0;n<16;n++) { u16=(u16>>1) | (BitRead() ? 0x8000 : 0); } return (u16>>1) & 0x3FFF; } static void CmdLoadConfiguration(void) { CmdSend(0x00); DataSend(0x3FFF); /* Send dummy data */ } static void CmdLoadDataProgram(U16 u16) { CmdSend(0x02); DataSend(u16); } static void CmdLoadDataMemory(U16 u16) { CmdSend(0x03); DataSend(u16); } static U16 CmdReadDataProgram(void) { CmdSend(0x04); return DataRead(); } static U16 CmdReadDataMemory(void) { CmdSend(0x05); return DataRead(); } static void CmdEraseProgram(U16 u16Wait) { CmdSend(0x08); Sleep(u16Wait); } static void CmdIncrement(void) { CmdSend(0x06); } static void CmdBulkEraseSetup1(void) { CmdSend(0x01); } static void CmdBulkEraseSetup2(void) { CmdSend(0x07); } static void CmdProgram(U16 u16Wait) { CmdSend(0x18); Sleep(u16Wait); } static void CmdChipErase(void) { CmdSend(0x1F); Sleep(10); } static void CmdEndProgramming(void) { CmdSend(0x17); } static BOOL ReadHexDigit(char *psz,U8 *pu8) { char c=*psz; if (c>='0' && c<='9') { *pu8=c-'0'; } else { if (c>='a' && c<='f') { *pu8=c-'a'+10; } else { if (c>='A' && c<='F') { *pu8=c-'A'+10; } else { return FALSE; } } } return TRUE; } static BOOL ReadHexPair(char *psz,U8 *pu8) { U8 u8; if (psz[0]=='\0' || psz[1]=='\0') { return FALSE; } if (!ReadHexDigit(psz,&u8)) { return FALSE; } *pu8=u8<<4; if (!ReadHexDigit(psz+1,&u8)) { return FALSE; } *pu8|=u8 & 0x0F; return TRUE; } int main(int nArgs,char *apszArgs[]) { FILE *pfIn=NULL; DCB dcb; U16 u16PC=0; int nLine=0; BOOL bFinished=FALSE; U16 au16Data[16384]; U16 u16DeviceID; fprintf(stderr,"LVB Tracker firmware uploader v0.2 G6LVB\n"); { int n; for (n=0;n<16384;n++) { au16Data[n]=0x3FFF; } } // Default config bits... // Osc=XT, WDT off, PUT on, BOD off, LVP off, FPW on, DBG off, data EE prot off, CodeProt off au16Data[0x2007]=0x3F31; if (nArgs<=1) { fprintf(stderr,"Usage: %0 []\n"); fprintf(stderr,"where is of the from COM1, COM2 etc. Default is COM1.\n"); return -1; } if (nArgs>=3) { _pszPort=apszArgs[2]; } if ((pfIn=fopen(apszArgs[1],"rb"))==NULL) { fprintf(stderr,"OS Error: %d. Unable to open file: %s\n",_doserrno,apszArgs[1]); return _doserrno; } printf("Reading Hex file...\n"); while (!feof(pfIn) && !bFinished) { char szLine[1024]; char *psz=szLine; U8 u8Len; U16 u16Addr; U8 u8RecType; U8 u8; U8 u8Checksum=0; int n; if (fgets(szLine,sizeof(szLine)-1,pfIn)!=NULL) { szLine[1023]='\0'; if (szLine[strlen(szLine)-1]=='\r') { szLine[strlen(szLine)-1]='\0'; } nLine++; } else { if (!feof(pfIn)) { fprintf(stderr,"OS Error: %d. fgets() failed on file %s\n",_doserrno,apszArgs[1]); fclose(pfIn); pfIn=NULL; return _doserrno; } else { break; } } if (*psz++!=':') { fprintf(stderr,"':' expected in file %s, line %d\n",apszArgs[1],nLine); fclose(pfIn); pfIn=NULL; return -1; } if (!ReadHexPair(psz,&u8Len)) { fprintf(stderr,"Record length hexadecimal pair expected in file %s, line %d, position %d\n",apszArgs[1],nLine,psz-szLine); fclose(pfIn); pfIn=NULL; return -1; } u8Checksum+=u8Len; psz+=2; if ((u8Len & 1)!=0) { fprintf(stderr,"Record length must be even in file %s, line %d, position %d\n",apszArgs[1],nLine,psz-szLine); fclose(pfIn); pfIn=NULL; return -1; } u8Len>>=1; if (!ReadHexPair(psz,&u8)) { fprintf(stderr,"Load address high hexadecimal pair expected in file %s, line %d, position %d\n",apszArgs[1],nLine,psz-szLine); fclose(pfIn); pfIn=NULL; return -1; } u8Checksum+=u8; psz+=2; u16Addr=((U16)u8)<<8; if (!ReadHexPair(psz,&u8)) { fprintf(stderr,"Load address low hexadecimal pair expected in file %s, line %d, position %d\n",apszArgs[1],nLine,psz-szLine); fclose(pfIn); pfIn=NULL; return -1; } u8Checksum+=u8; psz+=2; u16Addr|=u8; if ((u16Addr & 0x01)!=0) { fprintf(stderr,"Invalid load address (must be even) in file %s, line %d, position %d\n",apszArgs[1],nLine,psz-szLine); fclose(pfIn); pfIn=NULL; return -1; } u16Addr>>=1; if (!ReadHexPair(psz,&u8RecType)) { fprintf(stderr,"Record type hexadecimal pair expected in file %s, line %d, position %d\n",apszArgs[1],nLine,psz-szLine); fclose(pfIn); pfIn=NULL; return -1; } u8Checksum+=u8RecType; psz+=2; switch(u8RecType) { case 0: for (n=0;n