// PACKGEN.C Written in Imagecraft C Ver.5.0 10/2000 // for ther 68HC11 microcontroller // All rights reserved by Don Carveth. This program may be used in whole // or in part for non-commercial uses without permission. If used // for commercial purposes permission from the author is required. // This purpose of this program is to send a repeating test data // packet from the SCIport to a PC. // The test packet is formatted as either ASCII Hex or // as 5050 characters. The test packet consists of three variables: // one character, one integer and one string[5]. The character and // integer are ramped from near rail to rail to simulate changing // real world values. The string oscillates between two values. // The receiving PC must have software configured to accept the same // packet and data format. // The ASCII Hex packet is formatted as: // ;NnDdDdDdDdDd....Xx // where // ; is the start character // Nn are the MS nibble and LS nibble of the Node Number byte // Dd are the MS nibble and LS nibble of the Data bytes // Xx are the MS nibble and LS nibble of the checksum byte // The receiving device must know the packet length based on the node number. // The 5050 packet is formatted the same except: // - A sync string prefix is added: UUUUU and 0xFF // - an extra identical start character is added // - all characters except the sync & start characters are converted // from ASCII hex to 5050 characters. // - A suffix is added: UU // The packet becomes UUUUU ;;NnDdDdDdDd...XxUU where all // N,n,D,d,X,x are mapped to 5050 characters. // This program listing contains some code required for C++ Builder. The // program was developed in C++ Builder, tested and debugged, then moved // to the Imagecraft IDE for compilation to an S19 file for the HC11. // Note the use of INT16S and CHARU as variable types. By defining these // to be the same length in both Builder and Imagecraft the ambiguity of // "char" and "int" is removed. // //------------------------------ PROGRAM START // Comment this section out for HC11 or HC12 // #pragma hdrstop // #include // #include // #include // #pragma argsused // #define ONE_MS 32000 // //Comment this section out for PC #define ONE_MS 160 // #include #include "StdDefs.c" #include #include "vectors.c" //----------------------------------- Defines #define MAX_PACKET_LEN 40 #define START_CHAR ';' //---------------------------- Variable Declarations INT16S LC; CHARU c; INT16S cFlag = 1; CHARU packet[MAX_PACKET_LEN]; INT16S PackPtr; CHARU C1; /* Variables being sent to host */ INT16S C1flag = 1; INT16S I1; INT16S I1flag = 1; CHARU S1[5] = {'A','B','1','2','3'}; INT16S Sflag = 1; CHARU *Sptr; CHARU FFTable[23] = {0x3C,0x47,0x4B,0x33,0x4E,0x35,0x36,0x59,0x5A,0x39, 0x63,0x65,0x66,0x69,0x6A,0x6C,0x71,0x72,0x74,0x78, 0x4D,0x53,0x56}; //----------------------------- Function Declarations void initialize(void); void RampVars(void); void BuildAHPacket(void); void Build5050Packet(void); void SendPacket(void); void run_led(void); void msleep(INT16S ms); INT16S NewInt(INT16S, INT16S*, INT16S); //------------------------------------ MAIN // int main(int argc, char **argv) /* For PC only */ void main(void) { initialize(); for (;;) { RampVars(); PORTA |= 0x20; /* Turn transmitter power on */ Build5050Packet(); /* Use this for 5050 output, or */ // BuildAHPacket(); /* this for ASCII Hex output - not both */ SendPacket(); PORTA &= ~0x20; /* Turn transmitter power off */ run_led(); LC++; msleep(500); } // return 0; /* For PC only */ } //--------------------------------- Initialize void initialize(void) { // Comment out all content for PC INTR_OFF(); setbaud(BAUD4800); /* Set to match radio */ INTR_ON(); } //--------------------------------- Misc Utilities void run_led(void) { // Comment out all content for PC if (PORTA & 0x40) PORTA &= ~0x40; else PORTA |= 0x40; } void msleep(INT16S ms) { INT16S i,j; for (i = 1; i < ms; i++) for (j = 1; j < ONE_MS; j++); /* to give 1 ms*/ } //--------------------------- Ramping Variables Routines /* Ramps a char variable up/down by increment amount */ CHARU NewChar(CHARU CharVar, INT16S *CVFlag, INT16S increment) { return (char)NewInt((INT16S)CharVar, CVFlag, increment); } /* Ramps an integer variable up/down by increment amount */ INT16S NewInt(INT16S IntVar, INT16S *IVFlag, INT16S increment) { if (*IVFlag == 1) { IntVar += increment; if ((32000 - IntVar) < increment) *IVFlag = 0; } else { IntVar -= increment; if ((IntVar - 3) < increment) *IVFlag = 1; } return IntVar; } void RampVars(void) /* Used for testing, automatically ramps the test variable int and char from near max to near min values, string variable is toggled between two strings */ { int i; C1 = NewChar(C1,&C1flag,10); /* Ramp character value every scan */ I1 = NewInt(I1,&I1flag,1000); /* Ramp integer value every scan */ Sptr = &S1[0]; /* Alternate string value between "AAAAA" and "BBBBB" */ if (Sflag == 1) { for (i = 0; i < 5; i++) S1[i] = 'A'; Sflag = 0; } else { for (i = 0; i < 5; i++) S1[i] = 'B'; Sflag = 1; } } //------------------------------- Comm Routines INT16S hex_to_int(CHARU MSB, CHARU LSB) { INT16S intval; if (LSB > 0x2Fu) LSB = LSB - 0x30u; else LSB = 0u; if (LSB > 0x9u) LSB = LSB - 7; if (MSB > 0x2Fu) MSB = MSB - 0x30u; else MSB = 0u; if (MSB > 0x9u) MSB = MSB - 7; MSB = MSB * 16; intval = LSB + MSB; return intval; } CHARU char_to_hex(CHARU c) /* Returns ASCII value for 0-F */ { if (c < 10) c = c + 0x30; else c = c + 0x37; return c; } void AddChar(CHARU CharVar, INT16S *pptr) { packet[*pptr] = char_to_hex((CharVar >> 4) & 0x0F); packet[*pptr + 1] = char_to_hex(CharVar & 0x0F); *pptr += 2; } void AddInt(INT16S IntVar, INT16S *pptr) { packet[*pptr] = char_to_hex((IntVar >> 12) & 0x0F); packet[*pptr + 1] = char_to_hex((IntVar >> 8) & 0x0F); packet[*pptr + 2] = char_to_hex((IntVar >> 4) & 0x0F); packet[*pptr + 3] = char_to_hex(IntVar & 0x0F); *pptr += 4; } void AddStr(CHARU *StrVar, INT16S SLen, INT16S *pptr) { INT16S i; for (i = 0; i < SLen; i++) { packet[*pptr + (2*i)] = char_to_hex((*(StrVar+i) >> 4) & 0x0F); packet[*pptr + (2*i) + 1] = char_to_hex((*(StrVar+i)) & 0x0F); } *pptr = *pptr + (2*i); } void AddChecksum(CHARU *pack, INT16S pptrLess1) /* Packet must consist of hex pairs, starts from first char passed. Calcs checksum by adding each hex pair value - checksum is LSB of result. Adds two hex bits as checksum to packet. */ { INT16S sumx, i; CHARU cs; sumx = 0; for (i = 0; i < pptrLess1; i+= 2) sumx = sumx + hex_to_int(*(pack + i), *(pack + i + 1)); cs = sumx & 0xFF; *(pack + pptrLess1) = char_to_hex((cs >> 4) & 0x0F); *(pack + pptrLess1 + 1) = char_to_hex(cs & 0x0F); } void HA_To5050(CHARU *pack, INT16S LengthLess1) { int j; for (j = 0; j <= LengthLess1; j++) *(pack + j) = FFTable[*(pack + j) - 0x30]; } void AddPreamble(void) { packet[0] = 'U'; packet[1] = 'U'; packet[2] = 'U'; packet[3] = 'U'; packet[4] = 'U'; packet[5] = 0xFF; packet[6] = START_CHAR; packet[7] = START_CHAR; } void BuildAHPacket(void) { packet[0] = START_CHAR; packet[1] = '0'; /* Node 01 */ packet[2] = '1'; PackPtr = 3; AddChar(C1, &PackPtr); AddInt(I1, &PackPtr); Sptr = &S1[0]; AddStr(Sptr, 5, &PackPtr); Sptr = &packet[1]; AddChecksum(Sptr, PackPtr - 1); PackPtr += 2; } void Build5050Packet(void) { AddPreamble(); packet[8] = '0'; /* Node 01 */ packet[9] = '1'; PackPtr = 10; AddChar(C1, &PackPtr); AddInt(I1, &PackPtr); Sptr = &S1[0]; AddStr(Sptr, 5, &PackPtr); Sptr = &packet[8]; AddChecksum(Sptr, PackPtr - 8); PackPtr += 2; HA_To5050(Sptr, PackPtr - 9); packet[PackPtr] = 'U'; packet[PackPtr] = 'U'; PackPtr += 2; } void SendPacket(void) { INT16S i; // Comment out for HC11, HC12 // for (i = 0; i <= PackPtr; i++) // cout << packet[i]; // cout << endl; // getch(); // // Comment out for PC for (i = 0; i <= PackPtr; i++) putchar(packet[i]); // }