CCS PCW C Compiler, Version 3.068, 13348 Filename: /usr3/ha/hcs_II/hcs/ccc/t.LST ROM used: 887 (87%) Largest free fragment is 137 RAM used: 47 (69%) at main() level 53 (78%) worst case Stack: 3 worst case (2 in main + 1 for interrupts) * 0000: MOVLW 00 0001: MOVWF 0A 0002: GOTO 16D 0003: NOP 0004: BTFSC 03.5 0005: GOTO 00A 0006: MOVWF 0E 0007: SWAPF 03,W 0008: MOVWF 0F 0009: GOTO 00F 000A: BCF 03.5 000B: MOVWF 0E 000C: SWAPF 03,W 000D: MOVWF 0F 000E: BSF 0F.1 000F: SWAPF 0E,F 0010: MOVF 04,W 0011: MOVWF 10 0012: MOVF 0C,W 0013: MOVWF 11 0014: MOVF 0D,W 0015: MOVWF 12 0016: BCF 03.5 0017: BTFSS 0B.5 0018: GOTO 01B 0019: BTFSC 0B.2 001A: GOTO 089 001B: MOVF 10,W 001C: MOVWF 04 001D: MOVF 11,W 001E: MOVWF 0C 001F: MOVF 12,W 0020: MOVWF 0D 0021: SWAPF 0F,W 0022: MOVWF 03 0023: BCF 03.5 0024: SWAPF 0E,W 0025: BTFSC 0F.1 0026: BSF 03.5 0027: RETFIE .................... #INCLUDE <16f84.h> .................... //////// Standard Header file for the PIC16F84 device //////////////// .................... #device PIC16F84 .................... #list .................... .................... .................... #opt 9 .................... .................... #FUSES XT, NOWDT, NOPROTECT, NOPUT // We actually want the Powerup Timer, but my programmer gets it backwards! .................... #USE DELAY (CLOCK=4000000) * 0137: MOVLW 37 0138: MOVWF 04 0139: MOVF 00,W 013A: BTFSC 03.2 013B: GOTO 14B 013C: MOVLW 01 013D: MOVWF 0D 013E: CLRF 0C 013F: DECFSZ 0C,F 0140: GOTO 13F 0141: DECFSZ 0D,F 0142: GOTO 13E 0143: MOVLW 4A 0144: MOVWF 0C 0145: DECFSZ 0C,F 0146: GOTO 145 0147: NOP 0148: NOP 0149: DECFSZ 00,F 014A: GOTO 13C 014B: GOTO 335 (RETURN) .................... .................... #USE FAST_IO(A) .................... #USE FAST_IO(B) .................... .................... #ZERO_RAM // Saves us any trouble! .................... .................... // Buffer only needs to be 16 - we'll give it 20 .................... #define BUFFER_SIZE 20 .................... .................... // EEPROM memory map .................... #define saved_node_addr 0 .................... .................... #Bit T0IF = 0x0B.2 // Map name to RTCC interrupt flag .................... .................... struct porta_map { .................... boolean strobe; .................... boolean config; .................... boolean serial_enable; .................... boolean serial_out; .................... boolean serial_in; .................... int not_used : 3; .................... } porta; .................... .................... #byte porta = 0x05 .................... #byte portb = 0x06 .................... #byte OPTION = 0x81 .................... .................... // Globals .................... // Buffer is split in two becuase compiler can't handle array's which cross .................... // a memory page. .................... char buffer1[BUFFER_SIZE]; .................... .................... int serial_idx, process_idx, idx, scratch; .................... boolean p_idle; // When TRUE, the buffer is not being processed .................... boolean s_idle; // When TRUE, we are NOT receiving a packet .................... boolean go_data; // When TRUE, we have a packet to munch .................... boolean a_check; .................... .................... .................... // Serial routine .................... .................... // Since we want to use all of Port B for IO (need the pullups) .................... // We'll use the RTCC input to generate an interrupt when a start bit arrives .................... // To do this, we setup RTCC to increment on High to Low transitions and set it to 0xFF .................... // We simply increment RTCC on the falling edge and generate a rollover interrupt .................... .................... #INT_RTCC .................... void serial_in() { .................... char data_in; .................... int sidx, samp_cnt; .................... .................... // Lets receive the data at 9600 bps (104us per bit) .................... // We have 1 us per inst at 4MHz .................... // Int Handler takes ~21 instructions .................... .................... // Ensure it was not a glitch (this takes 3 us) .................... if (porta.serial_in) { * 0089: BTFSS 05.4 008A: GOTO 08E .................... set_rtcc(0xFF); // Reset interrupt 008B: MOVLW FF 008C: MOVWF 01 .................... return; 008D: GOTO 0EC .................... } .................... .................... delay_us(120); // Need to delay 1.5B (156us) We already have 21 int instructions = 21us + 3us above 008E: MOVLW 27 008F: MOVWF 0C 0090: DECFSZ 0C,F 0091: GOTO 090 0092: NOP 0093: NOP .................... // There are 12 inst until the middle sample - remove 12us more so we sync properly .................... // Thus we delay 156-(21 + 3 + 12) = 124us (Subtract 3 more for initial 3us delay) .................... .................... for(sidx=0; sidx<8; sidx++) { 0094: CLRF 3E 0095: MOVF 3E,W 0096: SUBLW 07 0097: BTFSS 03.0 0098: GOTO 0B7 .................... // To ensure the bit is read ok, lets sample the bit 3 times at 3us intervals .................... // Majority rules for the value .................... .................... // Lets sample over 15us .................... samp_cnt = porta.serial_in; 0099: CLRF 3F 009A: BTFSC 05.4 009B: INCF 3F,F .................... delay_us(3); 009C: NOP 009D: NOP 009E: NOP .................... if (porta.serial_in) { samp_cnt++; } 009F: BTFSS 05.4 00A0: GOTO 0A2 00A1: INCF 3F,F .................... delay_us(3); 00A2: NOP 00A3: NOP 00A4: NOP .................... if (porta.serial_in) { samp_cnt++; } 00A5: BTFSS 05.4 00A6: GOTO 0A8 00A7: INCF 3F,F .................... delay_us(3); 00A8: NOP 00A9: NOP 00AA: NOP .................... .................... shift_right(&data_in, 1, bit_test(samp_cnt,1)); // If samp_cnt = 0|1 -> 0 2|3 -> 1 00AB: BTFSC 3F.1 00AC: GOTO 0AF 00AD: BCF 03.0 00AE: GOTO 0B0 00AF: BSF 03.0 00B0: RRF 3D,F .................... delay_us(76); // 104us - 28us of instructions (28 inst) for loop = 76us 00B1: MOVLW 19 00B2: MOVWF 0C 00B3: DECFSZ 0C,F 00B4: GOTO 0B3 .................... } 00B5: INCF 3E,F 00B6: GOTO 095 .................... .................... // Lets setup RTCC for next start bit .................... set_rtcc(0xFF); // Roll over on next drop 00B7: MOVLW FF 00B8: MOVWF 01 .................... .................... // That's it! Lets act on the data... .................... // We are looking for the start of a packet. .................... // Otherwise we stay in this state and ignore the incoming char .................... if (s_idle) { 00B9: BTFSS 2B.1 00BA: GOTO 0CB .................... if ((data_in == '!') || (data_in == '#')) { 00BB: MOVF 3D,W 00BC: SUBLW 21 00BD: BTFSC 03.2 00BE: GOTO 0C3 00BF: MOVF 3D,W 00C0: SUBLW 23 00C1: BTFSS 03.2 00C2: GOTO 0CA .................... // New Packet - Lets go to the front of the buffer .................... serial_idx = 0; 00C3: CLRF 27 .................... buffer1[serial_idx] = data_in; 00C4: MOVLW 13 00C5: ADDWF 27,W 00C6: MOVWF 04 00C7: MOVF 3D,W 00C8: MOVWF 00 .................... s_idle = FALSE; 00C9: BCF 2B.1 .................... } .................... } else { 00CA: GOTO 0EC .................... if (++serial_idx == BUFFER_SIZE) { 00CB: INCF 27,F 00CC: MOVF 27,W 00CD: SUBLW 14 00CE: BTFSS 03.2 00CF: GOTO 0D3 .................... // Buffer Overflow - lets dump it since the checksum won't validate anyway .................... s_idle = TRUE; 00D0: BSF 2B.1 .................... a_check = FALSE; // Reset the address check for the next packet 00D1: BCF 2B.3 .................... } else { 00D2: GOTO 0EC .................... // If the buffer is being processed, make sure we don't catch up .................... if (!p_idle) { 00D3: BTFSC 2B.0 00D4: GOTO 0DC .................... if (serial_idx == process_idx) { 00D5: MOVF 28,W 00D6: SUBWF 27,W 00D7: BTFSS 03.2 00D8: GOTO 0DC .................... // We caught up! Dump the buffer .................... s_idle = TRUE; 00D9: BSF 2B.1 .................... a_check = FALSE; // Reset the address check for the next packet 00DA: BCF 2B.3 .................... return; 00DB: GOTO 0EC .................... } .................... } .................... .................... // Check for the end of the packet .................... if ((data_in == '\r') || (data_in == '\n')) { 00DC: MOVF 3D,W 00DD: SUBLW 0D 00DE: BTFSC 03.2 00DF: GOTO 0E4 00E0: MOVF 3D,W 00E1: SUBLW 0A 00E2: BTFSS 03.2 00E3: GOTO 0E7 .................... go_data = TRUE; // Tell main program to process buffer 00E4: BSF 2B.2 .................... s_idle = TRUE; 00E5: BSF 2B.1 .................... } else { 00E6: GOTO 0EC .................... // Save the data .................... buffer1[serial_idx] = data_in; 00E7: MOVLW 13 00E8: ADDWF 27,W 00E9: MOVWF 04 00EA: MOVF 3D,W 00EB: MOVWF 00 .................... } .................... } .................... } 00EC: BCF 0B.2 00ED: BCF 0A.3 00EE: GOTO 01B .................... } .................... .................... .................... // This routine sends a serial byte .................... .................... // TUNED FOR 4MHz! .................... .................... void send_serial_byte(byte byte_in) { .................... .................... int bitc; .................... .................... // Sending a serial byte is fairly easy .................... // Disable interrupt since data is looped in RS485 chip .................... // Send RS485 enable bit high .................... // Send start bit (LOW) .................... // Delay 104us .................... // Shift data bits (8) onto serial out - wait 104us .................... // Send stop bit (HIGH) .................... // Clear EXT interrupt flag .................... // Re-enable EXT interrupt .................... // Delay 104us for stop bit .................... .................... disable_interrupts(INT_RTCC); 00EF: BCF 0B.5 .................... porta.serial_enable = 1; 00F0: BSF 05.2 .................... //#asm .................... // nop .................... //#endasm .................... delay_cycles(1); 00F1: NOP .................... porta.serial_out = 0; 00F2: BCF 05.3 .................... .................... // Delay 104us minus 9 inst cycles to get first bit out - 9us = 95 .................... delay_us(95); 00F3: MOVLW 1F 00F4: MOVWF 0C 00F5: DECFSZ 0C,F 00F6: GOTO 0F5 00F7: NOP .................... .................... for(bitc = 0; bitc < 8; ++bitc) { 00F8: CLRF 3A 00F9: MOVF 3A,W 00FA: SUBLW 07 00FB: BTFSS 03.0 00FC: GOTO 10A .................... // Lets send the bits .................... porta.serial_out = shift_right(&byte_in,1,0); 00FD: BCF 03.0 00FE: RRF 39,F 00FF: BTFSC 03.0 0100: GOTO 103 0101: BCF 05.3 0102: GOTO 104 0103: BSF 05.3 .................... .................... // Loop takes 13 instructions. @4MHz - 13us (104 - 13 = 91us) .................... delay_us(91); 0104: MOVLW 1E 0105: MOVWF 0C 0106: DECFSZ 0C,F 0107: GOTO 106 .................... } 0108: INCF 3A,F 0109: GOTO 0F9 .................... .................... // Now we send the stop bit and re-enable the interrupts .................... delay_us(4); // Allow last bit to finish 104us 010A: NOP 010B: NOP 010C: NOP 010D: NOP .................... porta.serial_out = 1; 010E: BSF 05.3 .................... delay_us(1); // Allow line to stabilize 010F: NOP .................... .................... // Now we can re-enable our interrupts .................... T0IF = FALSE; // Clear the INT bit which would be set above during send 0110: BCF 0B.2 .................... enable_interrupts(INT_RTCC); 0111: BSF 0B.5 .................... set_rtcc(0xFF); 0112: MOVLW FF 0113: MOVWF 01 .................... .................... // Delay for the rest of the stop bit time .................... // We have 6 inst above plus 3 to return -> 104 - 9 = 98us .................... delay_us(95); 0114: MOVLW 1F 0115: MOVWF 0C 0116: DECFSZ 0C,F 0117: GOTO 116 0118: NOP .................... .................... porta.serial_enable = 0; // Disable 485 driver 0119: BCF 05.2 011A: RETLW 00 .................... } .................... .................... .................... // This routine is used to convert characters for checking the checksum .................... // It simply converts an ASCII hex value into true decimal form .................... // ASCII allows for a quick and dirty conversion routine! .................... .................... byte gethexbyte(char digit) { .................... if(!BIT_TEST(digit,6)) // Its a number if bit 6 is 0 011B: BTFSC 3B.6 011C: GOTO 122 .................... return(digit & 0x0F); // Simple way to convert 0-9 011D: MOVF 3B,W 011E: ANDLW 0F 011F: MOVWF 0D 0120: GOTO 127 .................... else 0121: GOTO 127 .................... return((digit & 0x0F) + 9); 0122: MOVF 3B,W 0123: ANDLW 0F 0124: ADDLW 09 0125: MOVWF 0D 0126: GOTO 127 0127: RETLW 00 .................... } .................... .................... // This routine converts an 4-bit hex value into an associated ASCII character .................... .................... byte byte_to_ascii(byte tdata) { .................... if (tdata <= 9) { 0128: MOVF 38,W 0129: SUBLW 09 012A: BTFSS 03.0 012B: GOTO 131 .................... return (tdata | 0x30); 012C: MOVF 38,W 012D: IORLW 30 012E: MOVWF 0D 012F: GOTO 136 .................... } else { 0130: GOTO 136 .................... return ((tdata - 9) | 0x40); 0131: MOVLW 09 0132: SUBWF 38,W 0133: IORLW 40 0134: MOVWF 0D 0135: GOTO 136 .................... } 0136: RETLW 00 .................... } .................... .................... void main () { .................... int endbuff, data, node_total, last_hcs_data; .................... boolean checksum, byte_query; * 016D: MOVLW 43 016E: MOVWF 0C 016F: MOVLW 0D 0170: MOVWF 04 0171: CLRF 00 0172: INCF 04,F 0173: DECFSZ 0C,F 0174: GOTO 171 0175: CLRF 20 0176: CLRF 04 0177: MOVLW 1F 0178: ANDWF 03,F .................... char thisnode[4], data_char[2]; .................... .................... PORT_B_PULLUPS(TRUE); // Since we tri state a High on port B 0179: BSF 03.5 017A: BCF 01.7 .................... .................... set_tris_b(0b11111111); // User will determine the directions 017B: MOVLW FF 017C: TRIS 6 .................... set_tris_a(0b11110010); // These shouldn't change 017D: MOVLW F2 017E: TRIS 5 .................... .................... porta.serial_enable = 0; 017F: BCF 03.5 0180: BCF 05.2 .................... //delay_cycles(1); .................... #asm .................... nop .................... #endasm 0181: NOP .................... porta.strobe = 1; // Init printer port 0182: BSF 05.0 .................... //delay_cycles(1); .................... #asm .................... nop .................... #endasm 0183: NOP .................... porta.serial_out = 1; // Leave serial out high 0184: BSF 05.3 .................... .................... // We'll use the RTCC rollover to initiate an interrupt for the start bit .................... .................... // Compiler doesn't seem to be doing this right - we'll do it ourselves .................... // Set bits 5, 4, 3 (External clock H to L, WDT prescale (RTCC = 1:1) .................... OPTION |= 0b00111000; 0185: MOVLW 38 0186: BSF 03.5 0187: IORWF 01,F .................... .................... last_hcs_data = 0xFF; // Assume all inputs from HCS to start 0188: MOVLW FF 0189: BCF 03.5 018A: MOVWF 2F .................... .................... // Lets see if they are trying to configure the chip .................... // If porta.config is low, they are! Read portb 0-2 and save value .................... // then loop forever. .................... if (!porta.config) { 018B: BTFSC 05.1 018C: GOTO 1C3 .................... // Lets config the system and output a message so they know we are okay .................... printf(send_serial_byte, "\nCreative Control Concepts Mini-DIO\nv1.0 July 1998\n"); * 0028: BCF 0A.0 0029: BCF 0A.1 002A: BCF 0A.2 002B: ADDWF 02,F 002C: RETLW 0A 002D: RETLW 43 002E: RETLW 72 002F: RETLW 65 0030: RETLW 61 0031: RETLW 74 0032: RETLW 69 0033: RETLW 76 0034: RETLW 65 0035: RETLW 20 0036: RETLW 43 0037: RETLW 6F 0038: RETLW 6E 0039: RETLW 74 003A: RETLW 72 003B: RETLW 6F 003C: RETLW 6C 003D: RETLW 20 003E: RETLW 43 003F: RETLW 6F 0040: RETLW 6E 0041: RETLW 63 0042: RETLW 65 0043: RETLW 70 0044: RETLW 74 0045: RETLW 73 0046: RETLW 20 0047: RETLW 4D 0048: RETLW 69 0049: RETLW 6E 004A: RETLW 69 004B: RETLW 2D 004C: RETLW 44 004D: RETLW 49 004E: RETLW 4F 004F: RETLW 0A 0050: RETLW 76 0051: RETLW 31 0052: RETLW 2E 0053: RETLW 30 0054: RETLW 20 0055: RETLW 4A 0056: RETLW 75 0057: RETLW 6C 0058: RETLW 79 0059: RETLW 20 005A: RETLW 31 005B: RETLW 39 005C: RETLW 39 005D: RETLW 38 005E: RETLW 0A 005F: RETLW 00 * 018D: CLRF 37 018E: MOVF 37,W 018F: CALL 028 0190: INCF 37,F 0191: MOVWF 39 0192: CALL 0EF 0193: MOVLW 33 0194: SUBWF 37,W 0195: BTFSS 03.2 0196: GOTO 18E .................... .................... // Read portb .................... scratch = (portb & 0b00000111) + 48; // Only save 3 bits 0197: MOVF 06,W 0198: ANDLW 07 0199: ADDLW 30 019A: MOVWF 2A .................... write_eeprom(saved_node_addr, scratch); // Save the address value 019B: CLRF 09 019C: MOVF 2A,W 019D: MOVWF 08 019E: MOVF 0B,W 019F: MOVWF 0C 01A0: MOVF 0B,W 01A1: MOVWF 0D 01A2: BCF 0B.7 01A3: BSF 03.5 01A4: BSF 08.2 01A5: MOVLW 55 01A6: MOVWF 09 01A7: MOVLW AA 01A8: MOVWF 09 01A9: BSF 08.1 01AA: BTFSC 08.1 01AB: GOTO 1AA 01AC: BCF 08.2 01AD: BCF 03.5 01AE: BTFSC 0C.7 01AF: MOVF 0D,W 01B0: MOVWF 0B .................... .................... printf(send_serial_byte, "\nAddress set to DIO%c\n", scratch); * 0060: BCF 0A.0 0061: BCF 0A.1 0062: BCF 0A.2 0063: ADDWF 02,F 0064: RETLW 0A 0065: RETLW 41 0066: RETLW 64 0067: RETLW 64 0068: RETLW 72 0069: RETLW 65 006A: RETLW 73 006B: RETLW 73 006C: RETLW 20 006D: RETLW 73 006E: RETLW 65 006F: RETLW 74 0070: RETLW 20 0071: RETLW 74 0072: RETLW 6F 0073: RETLW 20 0074: RETLW 44 0075: RETLW 49 0076: RETLW 4F 0077: RETLW 25 0078: RETLW 63 0079: RETLW 0A 007A: RETLW 00 * 01B1: CLRF 37 01B2: MOVF 37,W 01B3: CALL 060 01B4: INCF 37,F 01B5: MOVWF 39 01B6: CALL 0EF 01B7: MOVLW 13 01B8: SUBWF 37,W 01B9: BTFSS 03.2 01BA: GOTO 1B2 01BB: MOVF 2A,W 01BC: MOVWF 39 01BD: CALL 0EF 01BE: MOVLW 0A 01BF: MOVWF 39 01C0: CALL 0EF .................... while(TRUE) {}; // Endless loop; 01C1: GOTO 1C1 .................... } else { 01C2: GOTO 1EE .................... // Lets get our address .................... .................... thisnode[0] = 'D'; 01C3: MOVLW 44 01C4: MOVWF 31 .................... thisnode[1] = 'I'; 01C5: MOVLW 49 01C6: MOVWF 32 .................... thisnode[2] = 'O'; 01C7: MOVLW 4F 01C8: MOVWF 33 .................... .................... thisnode[3] = read_eeprom(saved_node_addr); 01C9: CLRF 09 01CA: BSF 03.5 01CB: BSF 08.0 01CC: BCF 03.5 01CD: MOVF 08,W 01CE: MOVWF 34 .................... .................... // If they haven't set an addr and its bogus, set it to 0 for them .................... if ((thisnode[3] > '7') || (thisnode[3] < '0')) { 01CF: MOVF 34,W 01D0: SUBLW 37 01D1: BTFSS 03.0 01D2: GOTO 1D7 01D3: MOVF 34,W 01D4: SUBLW 2F 01D5: BTFSS 03.0 01D6: GOTO 1EE .................... thisnode[3] = '0'; 01D7: MOVLW 30 01D8: MOVWF 34 .................... write_eeprom(saved_node_addr, '0'); 01D9: CLRF 09 01DA: MOVWF 08 01DB: MOVF 0B,W 01DC: MOVWF 0C 01DD: MOVF 0B,W 01DE: MOVWF 0D 01DF: BCF 0B.7 01E0: BSF 03.5 01E1: BSF 08.2 01E2: MOVLW 55 01E3: MOVWF 09 01E4: MOVLW AA 01E5: MOVWF 09 01E6: BSF 08.1 01E7: BTFSC 08.1 01E8: GOTO 1E7 01E9: BCF 08.2 01EA: BCF 03.5 01EB: BTFSC 0C.7 01EC: MOVF 0D,W 01ED: MOVWF 0B .................... } .................... } .................... .................... // Lets total up the set parts of the checksum (#, spaces, dummy checksum, and nodename) .................... // This saves us time during each packet .................... node_total = '#' + '0' + '0' + ' ' + ' ' + 'D' + 'I' + 'O'; 01EE: MOVLW 9F 01EF: MOVWF 2E .................... node_total += thisnode[3]; 01F0: MOVF 34,W 01F1: ADDWF 2E,F .................... .................... // Initial values for serial and buffer handling .................... s_idle = TRUE; 01F2: BSF 2B.1 .................... p_idle = TRUE; 01F3: BSF 2B.0 .................... go_data = FALSE; 01F4: BCF 2B.2 .................... serial_idx = 0; 01F5: CLRF 27 .................... .................... // Lets enable the interrupts! .................... disable_interrupts(GLOBAL); 01F6: BCF 0B.6 01F7: BCF 0B.7 01F8: BTFSC 0B.7 01F9: GOTO 1F7 .................... enable_interrupts(INT_RTCC); 01FA: BSF 0B.5 .................... T0IF = FALSE; 01FB: BCF 0B.2 .................... set_rtcc(0xFF); // get ready for first start bit 01FC: MOVLW FF 01FD: MOVWF 01 .................... enable_interrupts(GLOBAL); 01FE: BSF 0B.7 .................... .................... Buffer_Scan: .................... p_idle = TRUE; 01FF: BSF 2B.0 .................... a_check = FALSE; // Make sure we run address check only once 0200: BCF 2B.3 .................... process_idx = 0; 0201: CLRF 28 .................... .................... // Lets wait until the buffer has a valid packet for our node .................... // We check here and quite using the buffer if it isn't our packet .................... .................... while((!a_check) || (!go_data)) { 0202: BTFSS 2B.3 0203: GOTO 206 0204: BTFSC 2B.2 0205: GOTO 24A .................... .................... // Lets see if we get a packet with our address .................... // We can verify the checksum later - this gets us a quicker start .................... .................... // Once we hit the 9th buffer slot, lets check the address for a match .................... // a_check ensures we only run this once .................... // !s_idle || go_data ensures we are either receiving or have received a new buffer .................... // This is required since there is a chance we'll get an entire new buffer (s_idle TRUE) .................... // before we even enter this loop (long previous packet) .................... if (!a_check && (!s_idle || go_data) && (serial_idx > 6)) { 0206: BTFSC 2B.3 0207: GOTO 249 0208: BTFSS 2B.1 0209: GOTO 20C 020A: BTFSS 2B.2 020B: GOTO 249 020C: MOVF 27,W 020D: SUBLW 06 020E: BTFSC 03.0 020F: GOTO 249 .................... // 8th character is now in the buffer .................... a_check = TRUE; 0210: BSF 2B.3 .................... .................... if (buffer1[0] == '#') { 0211: MOVF 13,W 0212: SUBLW 23 0213: BTFSS 03.2 0214: GOTO 219 .................... scratch = 4; 0215: MOVLW 04 0216: MOVWF 2A .................... checksum = TRUE; 0217: BSF 30.0 .................... } else { 0218: GOTO 21C .................... scratch = 2; 0219: MOVLW 02 021A: MOVWF 2A .................... checksum = FALSE; 021B: BCF 30.0 .................... } .................... .................... // Let's check the address. If it isn't ours, we skip .................... for(idx = 0; idx < 4; idx++) { 021C: CLRF 29 021D: MOVF 29,W 021E: SUBLW 03 021F: BTFSS 03.0 0220: GOTO 233 .................... if (thisnode[idx] != buffer1[scratch++]) { 0221: MOVLW 31 0222: ADDWF 29,W 0223: MOVWF 04 0224: MOVF 00,W 0225: MOVWF 37 0226: MOVF 2A,W 0227: INCF 2A,F 0228: ADDLW 13 0229: MOVWF 04 022A: MOVF 00,W 022B: SUBWF 37,W 022C: BTFSC 03.2 022D: GOTO 231 .................... // Not our packet! .................... s_idle = TRUE; // Reset buffer - scan for packet start 022E: BSF 2B.1 .................... go_data = FALSE; // Until the next valid packet 022F: BCF 2B.2 .................... goto Buffer_Scan; 0230: GOTO 1FF .................... } .................... } 0231: INCF 29,F 0232: GOTO 21D .................... .................... if (checksum) { 0233: BTFSS 30.0 0234: GOTO 247 .................... // convert ascii to hex byte .................... scratch = ((gethexbyte(buffer1[1]) << 4) | gethexbyte(buffer1[2])); 0235: MOVF 14,W 0236: MOVWF 3B 0237: CALL 11B 0238: SWAPF 0D,W 0239: MOVWF 38 023A: MOVLW F0 023B: ANDWF 38,F 023C: MOVF 15,W 023D: MOVWF 3B 023E: CALL 11B 023F: MOVF 38,W 0240: IORWF 0D,W 0241: MOVWF 2A .................... .................... process_idx = 9; // Give the buffer some breathing room 0242: MOVLW 09 0243: MOVWF 28 .................... .................... // Lets add the nodename and default chars (#, space, 00 for default checksum) .................... scratch += node_total; 0244: MOVF 2E,W 0245: ADDWF 2A,F .................... } else { 0246: GOTO 249 .................... process_idx = 7; // Give the buffer some breathing room 0247: MOVLW 07 0248: MOVWF 28 .................... } .................... } .................... } 0249: GOTO 202 .................... .................... // Okay, lets process the packet .................... p_idle = FALSE; // Let the interrupt routine know we are processing a buffer 024A: BCF 2B.0 .................... endbuff = serial_idx; // So we know where the end of the buffer is! 024B: MOVF 27,W 024C: MOVWF 2C .................... go_data = FALSE; 024D: BCF 2B.2 .................... .................... // Lets finish adding and validate the checksum .................... if (checksum) { 024E: BTFSS 30.0 024F: GOTO 261 .................... idx = 9; // Skip first 10 chars in buffer 0250: MOVLW 09 0251: MOVWF 29 .................... while (idx < endbuff) { 0252: MOVF 2C,W 0253: SUBWF 29,W 0254: BTFSC 03.0 0255: GOTO 25D .................... scratch += buffer1[idx++]; 0256: MOVF 29,W 0257: INCF 29,F 0258: ADDLW 13 0259: MOVWF 04 025A: MOVF 00,W 025B: ADDWF 2A,F .................... } 025C: GOTO 252 .................... .................... // Need the lower 8 bits to compare .................... if (scratch != 0) { 025D: MOVF 2A,F 025E: BTFSC 03.2 025F: GOTO 261 .................... // Bad Checksum .................... goto Buffer_Scan; 0260: GOTO 1FF .................... } .................... } .................... .................... // Command handling .................... // The PIC DIO watches for the following commands: .................... // Note space after command is optional! .................... .................... // Byte Set: DIO# S DP=(hex byte) .................... // Bit Set: DIO# S DP.(bit num 0-7)=0 or 1 .................... // Byte Read: DIO# Q DP .................... // Bit Read: DIO# Q DP.(bit num 0-7) .................... .................... scratch = buffer1[process_idx]; // Lets get the command 0261: MOVLW 13 0262: ADDWF 28,W 0263: MOVWF 04 0264: MOVF 00,W 0265: MOVWF 2A .................... .................... // Lets allow a space between the command letter and DP .................... if (buffer1[++process_idx] == ' ') { process_idx++; } 0266: INCF 28,F 0267: MOVLW 13 0268: ADDWF 28,W 0269: MOVWF 04 026A: MOVF 00,W 026B: SUBLW 20 026C: BTFSS 03.2 026D: GOTO 26F 026E: INCF 28,F .................... .................... switch(scratch) { 026F: MOVF 2A,W 0270: MOVWF 0C 0271: MOVLW 53 0272: SUBWF 2A,W 0273: BTFSC 03.2 0274: GOTO 27A 0275: MOVLW 51 0276: SUBWF 0C,W 0277: BTFSC 03.2 0278: GOTO 2DC 0279: GOTO 374 .................... case('S'): .................... // Its a set command, bit or byte .................... process_idx += 2; // skip to = or bit number 027A: MOVLW 02 027B: ADDWF 28,F .................... if (buffer1[process_idx] == '=') { 027C: MOVLW 13 027D: ADDWF 28,W 027E: MOVWF 04 027F: MOVF 00,W 0280: SUBLW 3D 0281: BTFSS 03.2 0282: GOTO 29F .................... // Its a byte set - easy! .................... // Convert the ASCII hex into a real hex value .................... last_hcs_data = (gethexbyte(buffer1[++process_idx]) * 16) + gethexbyte(buffer1[++process_idx]); 0283: INCF 28,F 0284: MOVLW 13 0285: ADDWF 28,W 0286: MOVWF 04 0287: MOVF 00,W 0288: MOVWF 37 0289: MOVWF 3B 028A: CALL 11B 028B: SWAPF 0D,W 028C: MOVWF 39 028D: MOVLW F0 028E: ANDWF 39,F 028F: INCF 28,F 0290: MOVLW 13 0291: ADDWF 28,W 0292: MOVWF 04 0293: MOVF 00,W 0294: MOVWF 3A 0295: MOVWF 3B 0296: CALL 11B 0297: MOVF 0D,W 0298: ADDWF 39,W 0299: MOVWF 2F .................... .................... // Because we need open collector ports, we use the Tris command to set highs .................... // and a normal port output for lows .................... .................... SET_TRIS_B(last_hcs_data); // Highs are high impedence 029A: MOVF 2F,W 029B: TRIS 6 .................... portb = last_hcs_data; // Assert the lows - highs already there due to pullups 029C: MOVF 2F,W 029D: MOVWF 06 .................... } else { 029E: GOTO 2D3 .................... // Its a bit set - little more complicated .................... .................... // Use the last data sent by the HCS to maintain proper Tristate settings .................... // We need this since a low input would reassert and flip the tri causing a possible short .................... // if we read the port, flipped the bit, and sent it back to the port .................... .................... idx = 1; 029F: MOVLW 01 02A0: MOVWF 29 .................... .................... // Lets prevent bogus bit numbers .................... if ((buffer1[++process_idx] > '7') || (buffer1[process_idx] < '0')) { break; } 02A1: INCF 28,F 02A2: MOVLW 13 02A3: ADDWF 28,W 02A4: MOVWF 04 02A5: MOVF 00,W 02A6: SUBLW 37 02A7: BTFSS 03.0 02A8: GOTO 2B0 02A9: MOVLW 13 02AA: ADDWF 28,W 02AB: MOVWF 04 02AC: MOVF 00,W 02AD: SUBLW 2F 02AE: BTFSS 03.0 02AF: GOTO 2B1 02B0: GOTO 375 .................... .................... // Quick and dirty way to get 2^x .................... for (scratch = (buffer1[process_idx] & 0x0F); scratch != 0; scratch--) { 02B1: MOVLW 13 02B2: ADDWF 28,W 02B3: MOVWF 04 02B4: MOVF 00,W 02B5: ANDLW 0F 02B6: MOVWF 2A 02B7: MOVF 2A,F 02B8: BTFSC 03.2 02B9: GOTO 2BE .................... idx <<= 1; // Shift the bit once 02BA: BCF 03.0 02BB: RLF 29,F .................... } 02BC: DECF 2A,F 02BD: GOTO 2B7 .................... .................... process_idx += 2; // Shift to bit value 02BE: MOVLW 02 02BF: ADDWF 28,F .................... if (buffer1[process_idx] == '0') { 02C0: MOVLW 13 02C1: ADDWF 28,W 02C2: MOVWF 04 02C3: MOVF 00,W 02C4: SUBLW 30 02C5: BTFSS 03.2 02C6: GOTO 2CF .................... // Lets twiddle the bit using the last HCS data .................... // Thus we won't grab inputs and re assert them .................... .................... last_hcs_data &= (idx ^ 0xFF); // Twiddle the bit from HCS data - maintain inputs 02C7: MOVF 29,W 02C8: XORLW FF 02C9: ANDWF 2F,F .................... .................... portb = last_hcs_data; // Set latches BEFORE changing TRIS 02CA: MOVF 2F,W 02CB: MOVWF 06 .................... SET_TRIS_B(last_hcs_data); // Now assert the low already set in latches 02CC: MOVF 2F,W 02CD: TRIS 6 .................... } else { 02CE: GOTO 2D3 .................... last_hcs_data |= idx; // Set the specific bit 02CF: MOVF 29,W 02D0: IORWF 2F,F .................... SET_TRIS_B(last_hcs_data); // No need to set port. Pull-ups take care of that 02D1: MOVF 2F,W 02D2: TRIS 6 .................... } .................... } .................... .................... p_idle = TRUE; // Release the old buffer - we are done with it. 02D3: BSF 2B.0 .................... .................... // Pulse the strobe on a port change in case the user needs it .................... #asm .................... nop .................... #endasm 02D4: NOP .................... //delay_cycles(1); // Let data stabilize .................... porta.strobe = 0; 02D5: BCF 05.0 .................... delay_us(250); // Pulse strobe low in case they need it 02D6: MOVLW 53 02D7: MOVWF 0C 02D8: DECFSZ 0C,F 02D9: GOTO 2D8 .................... porta.strobe = 1; 02DA: BSF 05.0 .................... .................... break; 02DB: GOTO 375 .................... .................... case('Q'): .................... // Its a query! Read the byte or bit and return it .................... // Note we DON'T touch last_hcs_data because a low input would be reasserted during the .................... // next bit twiddle. .................... .................... data = portb; 02DC: MOVF 06,W 02DD: MOVWF 2D .................... .................... // We need to figure out if they wanted a bit or byte returned .................... if ((process_idx + 3) < endbuff) { 02DE: MOVLW 03 02DF: ADDWF 28,W 02E0: SUBWF 2C,W 02E1: BTFSC 03.2 02E2: GOTO 315 02E3: BTFSS 03.0 02E4: GOTO 315 .................... // We still have valid data - it must be a bit query .................... byte_query = FALSE; 02E5: BCF 30.1 .................... process_idx += 3; // Move to bit number 02E6: MOVLW 03 02E7: ADDWF 28,F .................... .................... // Lets prevent bogus bit numbers .................... if ((buffer1[process_idx] > '7') || (buffer1[process_idx] < '0')) { break; } 02E8: MOVLW 13 02E9: ADDWF 28,W 02EA: MOVWF 04 02EB: MOVF 00,W 02EC: SUBLW 37 02ED: BTFSS 03.0 02EE: GOTO 2F6 02EF: MOVLW 13 02F0: ADDWF 28,W 02F1: MOVWF 04 02F2: MOVF 00,W 02F3: SUBLW 2F 02F4: BTFSS 03.0 02F5: GOTO 2F7 02F6: GOTO 375 .................... .................... for (idx = buffer1[process_idx]; idx >= '0'; idx--) { 02F7: MOVLW 13 02F8: ADDWF 28,W 02F9: MOVWF 04 02FA: MOVF 00,W 02FB: MOVWF 29 02FC: MOVF 29,W 02FD: SUBLW 2F 02FE: BTFSC 03.0 02FF: GOTO 307 .................... // Lets shift out the bit into a byte variable .................... scratch = shift_right(&data, 1, 0); 0300: BCF 03.0 0301: RRF 2D,F 0302: CLRF 2A 0303: BTFSC 03.0 0304: INCF 2A,F .................... } 0305: DECF 29,F 0306: GOTO 2FC .................... .................... // The requested bit is now in position 1 - lets wipe out the rest .................... scratch &= 0b00000001; 0307: MOVLW 01 0308: ANDWF 2A,F .................... data_char[0] = scratch + 48; // Convert to ASCII 0 or 1 0309: MOVLW 30 030A: ADDWF 2A,W 030B: MOVWF 35 .................... idx = buffer1[process_idx]; // ASCII value to return for bit number 030C: MOVLW 13 030D: ADDWF 28,W 030E: MOVWF 04 030F: MOVF 00,W 0310: MOVWF 29 .................... .................... // Neat trick - we won't use this to return data, but we can use it to add the .# .................... // to the computed checksum. Slick! .................... data_char[1] = '.' + idx; 0311: MOVLW 2E 0312: ADDWF 29,W 0313: MOVWF 36 .................... } else { 0314: GOTO 326 .................... // They want a byte returned .................... // Lets convert data into a 2 char ASCII string .................... byte_query = TRUE; 0315: BSF 30.1 .................... .................... data_char[0] = byte_to_ascii(data >> 4); 0316: SWAPF 2D,W 0317: MOVWF 37 0318: MOVLW 0F 0319: ANDWF 37,F 031A: MOVF 37,W 031B: MOVWF 38 031C: CALL 128 031D: MOVF 0D,W 031E: MOVWF 35 .................... data_char[1] = byte_to_ascii(data & 0x0F); 031F: MOVF 2D,W 0320: ANDLW 0F 0321: MOVWF 37 0322: MOVWF 38 0323: CALL 128 0324: MOVF 0D,W 0325: MOVWF 36 .................... } .................... .................... p_idle = TRUE; // We are done with the buffer 0326: BSF 2B.0 .................... .................... // Should we send back a checksum?? .................... if (checksum) { 0327: BTFSS 30.0 0328: GOTO 332 .................... // Lets build the checksum. We'll cheat and use some predetermined values here .................... scratch = '$' + '0' + '0' + ' ' + 'D' + 'I' + 'O' + ' ' + 'D' + 'P' + '='; // In 8 bits only! 0329: MOVLW 71 032A: MOVWF 2A .................... scratch += thisnode[3] + data_char[0] + data_char[1]; 032B: MOVF 35,W 032C: ADDWF 34,W 032D: ADDWF 36,W 032E: ADDWF 2A,F .................... .................... // Now lets take the 2's complement of the checksum subtotal result .................... scratch ^= 0xFF; 032F: MOVLW FF 0330: XORWF 2A,F .................... scratch++; 0331: INCF 2A,F .................... } .................... .................... // Lets send the response .................... delay_ms(50); 0332: MOVLW 32 0333: MOVWF 37 0334: GOTO 137 .................... .................... send_serial_byte('$'); 0335: MOVLW 24 0336: MOVWF 39 0337: CALL 0EF .................... .................... if (checksum) { 0338: BTFSS 30.0 0339: GOTO 33F .................... printf(send_serial_byte, "%2X", scratch); * 014C: BTFSC 38.7 014D: GOTO 15E 014E: MOVLW 0F 014F: MOVWF 0C 0150: SWAPF 37,W 0151: ANDWF 0C,F 0152: MOVLW 0A 0153: SUBWF 0C,W 0154: BTFSC 03.0 0155: GOTO 159 0156: MOVLW 30 0157: ADDWF 0C,F 0158: GOTO 15B 0159: MOVF 38,W 015A: ADDWF 0C,F 015B: MOVF 0C,W 015C: MOVWF 39 015D: CALL 0EF 015E: MOVLW 0F 015F: ANDWF 37,F 0160: MOVLW 0A 0161: SUBWF 37,W 0162: BTFSC 03.0 0163: GOTO 166 0164: MOVLW 30 0165: GOTO 168 0166: BCF 38.7 0167: MOVF 38,W 0168: ADDWF 37,F 0169: MOVF 37,W 016A: MOVWF 39 016B: CALL 0EF 016C: GOTO 33F (RETURN) * 033A: MOVF 2A,W 033B: MOVWF 37 033C: MOVLW 37 033D: MOVWF 38 033E: GOTO 14C .................... } .................... .................... printf(send_serial_byte, " DIO%c DP", thisnode[3]); * 007B: BCF 0A.0 007C: BCF 0A.1 007D: BCF 0A.2 007E: ADDWF 02,F 007F: RETLW 20 0080: RETLW 44 0081: RETLW 49 0082: RETLW 4F 0083: RETLW 25 0084: RETLW 63 0085: RETLW 20 0086: RETLW 44 0087: RETLW 50 0088: RETLW 00 * 033F: CLRF 37 0340: MOVF 37,W 0341: CALL 07B 0342: INCF 37,F 0343: MOVWF 39 0344: CALL 0EF 0345: MOVLW 04 0346: SUBWF 37,W 0347: BTFSS 03.2 0348: GOTO 340 0349: MOVF 34,W 034A: MOVWF 39 034B: CALL 0EF 034C: MOVLW 20 034D: MOVWF 39 034E: CALL 0EF 034F: MOVLW 44 0350: MOVWF 39 0351: CALL 0EF 0352: MOVLW 50 0353: MOVWF 39 0354: CALL 0EF .................... .................... if (!byte_query) { 0355: BTFSC 30.1 0356: GOTO 367 .................... // Lets include the .# for the queried bit .................... printf(send_serial_byte, ".%c=%c\n", idx, data_char[0]); 0357: MOVLW 2E 0358: MOVWF 39 0359: CALL 0EF 035A: MOVF 29,W 035B: MOVWF 39 035C: CALL 0EF 035D: MOVLW 3D 035E: MOVWF 39 035F: CALL 0EF 0360: MOVF 35,W 0361: MOVWF 39 0362: CALL 0EF 0363: MOVLW 0A 0364: MOVWF 39 0365: CALL 0EF .................... } else { 0366: GOTO 373 .................... printf(send_serial_byte, "=%c%c\n", data_char[0], data_char[1]); 0367: MOVLW 3D 0368: MOVWF 39 0369: CALL 0EF 036A: MOVF 35,W 036B: MOVWF 39 036C: CALL 0EF 036D: MOVF 36,W 036E: MOVWF 39 036F: CALL 0EF 0370: MOVLW 0A 0371: MOVWF 39 0372: CALL 0EF .................... } .................... .................... break; 0373: GOTO 375 .................... .................... default: .................... // Do nothing .................... break; 0374: GOTO 375 .................... .................... } // switch(buffer1[process_idx++]) .................... .................... goto Buffer_Scan; 0375: GOTO 1FF .................... } // End main .................... 0376: SLEEP .................... .................... ....................