├── Manchester.cpp ├── Manchester.h ├── README.markdown ├── examples ├── ManchesterRX_Array-unfixed_length │ └── ManchesterRX_Array-unfixed_length.ino └── ManchesterTX_Array-unfixed_length │ └── ManchesterTX_Array-unfixed_length.ino ├── keywords.txt └── library.json /Manchester.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This code is based on the Atmel Corporation Manchester 3 | Coding Basics Application Note. 4 | 5 | http://www.atmel.com/dyn/resources/prod_documents/doc9164.pdf 6 | 7 | Quotes from the application note: 8 | 9 | "Manchester coding states that there will always be a transition of the message signal 10 | at the mid-point of the data bit frame. 11 | What occurs at the bit edges depends on the state of the previous bit frame and 12 | does not always produce a transition. A logical '1' is defined as a mid-point transition 13 | from low to high and a '0' is a mid-point transition from high to low. 14 | 15 | We use Timing Based Manchester Decode. 16 | In this approach we will capture the time between each transition coming from the demodulation 17 | circuit." 18 | 19 | Timer 2 is used with a ATMega328. Timer 1 is used for a ATtiny85. 20 | 21 | This code gives a basic data rate as 1200 bauds. In manchester encoding we send 1 0 for a data bit 0. 22 | We send 0 1 for a data bit 1. This ensures an average over time of a fixed DC level in the TX/RX. 23 | This is required by the ASK RF link system to ensure its correct operation. 24 | The data rate is then 600 bits/s. 25 | */ 26 | 27 | #include "Manchester.h" 28 | 29 | static int8_t RxPin = 255; 30 | 31 | volatile static int16_t rx_sample = 0; 32 | volatile static int16_t rx_last_sample = 0; 33 | volatile static uint8_t rx_count = 0; 34 | volatile static uint8_t rx_sync_count = 0; 35 | volatile static uint8_t rx_mode = RX_MODE_IDLE; 36 | 37 | static uint16_t rx_manBits = 0; //the received manchester 32 bits 38 | static uint8_t rx_numMB = 0; //the number of received manchester bits 39 | static uint8_t rx_curByte = 0; 40 | 41 | static uint8_t rx_maxBytes = 2; 42 | static uint8_t rx_default_data[2]; 43 | static uint8_t* rx_data = rx_default_data; 44 | 45 | Manchester::Manchester() //constructor 46 | { 47 | applyWorkAround1Mhz = 0; 48 | } 49 | 50 | 51 | void Manchester::setTxPin(uint8_t pin) 52 | { 53 | TxPin = pin; // user sets the digital pin as output 54 | pinMode(TxPin, OUTPUT); 55 | } 56 | 57 | 58 | void Manchester::setRxPin(uint8_t pin) 59 | { 60 | ::RxPin = pin; // user sets the digital pin as output 61 | pinMode(::RxPin, INPUT); 62 | } 63 | 64 | void Manchester::workAround1MhzTinyCore(uint8_t a) 65 | { 66 | applyWorkAround1Mhz = a; 67 | } 68 | 69 | void Manchester::setupTransmit(uint8_t pin, uint8_t SF) 70 | { 71 | setTxPin(pin); 72 | speedFactor = SF; 73 | //we don't use exact calculation of passed time spent outside of transmitter 74 | //because of high ovehead associated with it, instead we use this 75 | //emprirically determined values to compensate for the time loss 76 | 77 | #if F_CPU == 1000000UL 78 | uint16_t compensationFactor = 88; //must be divisible by 8 for workaround 79 | #elif F_CPU == 8000000UL 80 | uint16_t compensationFactor = 12; 81 | #else //16000000Mhz 82 | uint16_t compensationFactor = 4; 83 | #endif 84 | 85 | #if (F_CPU == 80000000UL) || (F_CPU == 160000000) // ESP8266 80MHz or 160 MHz 86 | delay1 = delay2 = (HALF_BIT_INTERVAL >> speedFactor) - 2; 87 | #else 88 | delay1 = (HALF_BIT_INTERVAL >> speedFactor) - compensationFactor; 89 | delay2 = (HALF_BIT_INTERVAL >> speedFactor) - 2; 90 | 91 | #if F_CPU == 1000000UL 92 | delay2 -= 22; //22+2 = 24 is divisible by 8 93 | if (applyWorkAround1Mhz) { //definition of micro delay is broken for 1MHz speed in tiny cores as of now (May 2013) 94 | //this is a workaround that will allow us to transmit on 1Mhz 95 | //divide the wait time by 8 96 | delay1 >>= 3; 97 | delay2 >>= 3; 98 | } 99 | #endif 100 | #endif 101 | } 102 | 103 | 104 | void Manchester::setupReceive(uint8_t pin, uint8_t SF) 105 | { 106 | setRxPin(pin); 107 | ::MANRX_SetupReceive(SF); 108 | } 109 | 110 | 111 | void Manchester::setup(uint8_t Tpin, uint8_t Rpin, uint8_t SF) 112 | { 113 | setupTransmit(Tpin, SF); 114 | setupReceive(Rpin, SF); 115 | } 116 | 117 | 118 | void Manchester::transmit(uint8_t data) 119 | { 120 | uint8_t byteData[2] = {2, data}; 121 | transmitArray(2, byteData); 122 | } 123 | 124 | /* 125 | The 433.92 Mhz receivers have AGC, if no signal is present the gain will be set 126 | to its highest level. 127 | 128 | In this condition it will switch high to low at random intervals due to input noise. 129 | A CRO connected to the data line looks like 433.92 is full of transmissions. 130 | 131 | Any ASK transmission method must first sent a capture signal of 101010........ 132 | When the receiver has adjusted its AGC to the required level for the transmisssion 133 | the actual data transmission can occur. 134 | 135 | We send 14 0's 1010... It takes 1 to 3 10's for the receiver to adjust to 136 | the transmit level. 137 | 138 | The receiver waits until we have at least 10 10's and then a start pulse 01. 139 | The receiver is then operating correctly and we have locked onto the transmission. 140 | */ 141 | void Manchester::transmitArray(uint8_t numBytes, uint8_t *data) 142 | { 143 | 144 | #if SYNC_BIT_VALUE 145 | for( int8_t i = 0; i < SYNC_PULSE_DEF; i++) //send capture pulses 146 | { 147 | sendOne(); //end of capture pulses 148 | } 149 | sendZero(); //start data pulse 150 | #else 151 | for( int8_t i = 0; i < SYNC_PULSE_DEF; i++) //send capture pulses 152 | { 153 | sendZero(); //end of capture pulses 154 | } 155 | sendOne(); //start data pulse 156 | #endif 157 | 158 | // Send the user data 159 | for (uint8_t i = 0; i < numBytes; i++) 160 | { 161 | uint16_t mask = 0x01; //mask to send bits 162 | uint8_t d = data[i] ^ DECOUPLING_MASK; 163 | for (uint8_t j = 0; j < 8; j++) 164 | { 165 | if ((d & mask) == 0) 166 | sendZero(); 167 | else 168 | sendOne(); 169 | mask <<= 1; //get next bit 170 | }//end of byte 171 | }//end of data 172 | 173 | // Send 3 terminatings 0's to correctly terminate the previous bit and to turn the transmitter off 174 | #if SYNC_BIT_VALUE 175 | sendOne(); 176 | sendOne(); 177 | sendOne(); 178 | #else 179 | sendZero(); 180 | sendZero(); 181 | sendZero(); 182 | #endif 183 | }//end of send the data 184 | 185 | 186 | void Manchester::sendZero(void) 187 | { 188 | delayMicroseconds(delay1); 189 | digitalWrite(TxPin, HIGH); 190 | 191 | delayMicroseconds(delay2); 192 | digitalWrite(TxPin, LOW); 193 | }//end of send a zero 194 | 195 | 196 | void Manchester::sendOne(void) 197 | { 198 | delayMicroseconds(delay1); 199 | digitalWrite(TxPin, LOW); 200 | 201 | delayMicroseconds(delay2); 202 | digitalWrite(TxPin, HIGH); 203 | }//end of send one 204 | 205 | //TODO use repairing codes perhabs? 206 | //http://en.wikipedia.org/wiki/Hamming_code 207 | 208 | /* 209 | format of the message including checksum and ID 210 | 211 | [0][1][2][3][4][5][6][7][8][9][a][b][c][d][e][f] 212 | [ ID ][ checksum ][ data ] 213 | checksum = ID xor data[7:4] xor data[3:0] xor 0b0011 214 | 215 | */ 216 | 217 | //decode 8 bit payload and 4 bit ID from the message, return true if checksum is correct, otherwise false 218 | uint8_t Manchester::decodeMessage(uint16_t m, uint8_t &id, uint8_t &data) 219 | { 220 | //extract components 221 | data = (m & 0xFF); 222 | id = (m >> 12); 223 | uint8_t ch = (m >> 8) & 0b1111; //checksum received 224 | //calculate checksum 225 | uint8_t ech = (id ^ data ^ (data >> 4) ^ 0b0011) & 0b1111; //checksum expected 226 | return ch == ech; 227 | } 228 | 229 | //encode 8 bit payload, 4 bit ID and 4 bit checksum into 16 bit 230 | uint16_t Manchester::encodeMessage(uint8_t id, uint8_t data) 231 | { 232 | uint8_t chsum = (id ^ data ^ (data >> 4) ^ 0b0011) & 0b1111; 233 | uint16_t m = ((id) << 12) | (chsum << 8) | (data); 234 | return m; 235 | } 236 | 237 | void Manchester::beginReceiveArray(uint8_t maxBytes, uint8_t *data) 238 | { 239 | ::MANRX_BeginReceiveBytes(maxBytes, data); 240 | } 241 | 242 | void Manchester::beginReceive(void) 243 | { 244 | ::MANRX_BeginReceive(); 245 | } 246 | 247 | 248 | uint8_t Manchester::receiveComplete(void) 249 | { 250 | return ::MANRX_ReceiveComplete(); 251 | } 252 | 253 | 254 | uint8_t Manchester::getMessage(void) 255 | { 256 | return ::MANRX_GetMessage(); 257 | } 258 | 259 | 260 | void Manchester::stopReceive(void) 261 | { 262 | ::MANRX_StopReceive(); 263 | } 264 | 265 | //global functions 266 | 267 | #if defined( ESP8266 ) 268 | volatile uint16_t ESPtimer = 0; 269 | void timer0_ISR (void); 270 | #endif 271 | 272 | void MANRX_SetupReceive(uint8_t speedFactor) 273 | { 274 | pinMode(RxPin, INPUT); 275 | //setup timers depending on the microcontroller used 276 | 277 | #if defined( ESP8266 ) 278 | #if F_CPU == 80000000 279 | ESPtimer = (512 >> speedFactor) * 80; // 8MHZ, 300us for MAN_300, 128us for MAN_1200 280 | #elif F_CPU == 160000000 281 | ESPtimer = (512 >> speedFactor) * 160; 282 | #endif 283 | 284 | noInterrupts(); 285 | timer0_isr_init(); 286 | timer0_attachInterrupt(timer0_ISR); 287 | timer0_write(ESP.getCycleCount() + ESPtimer); //80Mhz -> 128us 288 | interrupts(); 289 | #elif defined( __AVR_ATtiny25__ ) || defined( __AVR_ATtiny45__ ) || defined( __AVR_ATtiny85__ ) 290 | 291 | /* 292 | Timer 1 is used with a ATtiny85. 293 | http://www.atmel.com/Images/Atmel-2586-AVR-8-bit-Microcontroller-ATtiny25-ATtiny45-ATtiny85_Datasheet.pdf page 88 294 | How to find the correct value: (OCRxA +1) = F_CPU / prescaler / 1953.125 295 | OCR1C is 8 bit register 296 | */ 297 | 298 | #if F_CPU == 1000000UL 299 | TCCR1 = _BV(CTC1) | _BV(CS12); // 1/8 prescaler 300 | OCR1C = (64 >> speedFactor) - 1; 301 | #elif F_CPU == 8000000UL 302 | TCCR1 = _BV(CTC1) | _BV(CS12) | _BV(CS11) | _BV(CS10); // 1/64 prescaler 303 | OCR1C = (64 >> speedFactor) - 1; 304 | #elif F_CPU == 16000000UL 305 | TCCR1 = _BV(CTC1) | _BV(CS12) | _BV(CS11) | _BV(CS10); // 1/64 prescaler 306 | OCR1C = (128 >> speedFactor) - 1; 307 | #elif F_CPU == 16500000UL 308 | TCCR1 = _BV(CTC1) | _BV(CS12) | _BV(CS11) | _BV(CS10); // 1/64 prescaler 309 | OCR1C = (132 >> speedFactor) - 1; 310 | #else 311 | #error "Manchester library only supports 1mhz, 8mhz, 16mhz, 16.5Mhz clock speeds on ATtiny85 chip" 312 | #endif 313 | 314 | OCR1A = 0; // Trigger interrupt when TCNT1 is reset to 0 315 | TIMSK |= _BV(OCIE1A); // Turn on interrupt 316 | TCNT1 = 0; // Set counter to 0 317 | 318 | #elif defined( __AVR_ATtiny2313__ ) || defined( __AVR_ATtiny2313A__ ) || defined( __AVR_ATtiny4313__ ) 319 | 320 | /* 321 | Timer 1 is used with a ATtiny2313. 322 | http://www.atmel.com/Images/doc2543.pdf page 107 323 | How to find the correct value: (OCRxA +1) = F_CPU / prescaler / 1953.125 324 | OCR1A/B are 8 bit registers 325 | */ 326 | 327 | #if F_CPU == 1000000UL 328 | TCCR1A = 0; 329 | TCCR1B = _BV(WGM12) | _BV(CS11); // reset counter on match, 1/8 prescaler 330 | OCR1A = (64 >> speedFactor) - 1; 331 | #elif F_CPU == 8000000UL 332 | TCCR1B = _BV(WGM12) | _BV(CS12) | _BV(CS11) | _BV(CS10); // 1/64 prescaler 333 | OCR1A = (64 >> speedFactor) - 1; 334 | #else 335 | #error "Manchester library only supports 1mhz, 8mhz clock speeds on ATtiny2313 chip" 336 | #endif 337 | 338 | OCR1B = 0; // Trigger interrupt when TCNT1 is reset to 0 339 | TIMSK |= _BV(OCIE1B); // Turn on interrupt 340 | TCNT1 = 0; // Set counter to 0 341 | 342 | 343 | #elif defined( __AVR_ATtiny24__ ) || defined( __AVR_ATtiny24A__ ) || defined( __AVR_ATtiny44__ ) || defined( __AVR_ATtiny44A__ ) || defined( __AVR_ATtiny84__ ) || defined( __AVR_ATtiny84A__ ) 344 | 345 | /* 346 | Timer 1 is used with a ATtiny84. 347 | http://www.atmel.com/Images/doc8006.pdf page 111 348 | How to find the correct value: (OCRxA +1) = F_CPU / prescaler / 1953.125 349 | OCR1A is 8 bit register 350 | */ 351 | 352 | TCCR1A = 0; 353 | 354 | #if F_CPU == 1000000UL 355 | TCCR1B = _BV(WGM12) | _BV(CS11); // 1/8 prescaler 356 | OCR1A = (64 >> speedFactor) - 1; 357 | #elif F_CPU == 8000000UL 358 | TCCR1B = _BV(WGM12) | _BV(CS11) | _BV(CS10); // 1/64 prescaler 359 | OCR1A = (64 >> speedFactor) - 1; 360 | #elif F_CPU == 16000000UL 361 | TCCR1B = _BV(WGM12) | _BV(CS11) | _BV(CS10); // 1/64 prescaler 362 | OCR1A = (128 >> speedFactor) - 1; 363 | #else 364 | #error "Manchester library only supports 1mhz, 8mhz, 16mhz on ATtiny84" 365 | #endif 366 | 367 | TIMSK1 |= _BV(OCIE1A); // Turn on interrupt 368 | TCNT1 = 0; // Set counter to 0 369 | 370 | #elif defined(__AVR_ATmega32U4__) 371 | 372 | /* 373 | Timer 3 is used with a ATMega32U4. 374 | http://www.atmel.com/Images/doc7766.pdf page 133 375 | How to find the correct value: (OCRxA +1) = F_CPU / prescaler / 1953.125 376 | OCR3A is 16 bit register 377 | */ 378 | TCCR3A = 0; // 2016, added, make it work for Leonardo 379 | TCCR3B = 0; // 2016, added, make it work for Leonardo 380 | TCCR3B = _BV(WGM32) | _BV(CS31); // 1/8 prescaler 381 | #if F_CPU == 1000000UL 382 | OCR3A = (64 >> speedFactor) - 1; 383 | #elif F_CPU == 8000000UL 384 | OCR3A = (512 >> speedFactor) - 1; 385 | #elif F_CPU == 16000000UL 386 | OCR3A = (1024 >> speedFactor) - 1; 387 | #else 388 | #error "Manchester library only supports 1mhz, 8mhz, 16mhz on ATMega32U4" 389 | #endif 390 | 391 | TCCR3A = 0; // reset counter on match 392 | TIFR3 = _BV(OCF3A); // clear interrupt flag 393 | TIMSK3 = _BV(OCIE3A); // Turn on interrupt 394 | TCNT3 = 0; // Set counter to 0 395 | 396 | #elif defined(__AVR_ATmega8__) 397 | 398 | /* 399 | Timer/counter 1 is used with ATmega8. 400 | http://www.atmel.com/Images/Atmel-2486-8-bit-AVR-microcontroller-ATmega8_L_datasheet.pdf page 99 401 | How to find the correct value: (OCRxA +1) = F_CPU / prescaler / 1953.125 402 | OCR1A is 16 bit register 403 | */ 404 | 405 | TCCR1A = _BV(WGM12); // reset counter on match 406 | TCCR1B = _BV(CS11); // 1/8 prescaler 407 | #if F_CPU == 1000000UL 408 | OCR1A = (64 >> speedFactor) - 1; 409 | #elif F_CPU == 8000000UL 410 | OCR1A = (512 >> speedFactor) - 1; 411 | #elif F_CPU == 16000000UL 412 | OCR1A = (1024 >> speedFactor) - 1; 413 | #else 414 | #error "Manchester library only supports 1Mhz, 8mhz, 16mhz on ATMega8" 415 | #endif 416 | TIFR = _BV(OCF1A); // clear interrupt flag 417 | TIMSK = _BV(OCIE1A); // Turn on interrupt 418 | TCNT1 = 0; // Set counter to 0 419 | 420 | #else // ATmega328 is a default microcontroller 421 | 422 | 423 | /* 424 | Timer 2 is used with a ATMega328. 425 | http://www.atmel.com/dyn/resources/prod_documents/doc8161.pdf page 162 426 | How to find the correct value: (OCRxA +1) = F_CPU / prescaler / 1953.125 427 | OCR2A is only 8 bit register 428 | */ 429 | 430 | TCCR2A = _BV(WGM21); // reset counter on match 431 | #if F_CPU == 1000000UL 432 | TCCR2B = _BV(CS21); // 1/8 prescaler 433 | OCR2A = (64 >> speedFactor) - 1; 434 | #elif F_CPU == 8000000UL 435 | TCCR2B = _BV(CS21) | _BV(CS20); // 1/32 prescaler 436 | OCR2A = (128 >> speedFactor) - 1; 437 | #elif F_CPU == 16000000UL 438 | TCCR2B = _BV(CS22); // 1/64 prescaler 439 | OCR2A = (128 >> speedFactor) - 1; 440 | #else 441 | #error "Manchester library only supports 8mhz, 16mhz on ATMega328" 442 | #endif 443 | TIMSK2 = _BV(OCIE2A); // Turn on interrupt 444 | TCNT2 = 0; // Set counter to 0 445 | #endif 446 | 447 | } //end of setupReceive 448 | 449 | void MANRX_BeginReceive(void) 450 | { 451 | rx_maxBytes = 2; 452 | rx_data = rx_default_data; 453 | rx_mode = RX_MODE_PRE; 454 | } 455 | 456 | void MANRX_BeginReceiveBytes(uint8_t maxBytes, uint8_t *data) 457 | { 458 | rx_maxBytes = maxBytes; 459 | rx_data = data; 460 | rx_mode = RX_MODE_PRE; 461 | } 462 | 463 | void MANRX_StopReceive(void) 464 | { 465 | rx_mode = RX_MODE_IDLE; 466 | } 467 | 468 | uint8_t MANRX_ReceiveComplete(void) 469 | { 470 | return (rx_mode == RX_MODE_MSG); 471 | } 472 | 473 | uint8_t MANRX_GetMessage(void) 474 | { 475 | return (((int16_t)rx_data[0]) << 8) | (int16_t)rx_data[1]; 476 | } 477 | 478 | 479 | void MANRX_SetRxPin(uint8_t pin) 480 | { 481 | RxPin = pin; 482 | pinMode(RxPin, INPUT); 483 | }//end of set transmit pin 484 | 485 | void AddManBit(uint16_t *manBits, uint8_t *numMB, 486 | uint8_t *curByte, uint8_t *data, 487 | uint8_t bit) 488 | { 489 | *manBits <<= 1; 490 | *manBits |= bit; 491 | (*numMB)++; 492 | if (*numMB == 16) 493 | { 494 | uint8_t newData = 0; 495 | for (int8_t i = 0; i < 8; i++) 496 | { 497 | // ManBits holds 16 bits of manchester data 498 | // 1 = LO,HI 499 | // 0 = HI,LO 500 | // We can decode each bit by looking at the bottom bit of each pair. 501 | newData <<= 1; 502 | newData |= (*manBits & 1); // store the one 503 | *manBits = *manBits >> 2; //get next data bit 504 | } 505 | data[*curByte] = newData ^ DECOUPLING_MASK; 506 | (*curByte)++; 507 | 508 | // added by caoxp @ https://github.com/caoxp 509 | // compatible with unfixed-length data, with the data length defined by the first byte. 510 | // at a maximum of 255 total data length. 511 | if( (*curByte) == 1) 512 | { 513 | rx_maxBytes = data[0]; 514 | } 515 | 516 | *numMB = 0; 517 | } 518 | } 519 | 520 | 521 | 522 | #if defined( ESP8266 ) 523 | void ICACHE_RAM_ATTR timer0_ISR (void) 524 | #elif defined( __AVR_ATtiny25__ ) || defined( __AVR_ATtiny45__ ) || defined( __AVR_ATtiny85__ ) 525 | ISR(TIMER1_COMPA_vect) 526 | #elif defined( __AVR_ATtiny2313__ ) || defined( __AVR_ATtiny2313A__ ) || defined( __AVR_ATtiny4313__ ) 527 | ISR(TIMER1_COMPB_vect) 528 | #elif defined( __AVR_ATtiny24__ ) || defined( __AVR_ATtiny24A__ ) || defined( __AVR_ATtiny44__ ) || defined( __AVR_ATtiny44A__ ) || defined( __AVR_ATtiny84__ ) || defined( __AVR_ATtiny84A__ ) 529 | ISR(TIM1_COMPA_vect) 530 | #elif defined(__AVR_ATmega32U4__) 531 | ISR(TIMER3_COMPA_vect) 532 | #else 533 | ISR(TIMER2_COMPA_vect) 534 | #endif 535 | { 536 | if (rx_mode < RX_MODE_MSG) //receiving something 537 | { 538 | // Increment counter 539 | rx_count += 8; 540 | 541 | // Check for value change 542 | //rx_sample = digitalRead(RxPin); 543 | // caoxp@github, 544 | // add filter. 545 | // sample twice, only the same means a change. 546 | static uint8_t rx_sample_0=0; 547 | static uint8_t rx_sample_1=0; 548 | rx_sample_1 = digitalRead(RxPin); 549 | if( rx_sample_1 == rx_sample_0 ) 550 | { 551 | rx_sample = rx_sample_1; 552 | } 553 | rx_sample_0 = rx_sample_1; 554 | 555 | 556 | //check sample transition 557 | uint8_t transition = (rx_sample != rx_last_sample); 558 | 559 | if (rx_mode == RX_MODE_PRE) 560 | { 561 | // Wait for first transition to HIGH 562 | if (transition && (rx_sample == 1)) 563 | { 564 | rx_count = 0; 565 | rx_sync_count = 0; 566 | rx_mode = RX_MODE_SYNC; 567 | } 568 | } 569 | else if (rx_mode == RX_MODE_SYNC) 570 | { 571 | // Initial sync block 572 | if (transition) 573 | { 574 | if( ( (rx_sync_count < (SYNC_PULSE_MIN * 2) ) || (rx_last_sample == 1) ) && 575 | ( (rx_count < MinCount) || (rx_count > MaxCount))) 576 | { 577 | // First 20 bits and all 1 bits are expected to be regular 578 | // Transition was too slow/fast 579 | rx_mode = RX_MODE_PRE; 580 | } 581 | else if((rx_last_sample == 0) && 582 | ((rx_count < MinCount) || (rx_count > MaxLongCount))) 583 | { 584 | // 0 bits after the 20th bit are allowed to be a double bit 585 | // Transition was too slow/fast 586 | rx_mode = RX_MODE_PRE; 587 | } 588 | else 589 | { 590 | rx_sync_count++; 591 | 592 | if((rx_last_sample == 0) && 593 | (rx_sync_count >= (SYNC_PULSE_MIN * 2) ) && 594 | (rx_count >= MinLongCount)) 595 | { 596 | // We have seen at least 10 regular transitions 597 | // Lock sequence ends with unencoded bits 01 598 | // This is encoded and TX as HI,LO,LO,HI 599 | // We have seen a long low - we are now locked! 600 | rx_mode = RX_MODE_DATA; 601 | rx_manBits = 0; 602 | rx_numMB = 0; 603 | rx_curByte = 0; 604 | } 605 | else if (rx_sync_count >= (SYNC_PULSE_MAX * 2) ) 606 | { 607 | rx_mode = RX_MODE_PRE; 608 | } 609 | rx_count = 0; 610 | } 611 | } 612 | } 613 | else if (rx_mode == RX_MODE_DATA) 614 | { 615 | // Receive data 616 | if (transition) 617 | { 618 | if((rx_count < MinCount) || 619 | (rx_count > MaxLongCount)) 620 | { 621 | // wrong signal lenght, discard the message 622 | rx_mode = RX_MODE_PRE; 623 | } 624 | else 625 | { 626 | if(rx_count >= MinLongCount) // was the previous bit a double bit? 627 | { 628 | AddManBit(&rx_manBits, &rx_numMB, &rx_curByte, rx_data, rx_last_sample); 629 | } 630 | if ((rx_sample == 1) && 631 | (rx_curByte >= rx_maxBytes)) 632 | { 633 | rx_mode = RX_MODE_MSG; 634 | } 635 | else 636 | { 637 | // Add the current bit 638 | AddManBit(&rx_manBits, &rx_numMB, &rx_curByte, rx_data, rx_sample); 639 | rx_count = 0; 640 | } 641 | } 642 | } 643 | } 644 | 645 | // Get ready for next loop 646 | rx_last_sample = rx_sample; 647 | } 648 | #if defined( ESP8266 ) 649 | timer0_write(ESP.getCycleCount() + ESPtimer); 650 | #endif 651 | } 652 | 653 | Manchester man; 654 | -------------------------------------------------------------------------------- /Manchester.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | https://github.com/mchr3k/arduino-libs-manchester 5 | 6 | 7 | 8 | This code is based on the Atmel Corporation Manchester 9 | Coding Basics Application Note. 10 | 11 | http://www.atmel.com/dyn/resources/prod_documents/doc9164.pdf 12 | 13 | Quotes from the application note: 14 | 15 | "Manchester coding states that there will always be a transition of the message signal 16 | at the mid-point of the data bit frame. 17 | What occurs at the bit edges depends on the state of the previous bit frame and 18 | does not always produce a transition. A logical '1' is defined as a mid-point transition 19 | from low to high and a '0' is a mid-point transition from high to low. 20 | 21 | We use Timing Based Manchester Decode. 22 | In this approach we will capture the time between each transition coming from the demodulation 23 | circuit." 24 | 25 | Timer 2 is used with a ATMega328. Timer 1 is used for a ATtiny85 and ATtiny84 26 | 27 | This code gives a basic data rate as 1200 bauds. In manchester encoding we send 1 0 for a data bit 0. 28 | We send 0 1 for a data bit 1. This ensures an average over time of a fixed DC level in the TX/RX. 29 | This is required by the ASK RF link system to ensure its correct operation. 30 | The data rate is then 600 bits/s. Higher and lower rates are also supported. 31 | */ 32 | 33 | #ifndef MANCHESTER_h 34 | #define MANCHESTER_h 35 | 36 | //timer scaling factors for different transmission speeds 37 | #define MAN_300 0 38 | #define MAN_600 1 39 | #define MAN_1200 2 40 | #define MAN_2400 3 41 | #define MAN_4800 4 42 | #define MAN_9600 5 43 | #define MAN_19200 6 44 | #define MAN_38400 7 45 | 46 | /* 47 | Timer 2 in the ATMega328 and Timer 1 in a ATtiny85 is used to find the time between 48 | each transition coming from the demodulation circuit. 49 | Their setup is for sampling the input in regular intervals. 50 | For practical reasons we use power of 2 timer prescaller for sampling, 51 | for best timing we use pulse lenght as integer multiple of sampling speed. 52 | We chose to sample every 8 ticks, and pulse lenght of 48 ticks 53 | thats 6 samples per pulse, lower sampling rate (3) will not work well for 54 | innacurate clocks (like internal oscilator) higher sampling rate (12) will 55 | cause too much overhead and will not work at higher transmission speeds. 56 | This gives us 16000000Hz/48/256 = 1302 pulses per second (so it's not really 1200) 57 | At different transmission speeds or on different microcontroller frequencies, clock prescaller is adjusted 58 | to be compatible with those values. We allow about 50% clock speed difference both ways 59 | allowing us to transmit even with up to 100% in clock speed difference 60 | */ 61 | 62 | // added by caoxp@github 63 | // 64 | // the sync pulse amount for transmitting and receiving. 65 | // a pulse means : HI,LO or LO,HI 66 | // usually SYNC_PULSE_MAX >= SYNC_PULSE_DEF + 2 67 | // SYNC_PULSE_MIN <= SYNC_PULSE_DEF + 2 68 | // consider the pulses rising when starting transmitting. 69 | // SYNC_PULSE_MIN should be much less than SYNC_PULSE_DEF 70 | // all maximum of 255 71 | #define SYNC_PULSE_MIN 1 72 | #define SYNC_PULSE_DEF 3 73 | #define SYNC_PULSE_MAX 5 74 | 75 | //#define SYNC_PULSE_MIN 10 76 | //#define SYNC_PULSE_DEF 14 77 | //#define SYNC_PULSE_MAX 16 78 | 79 | //define to use 1 or 0 to sync 80 | // when using 1 to sync, sending SYNC_PULSE_DEF 1's , and send a 0 to start data. 81 | // and end the transimitting by three 1's 82 | // when using 0 to sync, sending SYNC_PULSE_DEF 0's , and send a 1 to start data. 83 | // and end the transimitting by three 0's 84 | 85 | #define SYNC_BIT_VALUE 0 86 | //decoding not finished. 87 | //#define SYNC_BIT_VALUE 0 88 | 89 | 90 | /* 91 | Signal timing, we take sample every 8 clock ticks 92 | 93 | ticks: [0]-[8]--[16]-[24]-[32]-[40]-[48]-[56]-[64]-[72]-[80]-[88]-[96][104][112][120][128][136] 94 | samples: |----|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----| 95 | single: | [--------|----------] 96 | double: | [-----------------|--------------------] 97 | signal: |_____________________________ ______________________ 98 | | |_____________________________| 99 | 100 | */ 101 | 102 | //setup timing for receiver 103 | #define MinCount 33 //pulse lower count limit on capture 104 | #define MaxCount 65 //pulse higher count limit on capture 105 | #define MinLongCount 66 //pulse lower count on double pulse 106 | #define MaxLongCount 129 //pulse higher count on double pulse 107 | 108 | //setup timing for transmitter 109 | #define HALF_BIT_INTERVAL 3072 //(=48 * 1024 * 1000000 / 16000000Hz) microseconds for speed factor 0 (300baud) 110 | 111 | //it's common to zero terminate a string or to transmit small numbers involving a lot of zeroes 112 | //those zeroes may be mistaken for training pattern, confusing the receiver and resulting high packet lost, 113 | //therefore we xor the data with random decoupling mask 114 | #define DECOUPLING_MASK 0b11001010 115 | 116 | #define RX_MODE_PRE 0 117 | #define RX_MODE_SYNC 1 118 | #define RX_MODE_DATA 2 119 | #define RX_MODE_MSG 3 120 | #define RX_MODE_IDLE 4 121 | 122 | #define TimeOutDefault -1 //the timeout in msec default blocks 123 | 124 | #if defined(ARDUINO) && ARDUINO >= 100 125 | #include "Arduino.h" 126 | #else 127 | #include "WProgram.h" 128 | #include 129 | #endif 130 | 131 | class Manchester 132 | { 133 | public: 134 | Manchester(); //the constructor 135 | void setTxPin(uint8_t pin); //set the arduino digital pin for transmit. 136 | void setRxPin(uint8_t pin); //set the arduino digital pin for receive. 137 | 138 | void workAround1MhzTinyCore(uint8_t a = 1); //apply workaround for defect in tiny Core library for 1Mhz 139 | void setupTransmit(uint8_t pin, uint8_t SF = MAN_1200); //set up transmission 140 | void setupReceive(uint8_t pin, uint8_t SF = MAN_1200); //set up receiver 141 | void setup(uint8_t Tpin, uint8_t Rpin, uint8_t SF = MAN_1200); //set up receiver 142 | 143 | void transmit(uint8_t data); //transmit 16 bits of data 144 | void transmitArray(uint8_t numBytes, uint8_t *data); // transmit array of bytes 145 | 146 | uint8_t decodeMessage(uint16_t m, uint8_t &id, uint8_t &data); //decode 8 bit payload and 4 bit ID from the message, return 1 of checksum is correct, otherwise 0 147 | uint16_t encodeMessage(uint8_t id, uint8_t data); //encode 8 bit payload, 4 bit ID and 4 bit checksum into 16 bit 148 | 149 | //wrappers for global functions 150 | void beginReceive(void); 151 | void beginReceiveArray(uint8_t maxBytes, uint8_t *data); 152 | uint8_t receiveComplete(void); 153 | uint8_t getMessage(void); 154 | void stopReceive(void); 155 | uint8_t speedFactor; 156 | uint16_t delay1; 157 | uint16_t delay2; 158 | 159 | private: 160 | void sendZero(void); 161 | void sendOne(void); 162 | uint8_t TxPin; 163 | uint8_t applyWorkAround1Mhz; 164 | };//end of class Manchester 165 | 166 | // Cant really do this as a real C++ class, since we need to have 167 | // an ISR 168 | extern "C" 169 | { 170 | //set the arduino digital pin for receive. default 4. 171 | extern void MANRX_SetRxPin(uint8_t pin); 172 | 173 | //begin the timer used to receive data 174 | extern void MANRX_SetupReceive(uint8_t speedFactor = MAN_1200); 175 | 176 | // begin receiving 16 bits 177 | extern void MANRX_BeginReceive(void); 178 | 179 | // begin receiving a byte array 180 | extern void MANRX_BeginReceiveBytes(uint8_t maxBytes, uint8_t *data); 181 | 182 | // true if a complete message is ready 183 | extern uint8_t MANRX_ReceiveComplete(void); 184 | 185 | // fetch the received message 186 | extern uint8_t MANRX_GetMessage(void); 187 | 188 | // stop receiving data 189 | extern void MANRX_StopReceive(void); 190 | } 191 | 192 | extern Manchester man; 193 | 194 | #endif 195 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | Full details available on the [Arduino Manchester Encoding site](http://mchr3k.github.com/arduino-libs-manchester/) -------------------------------------------------------------------------------- /examples/ManchesterRX_Array-unfixed_length/ManchesterRX_Array-unfixed_length.ino: -------------------------------------------------------------------------------- 1 | 2 | #include "Manchester.h" 3 | 4 | /* 5 | 6 | Manchester Receiver example 7 | 8 | In this example receiver will receive array of 10 bytes per transmittion 9 | 10 | try different speeds using this constants, your maximum possible speed will 11 | depend on various factors like transmitter type, distance, microcontroller speed, ... 12 | 13 | MAN_300 0 14 | MAN_600 1 15 | MAN_1200 2 16 | MAN_2400 3 17 | MAN_4800 4 18 | MAN_9600 5 19 | MAN_19200 6 20 | MAN_38400 7 21 | 22 | */ 23 | 24 | #define RX_PIN 4 25 | #define LED_PIN 13 26 | 27 | uint8_t moo = 1; 28 | #define BUFFER_SIZE 22 29 | uint8_t buffer[BUFFER_SIZE]; 30 | 31 | void setup() 32 | { 33 | pinMode(LED_PIN, OUTPUT); 34 | digitalWrite(LED_PIN, moo); 35 | Serial.begin(19200); 36 | man.setupReceive(RX_PIN, MAN_9600); 37 | man.beginReceiveArray(BUFFER_SIZE, buffer); 38 | } 39 | 40 | void loop() 41 | { 42 | if (man.receiveComplete()) 43 | { 44 | uint8_t receivedSize = 0; 45 | 46 | //do something with the data in 'buffer' here before you start receiving to the same buffer again 47 | receivedSize = buffer[0]; 48 | for(uint8_t i=1; i 3 | 4 | /* 5 | 6 | Manchester Transmitter example 7 | 8 | In this example transmitter will send 10 bytes array per transmittion 9 | 10 | try different speeds using this constants, your maximum possible speed will 11 | depend on various factors like transmitter type, distance, microcontroller speed, ... 12 | 13 | MAN_300 0 14 | MAN_600 1 15 | MAN_1200 2 16 | MAN_2400 3 17 | MAN_4800 4 18 | MAN_9600 5 19 | MAN_19200 6 20 | MAN_38400 7 21 | 22 | */ 23 | 24 | #define TX_PIN 5 //pin where your transmitter is connected 25 | #define LED_PIN 13 //pin for blinking LED 26 | 27 | uint8_t moo = 1; //last led status 28 | uint8_t data[20] = {11, '1','2', '3', '4', '5', '6', '7', '8', '9','1','2','3','4','5','6','7','8','9'}; 29 | 30 | void setup() 31 | { 32 | pinMode(LED_PIN, OUTPUT); 33 | digitalWrite(LED_PIN, moo); 34 | man.workAround1MhzTinyCore(); //add this in order for transmitter to work with 1Mhz Attiny85/84 35 | man.setupTransmit(TX_PIN, MAN_9600); 36 | } 37 | 38 | 39 | uint8_t datalength=2; //at least two data 40 | void loop() 41 | { 42 | 43 | data[0] = datalength; 44 | 45 | man.transmitArray(datalength, data); 46 | moo = ++moo % 2; 47 | digitalWrite(LED_PIN, moo); 48 | 49 | 50 | delay(800); 51 | datalength++; 52 | if(datalength>18) datalength=2; 53 | } 54 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | man LITERAL1 2 | Manchester KEYWORD1 3 | setTxPin KEYWORD2 4 | setRxPin KEYWORD2 5 | setupTransmit KEYWORD2 6 | setupReceive KEYWORD2 7 | setup KEYWORD2 8 | transmit KEYWORD2 9 | transmitBytes KEYWORD2 10 | decodeMessage KEYWORD2 11 | encodeMessage KEYWORD2 12 | beginReceive KEYWORD2 13 | beginReceiveBytes KEYWORD2 14 | receiveComplete KEYWORD2 15 | getMessage KEYWORD2 16 | stopReceive KEYWORD2 17 | workAround1MhzTinyCore KEYWORD2 18 | 19 | -------------------------------------------------------------------------------- /library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Manchester", 3 | "keywords": "rf, radio, wireless", 4 | "description": "This is a Manchester encoding RF library which works on Arduino and ATTiny.", 5 | "authors": { 6 | "name": "mchr3k", 7 | "url": "https://github.com/mchr3k/arduino-libs-manchester" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/mchr3k/arduino-libs-manchester.git" 12 | }, 13 | "version": "1.0", 14 | "frameworks": "arduino", 15 | "platforms": ["atmelavr"] 16 | } 17 | --------------------------------------------------------------------------------