boiler95
Member level 1
- Joined
- Jan 7, 2011
- Messages
- 38
- Helped
- 1
- Reputation
- 2
- Reaction score
- 1
- Trophy points
- 1,288
- Activity points
- 1,731
Hi Guys,
I'm trying to transfer data between PIC16F72 and raspberry pi (Model B, Rev2) using a cheap 433Mhz module from Ebay.
I'm planning to DIY a weather station and wireless is an essential part of it. The communication is one way from PIC to RPI and i have soldered a 17.3 cm wire as an antenna.
data needs to be transmitted probably for 12 meters max.
i'm using Manchester encoding here. PIC acts a s transmitter and RPI acts a receiver.
however the problem is i'm unable to transmit successfully anything.
i have the folowg transmitted from PIC16F72
4 Bytes preamble 0xAAAAAAAA
2 Bytes start of data 0xAB38
20 bytes of data (This is just AAAA.... , in future it will be replaces by data from all the sensors.)
1 byte of Check sum.
The problem i believe, is in the receiver part. the bloody data that i get is always corrupted no mater what !!!!!
i have tried sending 2000bps 2250bps .. (and much lower as well but in vain)
sometimes Preamble, start of data is detected but data is corrupted. but this happens at random sometimes nothing is detected. I'm been looking into it for days now without progress :bang:
i have posted the entire code for reference. Code for raspberry PI used the wringPI Api and is in C .. That of PIC is written in ASM for better control over timing.
i'm using pin 13 (wringPi pin 2) on RPI for reception.
the idea is to detect atleasst 3 bytes of preamble. and then the start of data and then the data itself.
i haven't checked the checksum part yet, as i'm printing the data received and checking it manually.
on the PIC side, i'm using RB5 as an o/p port connected to the TX.
Timer 1 is used to precisely to construct ( send) the required waveform with the correct timing i have tried sending 400us , 600us and 200us pulses with 400us being much better in the sense that the receiver is at least able to detect corrupt data.
i'm using RC4 as a led o/p. and Rb0 for external interrupt to start the transmission.
Any help is appreciated.
Thanks,
VirtualVat
This is the transmitter code. (PIC)
I'm trying to transfer data between PIC16F72 and raspberry pi (Model B, Rev2) using a cheap 433Mhz module from Ebay.
I'm planning to DIY a weather station and wireless is an essential part of it. The communication is one way from PIC to RPI and i have soldered a 17.3 cm wire as an antenna.
data needs to be transmitted probably for 12 meters max.
i'm using Manchester encoding here. PIC acts a s transmitter and RPI acts a receiver.
however the problem is i'm unable to transmit successfully anything.
i have the folowg transmitted from PIC16F72
4 Bytes preamble 0xAAAAAAAA
2 Bytes start of data 0xAB38
20 bytes of data (This is just AAAA.... , in future it will be replaces by data from all the sensors.)
1 byte of Check sum.
The problem i believe, is in the receiver part. the bloody data that i get is always corrupted no mater what !!!!!
i have tried sending 2000bps 2250bps .. (and much lower as well but in vain)
sometimes Preamble, start of data is detected but data is corrupted. but this happens at random sometimes nothing is detected. I'm been looking into it for days now without progress :bang:
i have posted the entire code for reference. Code for raspberry PI used the wringPI Api and is in C .. That of PIC is written in ASM for better control over timing.
i'm using pin 13 (wringPi pin 2) on RPI for reception.
the idea is to detect atleasst 3 bytes of preamble. and then the start of data and then the data itself.
i haven't checked the checksum part yet, as i'm printing the data received and checking it manually.
on the PIC side, i'm using RB5 as an o/p port connected to the TX.
Timer 1 is used to precisely to construct ( send) the required waveform with the correct timing i have tried sending 400us , 600us and 200us pulses with 400us being much better in the sense that the receiver is at least able to detect corrupt data.
i'm using RC4 as a led o/p. and Rb0 for external interrupt to start the transmission.
Any help is appreciated.
Thanks,
VirtualVat
Code C - [expand] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 /***************************** * Pin 13 ( physical) or Pin 2 in wiringPi is used * Preamble of 2 bytes or 16 bits is sent first. * Check sum is yet to be decided. * bit rate of 2.5Khz will be considerded. This means 400us per bit ******************************/ #include <stdio.h> #include <stdlib.h> #include <wiringPi.h> #include <signal.h> #include <time.h> #include <stdint.h> #include <pthread.h> #include <math.h> #include <string.h> #define PULSEWIDTH 600000 // in nano seconds #define TOLERANCE 100000 // in nano seconds #define MIN_PREAMBLE_BITS 24 // This is the minimum bits in the preamble that needs to be detected. #define RXPIN 2 // This is pint 13 on physical layout #define ACTIVETIME 90 // timer befor main thread exit, we need to re think this strategy #define DATABYTES 21 // 20 bytes of data or 160 bits. (overall 3 bytes preamble so 178 bits or 71.2 ms burst ) #define PRIORITY 99 int result[DATABYTES * 8] ; int start_of_data[8] = {0,0,1,1,1,0,0,0}; typedef int bool ; #define true 1 #define false 0 // synchronization related. typedef int syncState ; #define notSynced 0 #define synching 1 #define synched 2 typedef int processState ; #define PRESYNC 0 #define POSTSYNC 2 #define DATA 3 // Timer related #define CLOCKID CLOCK_REALTIME #define SIG SIGRTMIN #define TIMERVAL 60000000000 // this is the timer value in ns, this is 1 min // global variables timer_t syncTimer; // this is the timer used in sync timing struct itimerspec its; // used in the creation of timer ( timer spec ) struct sigevent sev; // used in timer creation uint64_t count1 ; // used to calculate diff uint64_t count2 ; // forward declarations void initialize(void); long getTimeElapsed(time_t); uint64_t getCountDiff(void); void resetOnError(void); void initializeTimer(void); #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \ } while (0) processState procState ; syncState synchState; int currentBit; int prevBit ; int iter ; int const pulseWidthMax = PULSEWIDTH + TOLERANCE ; int const pulseWidthMin = PULSEWIDTH - TOLERANCE ; int const pulseHalfWidthMax = (PULSEWIDTH / 2 ) + TOLERANCE ; int const pulseHalfWidthMin = (PULSEWIDTH / 2 ) - TOLERANCE ; bool allDataRecieved = false ; pthread_mutex_t var ; void storeDecimalToHex(uint8_t decimalValue, char* hexResult) { static int i = 0 ; // static because we call it repeatedly int rem ; int iter = 1 ; while(decimalValue != 0) { rem = decimalValue%16 ; switch(rem) { case 10: hexResult[i+iter]='A'; break; case 11: hexResult[i+iter]='B'; break; case 12: hexResult[i+iter]='C'; break; case 13: hexResult[i+iter]='D'; break; case 14: hexResult[i+iter]='E'; break; case 15: hexResult[i+iter]='F'; break; default: hexResult[i+iter]=rem+'0'; break; } i++ ; // static so that we can track the number of bits done. iter = -1 ; // this is local decimalValue=decimalValue/16 ; } if(i == ((DATABYTES - 1 ) * 8 ) - 1 ) // if this is the last bit. then { hexResult[i+1] = '\0'; // add the end of string so that we can print it. } } int getCheckSum(int* result) { int bitcount = 0 ; uint8_t calculatedChecksum = 0 ; // use 8 bit integer so that it will overflow after 255 int index = 7 ; while(bitcount < ((DATABYTES - 1) * 8)) // only 19 bytes is data last byte is checksum { calculatedChecksum = calculatedChecksum + (*(result + bitcount )) * ((uint8_t)pow(2 , index)); // &(result + bitcount ) will point to a bit in each iteration. index starts from 7 ends to 0 then wraps to 7. if(index == 0) { index = 7 ; // this means one byte is over , reset the index to 7 } else { index -- ; // decrement the index during each iteration so that the bits are multiplied by appropriate powers of 2. } bitcount++ ; // increment during each iteration to keep track of number of bits } // Xor the resulting value with 255 (0xFF) calculatedChecksum = calculatedChecksum ^(uint8_t)255 ; // Add 1 to the result calculatedChecksum = calculatedChecksum + (uint8_t)1 ; return calculatedChecksum ; } void checkAndPrintData() { // we need to first get the check sum. // The transmitter transmits MSB first , so the first memory location contains the MSB. // Check sum is the last byte. // -------------- extract check sum ------------------------------- int i = 0 ; unsigned int extractedCheckSum = 0 ; while(i < 8) { extractedCheckSum = extractedCheckSum + ((*(result + (DATABYTES * 8) - 1 - i )) * ((uint8_t)pow(2 , i))) ; i++ ; } // -------- calclate checksum from the receieved data ------------------------; unsigned int calculatedCheckSum = 0 ; calculatedCheckSum = getCheckSum(result); if(calculatedCheckSum != extractedCheckSum ) { printf("Check sum do not match error in transmission \n"); } else { printf("Calculated checksum is %d , checksum receieved in the packet is %d \n ", calculatedCheckSum , extractedCheckSum); } // ----------------------- Print data --------------------------. char hex[39] ; // This is where data is stored. we have 19 bytes of data each bytes takes 2 hex number to represent. so 19 x 8 = 38 + 1 (end of string '\0' ) = 39 is array size needed. int bitcount = 0 ; uint8_t byteValDecimal = 0 ; // this is used to keep track of every byte in decimal ; int index = 7 ; while(bitcount < (DATABYTES - 1) * 8 ) // DATABYTES -1 because 20th byte is checksum and not data { // first get the byte value in decimal. byteValDecimal = byteValDecimal + (*(result + bitcount )) * (uint8_t)pow(2 , index); if(index == 0) { index = 7 ; // At this point 1 byte is over. convert this value to hex and store it. storeDecimalToHex( byteValDecimal, hex) ; } else { index-- ; } bitcount++ ; // increment during each iteration to keep track of number of bits } printf("Hexadecimal number: %s \n",hex); } int main(void) { if(wiringPiSetup() == -1 ) errExit("Error initializing wiring pi"); pinMode(RXPIN, INPUT); initialize(); printf("main thread executing delay for %d sec \n", ACTIVETIME ) ; int i = ACTIVETIME; while(i > 0) { delay(1000 ); // check meanwile if we have data. pthread_mutex_lock(&var); if(allDataRecieved == true ) { //checkAndPrintData(); int iterator = 0 ; while(iterator < (DATABYTES * 8)) { iterator++ ; printf("%d", result[iterator]); if(iterator % 8 == 0 ) { printf("\n"); } } break ; } pthread_mutex_unlock(&var); i-- ; } printf("main thread finished delay for %d sec \n bye !!", ACTIVETIME ) ; exit(EXIT_SUCCESS); } void _ISROnAllEdges(void) { currentBit = digitalRead (RXPIN) ; uint64_t diff = getCountDiff(); if(procState == PRESYNC ) { if(synchState == notSynced ) { /* start timer */ if (timer_settime(syncTimer, 0, &its, NULL) == -1) errExit("timer_settime"); /* mark the process as initializing */ synchState = synching ; /* initialize count1 */ count1 = TIMERVAL; } else if(synchState == synching ) { if(diff > pulseWidthMin && diff < pulseWidthMax) { if(iter < MIN_PREAMBLE_BITS) { if(currentBit == prevBit) { /*This is error*/ resetOnError(); return ; } else { prevBit = currentBit ; iter++ ; } } else if(iter >= MIN_PREAMBLE_BITS) { /* if we are here then we have got atleast 1010 There can be more 10101.. or we can get the 00111000 that preceeds the data. We need to identify the start of 00111000 before moving to the next step*/ if(currentBit == prevBit) { if(currentBit == 1) { printf("Preamble detected \n "); synchState = synched ; procState = POSTSYNC ; iter = 0 ; } else { /* Current bit and previous bit are 0 , this is not possible in preamble so error*/ resetOnError(); } } else { /*Still we are in preamble detection */ prevBit = currentBit ; iter++ ; } } count1 = count2 ; //Advance to next bit } else if(diff > pulseHalfWidthMin && diff < pulseHalfWidthMax ) { return ; // wait for the next edge. } else { /* Error out of sync */ resetOnError(); } } } else if( procState == POSTSYNC ) { printf("In post sync \n"); if(diff > pulseWidthMin && diff < pulseWidthMax ) { printf("In post sync: time matched \n"); /* this is where we identify the string of 00111000 This is the start of data identifier */ if(currentBit == start_of_data[iter++]) { printf("In post sync: iter = %d \n", iter); if(iter == 8 ) // all 8 bits are identified. next is start of data { printf("Ready to accept data \n"); procState = DATA ; iter = 0 ; } count1 = count2 ; // Advance to next bit. } else { printf("In post sync : expecting %d but %d detected \n", start_of_data[iter - 1] , currentBit); /*Error case since we are expecting all 1's */ resetOnError(); } } else if(diff > pulseHalfWidthMin && diff < pulseHalfWidthMax ) { printf("In post sync : Returning for next edge \n"); return ; // wait for the next edge. } else { printf("In post sync : Timing error %ld \n", (long)diff); /* Error out of sync */ resetOnError(); } } else if(procState == DATA) { if(diff > pulseHalfWidthMin && diff < pulseHalfWidthMax ) { return ; // wait for the next edge. } if(iter < (DATABYTES * 8) ) { if(diff < pulseWidthMin || diff > pulseWidthMax) { printf("Timer problem %ld \n", (long)diff); result[iter++] = 2 ; } else { result[iter++] = currentBit ; } } else { // Done De-register the interrupt system ("/usr/local/bin/gpio edge 17 none") ; // update the global variable to indicate data is recieved. pthread_mutex_lock(&var); allDataRecieved = true ; pthread_mutex_unlock(&var); return ; } count1 = count2 ; // Advance to next bit } } void initialize(void) { procState = PRESYNC ; synchState = notSynced; currentBit = 0 ; prevBit = 0 ; iter = 0 ; /*Elevate the thread priority*/ if(piHiPri(PRIORITY) == -1) errExit("Unable to elevate thread priority, run program as root \n"); initializeTimer() ; // instruct kernel to interrupt on all edges. wiringPiISR (RXPIN, INT_EDGE_BOTH , &_ISROnAllEdges) ; } void initializeTimer(void) { /* Create the timer */ sev.sigev_notify = SIGEV_NONE; if (timer_create(CLOCKID, &sev, &syncTimer) == -1) errExit("timer_create"); printf("timer ID is 0x%lx\n", (long) syncTimer); /* Start the timer later just fill the spec*/ its.it_value.tv_sec = TIMERVAL / 1000000000; its.it_value.tv_nsec = TIMERVAL % 1000000000; its.it_interval.tv_sec = its.it_value.tv_sec; its.it_interval.tv_nsec = its.it_value.tv_nsec; } uint64_t getCountDiff(void) { uint64_t nanosec = 0 ; struct itimerspec time_spec ; if(timer_gettime(syncTimer, &time_spec ) == -1) errExit("timer_getoverrun"); count2 = ((uint64_t)time_spec.it_value.tv_sec * (uint64_t)1000000000 ) + (uint64_t)time_spec.it_value.tv_nsec ; nanosec = count1 - count2 ; return nanosec ; } void resetOnError(void) { /*This is error*/ synchState = notSynced ; // error start all over. procState = PRESYNC ; iter = 0 ; prevBit = 0 ; // This forces the algorithm to proceed only when the pulses are 1 currentBit = 0 ; /* if(timer_delete(syncTimer) == -1) // Timer is deleted an recreated in a new cycle errExit("Delete the timer"); No need of this because thn new time is set timer is automatically rearmed */ }
This is the transmitter code. (PIC)
Code ASM - [expand] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 ;********************************************************************** ; This file is a basic code template for assembly code generation * ; on the PIC16F72. This file contains the basic code * ; building blocks to build upon. * ; * ; Refer to the MPASM User's Guide for additional information on * ; features of the assembler (Document DS33014). * ; * ; Refer to the respective PIC data sheet for additional * ; information on the instruction set. * ; * ;********************************************************************** ; * ; Filename: xxx.asm * ; Date: * ; File Version: * ; * ; Author: * ; Company: * ; * ; * ;********************************************************************** ; * ; Files Required: P16F72.INC * ; * ;********************************************************************** ; * ; Notes: 20 bytes of data. 6 bytes of preamble. 1 start fo data byte . 1 byte Check sum * ; * ;********************************************************************** list p=16f72 ; list directive to define processor #include <p16f72.inc> ; processor specific variable definitions __CONFIG _CP_OFF & _WDTEN_OFF & _BODEN_OFF & _PWRTEN_ON & _HS_OSC ; '__CONFIG' directive is used to embed configuration data within .asm file. ; The lables following the directive are located in the respective .inc file. ; See respective data sheet for additional information on configuration word. ;***** VARIABLE DEFINITIONS w_temp EQU 0x20 ; variable used for context saving w_temp1 EQU 0xA0 ; reserve bank1 equivalent of w_temp status_temp EQU 0x21 ; variable used for context saving ISDATA EQU 0x40 ; ISDATA<1> is used to determine if the data is at edge of mid (Mid bit of bit edge), ISDATA<0> is used in calculation of Check Sum TEMP EQU 0x41 BITCOUNT EQU 0x42 CKS EQU 0x5E ; This is the last bytes in the data block below. This is used to store the Check sum CBLOCK 0x43 _DATA:28 ; data is 20 bytes wide, 6 bytes of preamble, 1 byte start fo data followed by 1 byte of checksum total 28 bytes ENDC ; End of Cblock , we can now access data by DATA , DATA+1 , DATA+2 etc.. cblock DELAY DELAY_1 DELAY_2 endc ;********************************************************************** ORG 0x000 ; processor reset vector goto main ; go to beginning of program ORG 0x004 ; interrupt vector location movwf w_temp ; save off current W register contents (At this point 2 cycles are already over when interrupt is raised, use this in the count) movf STATUS,w ; move status register into W register bcf STATUS,RP0 ; ensure file register bank set to 0 movwf status_temp ; save off contents of STATUS register ; isr code can go here or be located as a call subroutine elsewhere BTFSC INTCON, INTF ; Check if this is and external interrupt routine GOTO EXT_INT_ROUTINE BANKSEL PIR1 BTFSS PIR1, TMR1IF GOTO ISREND ; Handle timeout interrupt ; first check if it is bit edge. BTFSC ISDATA, 1 ; if clear then it is bit edge. GOTO MIDBIT ; This interrupt is for mid bit ; Start of bit edge operations BTFSS INDF, 7 ; bit edge. if 0 then tranamit 1 , if 1 then transmit 0 GOTO SEND_HIGH_EDGE_RELOAD ; send a high and load the timer to interrupt in next 200uS (This is for bit edge ) ; EBL : **** Start of edge bit low operations BANKSEL PORTB ; This is 2 instruction cycle NOP NOP ; These 2 NOP is to make the time taken since interrupt same for both EBL and EBH BCF PORTB, RB5 ; send bit low and load count. (19) MOVLW 0x24 ; 0x31 for 400us , 0x3C for 600us MOVWF TMR1L ; MOVLW 0xFE ; 0xFC for 400us , 0xFA for 600us MOVWF TMR1H ; GOTO BITEDGE_END ; ; End of bit edge low operation ; EBH ***** Start of bit edge high operations SEND_HIGH_EDGE_RELOAD NOP BANKSEL PORTB BSF PORTB, RB5 ; send bit High and load count. (19) MOVLW 0x24 ; 0x31 for 400us MOVWF TMR1L ; MOVLW 0xFE ; 0xFC for 400us MOVWF TMR1H ; ; End of bit edge high operations BITEDGE_END BSF ISDATA, 1 ; set it to indicate middle of the bit during next interrupt. GOTO PREISR ; Done goto PREISR so that we clear the interrupt. ; Start of mid bit operations MIDBIT BTFSS INDF, 7 ; check MSB and transmit. GOTO SEND_LOW_MID_RELOAD ; send a low and load the timer to interrupt in next 200uS (This is for bit middle ) ;MBH : ***** Start of mid bit high operations BANKSEL PORTB NOP ; To adjust cycles NOP BSF PORTB, RB5 ; 22 cycles till here. MOVLW 0x23 ; 0x30 for 400us , 0x3B for 600us MOVWF TMR1L ; MOVLW 0xFE ; 0xFC for 400us, 0xFA for 600us MOVWF TMR1H ; GOTO BITMID_END ; ; End of mid bit high operations ; MBL : ****** start of mid bit low operations SEND_LOW_MID_RELOAD NOP BANKSEL PORTB ; BCF PORTB, RB5 ; 22 cycles till here MOVLW 0x23 ; 0x30 for 400us MOVWF TMR1L ; MOVLW 0xFE ; 0xFC for 400us MOVWF TMR1H ; ; end of mid bit low operations. BITMID_END INCF BITCOUNT ; increment the bit count indicating we just transmitted a bit , This is used to determine end of transmission INCF TEMP ; Increment the temp register, This is used to determine if a byte has been transmitted BCF ISDATA, 1 ; Clear the flag to indicate next interrupt is for bit edge. RLF INDF, F ; we just sent one bit now we need to shift once MOVLW 0x08 ; Check if 8 bits are transmitted. SUBWF TEMP, W ; TEMP register is incremented every time a bit is transmitted so subract and see if result is 0 BTFSS STATUS, Z ; GOTO PREISR ; Zero bit is not set so 8 bits is not yet transmitted. CLRF TEMP ; 8 bits (1byte) are done get ready for the next byte. INCF FSR ; Increment FSR to point to next byte. MOVLW 0xD8 ; This corresponds to 184 SUBWF BITCOUNT, W ; subtract the bit counts from this value , this tells us if we have transmitted all the bits. BTFSS STATUS, Z GOTO PREISR ; Zero bit not set, means we have still some bits to transmit. ; ************** At this point we are done transmitting the data ***************** BANKSEL T1CON BCF T1CON, TMR1ON ; Stop the timer. CALL Delay ; 200us delay and lower the signal BANKSEL PORTB BCF PORTB, RB5 ; lower the signal BANKSEL PORTC BSF PORTC, RC4 ; Switch off the LED ; *************** End of transmission activity ********************************* PREISR NOP BANKSEL PIR1 BCF PIR1, TMR1IF ; clear the timer 1 interrupt flag so that we will get subsequent interrupts. GOTO ISREND ; start of enternal interrupt routine handling. EXT_INT_ROUTINE NOP ; Because we can't label BANLSEL, This usually the start of the transmission, prestart kind off BANKSEL PORTB ; initialize data to send CALL INIT_DATA BCF PORTB, RB5 ; Clear RB5 , so we are sendin a low on signal. ; Calculate check sum to the 21st byte, this is actually 27th byte including preamble and data CALL Cal_CKS MOVLW 0x43 ; Point the FSR to the first location that we need to send. MOVWF FSR BANKSEL PORTC BCF PORTC, RC4 ; Switch on LED indicating ready for transmission CALL Delay_1s ; Interoduce a delay of 1 second BANKSEL TMR1L CLRF TMR1L ; Start the timer from 00 (this is simoly done to give the receiever some more time to lock on.) CLRF TMR1H BANKSEL T1CON BSF T1CON, TMR1ON ; Enable timer 1 interrupt. BCF INTCON, INTF ; Clear the external interrupt ; End of the enternal interrupt routine handling ISREND NOP bcf STATUS,RP0 ; ensure file register bank set to 0 movf status_temp,w ; retrieve copy of STATUS register movwf STATUS ; restore pre-isr STATUS register contents swapf w_temp,f swapf w_temp,w ; restore pre-isr W register contents retfie ; return from interrupt main ; Configure port b as output BANKSEL TRISB BCF TRISB, RB5 ; Configure RB5 as a output for data to be transmitted. BSF TRISB, RB0 ; Configure port B as input for external interrupt. ; Configure port c , RC4 as a LED output BANKSEL TRISC BCF TRISC, RC4 BANKSEL PORTC BSF PORTC, RC4 ; This will clear the LED CALL Delay_1s BCF PORTC, RC4 ; This will on the LED CALL Delay_1s BSF PORTC, RC4 ; This will clear the LED CALL Delay_1s BCF PORTC, RC4 ; This will on the LED CALL Delay_1s BSF PORTC, RC4 ; This will clear the LED CALL Delay_1s ; Configure the timer 0 BANKSEL T1CON CLRF T1CON ; configure enternal interrupt BSF OPTION_REG, INTEDG ; interrupt on raising edge. ; Configure interrupt BANKSEL INTCON BSF INTCON, GIE ; Enabel global interrupt. BSF INTCON, INTE ; Enable external interrupt. BSF INTCON, PEIE ; enable pheripheral interript (This is for the timer 1 interrupt to fire) BANKSEL PIE1 BSF PIE1, TMR1IE ; Enable timer 1 interrupt. LOOP NOP GOTO LOOP ; Delay = 0.0002 seconds ; Clock frequency = 20 MHz ; Actual delay = 0.0002 seconds = 1000 cycles ; Error = 0 % Delay ;993 cycles movlw 0xC6 movwf DELAY movlw 0x01 movwf DELAY_1 Delay_0 decfsz DELAY, f goto $+2 decfsz DELAY_1, f goto Delay_0 ;3 cycles goto $+1 nop ;4 cycles (including call) return Cal_CKS ; Addition of all data begin. MOVLW 0x0C MOVWF TEMP ; Temp is iterated in every oteration, after 20 bytes are added(20 iterations) we will get 32 which is 100000 so we can check TEMP<5> MOVLW 0x4A ; MOVWF FSR ; FSR is in all banks. And points to a location, in this case location is 0x46 MOVLW 0x00 ; ADD_ITER BTFSC TEMP, 5 ; GOTO DONE_ADDING ; We done adding all data bits ADDWF INDF, W ; Store result in W register INCF TEMP INCF FSR GOTO ADD_ITER ; End of addition of data. DONE_ADDING CLRF TEMP ; This is again used in interrupt XORLW 0xFF ; MOVWF CKS INCF CKS ; Add 1 to the value, this finished the checksum. RETURN INIT_DATA MOVLW 0xAA MOVWF _DATA ; Preamble starts MOVWF _DATA+1 MOVWF _DATA+2 MOVWF _DATA+3 MOVWF _DATA+4 ; Preamble ends MOVLW b'10101011' MOVWF _DATA+5 MOVLW b'00111000' MOVWF _DATA+6 ; Start fo data CLRF TEMP BCF STATUS, IRP ; Clear IRP register to indicate banck 0 , 1 selection. (indirect addressing) MOVLW 0x4A ; 20 H , 21H, 22H are actually the preamble alreasy initialized so we look at the rest. MOVWF FSR ; We move the address 23 to FSR register and accedd INDF register. This will acceess location pointed by FSR. INIT MOVLW 0xAA ; data starts MOVWF INDF INCF TEMP INCF FSR MOVLW 0xAA MOVWF INDF INCF TEMP MOVLW 0x14 SUBWF TEMP, W ; Check if we need to quit. BTFSC STATUS, Z ; Subtract and move the result to W register. GOTO DONEINIT ; After 20 iterations chcek INCF FSR MOVLW 0xAA MOVWF INDF INCF TEMP INCF FSR MOVLW 0xAA MOVWF INDF INCF TEMP INCF FSR MOVLW 0xAA MOVWF INDF INCF TEMP INCF FSR MOVLW 0xAA MOVWF INDF INCF TEMP INCF FSR GOTO INIT DONEINIT CLRF TEMP CLRF BITCOUNT CLRF ISDATA BCF ISDATA, 1 ; This indicates that we need to send the bit edge first RETURN ; Delay = 1 seconds ; Clock frequency = 20 MHz ; Actual delay = 1 seconds = 5000000 cycles ; Error = 0 % Delay_1s ;4999993 cycles movlw 0x2C movwf DELAY movlw 0xE7 movwf DELAY_1 movlw 0x0B movwf DELAY_2 Delay_1s_0 decfsz DELAY, f goto $+2 decfsz DELAY_1, f goto $+2 decfsz DELAY_2, f goto Delay_1s_0 ;3 cycles goto $+1 nop ;4 cycles (including call) return END ; directive 'end of program'