mirror of
				https://github.com/Show-maket/IR-protocol.git
				synced 2025-10-29 10:02:36 +00:00 
			
		
		
		
	Compare commits
	
		
			61 Commits
		
	
	
		
			main
			...
			STM32-opti
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 2d839d3ff8 | |||
| 6ba8fdffe4 | |||
| aa0b478229 | |||
| 277985f79a | |||
| 444b84c313 | |||
| 2db1ef7805 | |||
| 1353ab6f75 | |||
| d1cb167aaf | |||
| 30ad816c2a | |||
| ecfb3b5f98 | |||
| 70a22463ef | |||
| 71f58a4992 | |||
| b6b9d2c820 | |||
| 98a21f5e56 | |||
| 591727546e | |||
| 79bb804bb4 | |||
| 0471b8cc89 | |||
| 90c41cfe2b | |||
| 1ecc33e9c4 | |||
| 7ef8158a00 | |||
| 341ff3a470 | |||
| e6dbdcee74 | |||
| cf5a6641f4 | |||
| da152c65ee | |||
| 8f77c60cba | |||
| fd51a4935c | |||
| aa862d8f2c | |||
| 7c9529d42f | |||
| d4dd0e95fd | |||
| 04af094f4b | |||
| 2f4ac3ddf8 | |||
| 784365181e | |||
| c66d47e464 | |||
| 3057e78aeb | |||
| a958c1d3b2 | |||
| 2147bf0788 | |||
| e37d4d79f1 | |||
| 373cd43b73 | |||
| 96f0ac623e | |||
| d46640b145 | |||
| e752d0fb50 | |||
| 5a5142e0aa | |||
| e951111c53 | |||
| 06d27f2590 | |||
| 3965616cd1 | |||
| 16da39a293 | |||
| 16a626db22 | |||
| 5cc4555bac | |||
| e334625864 | |||
| 03d74e30cd | |||
| 2972560b13 | |||
| 4d12f77a8b | |||
| 3b5045669b | |||
| 99e523129d | |||
| 0b888a5840 | |||
| 9643670942 | |||
| fd62972717 | |||
| e5983c8367 | |||
| d774f87f7a | |||
| 27a5b28a17 | |||
| ff306e7fae | 
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1 +1,5 @@ | ||||
| .vscode/* | ||||
| bin/* | ||||
| !.vscode/launch.json | ||||
| log/* | ||||
| /.vscode | ||||
|  | ||||
							
								
								
									
										5
									
								
								.vscode/arduino.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.vscode/arduino.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| { | ||||
|     "board": "STMicroelectronics:stm32:GenF4", | ||||
|     "port": "COM17", | ||||
|     "prebuild": "if exist bin rd /s /q bin" | ||||
| } | ||||
							
								
								
									
										20
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | ||||
| { | ||||
|     // Use IntelliSense to learn about possible attributes. | ||||
|     // Hover to view descriptions of existing attributes. | ||||
|     // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 | ||||
|     "version": "0.2.0", | ||||
|     "configurations": [ | ||||
|        | ||||
|       { | ||||
|         "cwd": "${workspaceFolder}", | ||||
|         "executable": "${workspaceFolder}/bin/${workspaceFolderBasename}.ino.elf", | ||||
|         "name": "Debug with ST-Link", | ||||
|         "request": "launch", | ||||
|         "type": "cortex-debug", | ||||
|         "runToEntryPoint": "main", | ||||
|         "showDevDebugOutput": "raw", | ||||
|         "servertype": "stlink", | ||||
|         "armToolchainPath": "C://Program Files (x86)//Arm GNU Toolchain arm-none-eabi//13.2 Rel1//bin" | ||||
|       } | ||||
|     ] | ||||
|   } | ||||
							
								
								
									
										606
									
								
								IR-protocol.ino
									
									
									
									
									
								
							
							
						
						
									
										606
									
								
								IR-protocol.ino
									
									
									
									
									
								
							| @ -4,13 +4,24 @@ | ||||
| #include "MemoryCheck.h" | ||||
| /////////////// Pinout /////////////// | ||||
|  | ||||
| #define encForward_PIN    5 | ||||
| #define encBackward_PIN   6 | ||||
| #define dec0_PIN PIN_KT1_IN | ||||
| #define dec1_PIN PIN_KT2_IN | ||||
| #define dec2_PIN PIN_KT3_IN | ||||
| #define dec3_PIN PIN_KT4_IN | ||||
| #define dec4_PIN PIN_KT5_IN | ||||
| #define dec5_PIN PIN_KT6_IN | ||||
| #define dec6_PIN PIN_KT7_IN | ||||
| #define dec7_PIN PIN_KT8_IN | ||||
| // #define dec8_PIN PB8 | ||||
| // #define dec9_PIN PB9 | ||||
| // #define dec10_PIN PB10 | ||||
| // #define dec11_PIN PB11 | ||||
| // #define dec12_PIN PB12 | ||||
| // #define dec13_PIN PB13 | ||||
| // #define dec14_PIN PB14 | ||||
| // #define dec15_PIN PB15 | ||||
|  | ||||
| #define LoopOut 12 | ||||
| #define ISR_Out 10 | ||||
|  | ||||
| #define TestOut 13 | ||||
| #define LoopOut PC13 | ||||
|  | ||||
| //////////////// Ini ///////////////// | ||||
|  | ||||
| @ -18,191 +29,252 @@ | ||||
| #define SERIAL_SPEED 115200 | ||||
|  | ||||
| //////////////// Var ///////////////// | ||||
| // IR_Encoder encForward(PA5, 42 /* , &decBackward */); | ||||
|  | ||||
| IR_Decoder decForward(2, 555); | ||||
| IR_Decoder decBackward(3, 777); | ||||
| IR_Encoder enc0(PIN_KT8_OUT, 42 /* , &decBackward */); | ||||
| // IR_Encoder enc1(PA1, 127 /* , &decBackward */); | ||||
| // IR_Encoder enc2(PA2, 137 /* , &decBackward */); | ||||
| // IR_Encoder enc3(PA3, 777 /* , &decBackward */); | ||||
| // IR_Encoder enc10(PA4, 555 /* , &decBackward */); | ||||
| // IR_Encoder enc11(PC14, 127 /* , &decBackward */); | ||||
| // IR_Encoder enc12(PC13, 137 /* , &decBackward */); | ||||
| // IR_Encoder enc13(PA12, 777 /* , &decBackward */); | ||||
|  | ||||
| IR_Encoder encForward(42/* , &decBackward */); | ||||
| // IR_Encoder encBackward(321, encBackward_PIN); | ||||
| // IR_Encoder encTree(325, A2); | ||||
|  | ||||
| //////////////////////// Функции прерываний //////////////////////// | ||||
|  | ||||
| void decForwardISR() { | ||||
|     decForward.isr(); | ||||
| void EncoderISR() | ||||
| { | ||||
|     IR_Encoder::isr(); | ||||
| } | ||||
|  | ||||
| // void decBackwardISR() { | ||||
| //     decBackward.isr(); | ||||
| // } | ||||
| //------------------------------------------------------------------- | ||||
|  | ||||
| IR_Decoder dec0(dec0_PIN, 0); | ||||
| void dec_0_ISR() { dec0.isr(); } | ||||
|  | ||||
| IR_Decoder dec1(dec1_PIN, 1); | ||||
| void dec_1_ISR() { dec1.isr(); } | ||||
|  | ||||
| IR_Decoder dec2(dec2_PIN, 2); | ||||
| void dec_2_ISR() { dec2.isr(); } | ||||
|  | ||||
| IR_Decoder dec3(dec3_PIN, 3); | ||||
| void dec_3_ISR() { dec3.isr(); } | ||||
|  | ||||
| IR_Decoder dec4(dec4_PIN, 4); | ||||
| void dec_4_ISR() { dec4.isr(); } | ||||
|  | ||||
| IR_Decoder dec5(dec5_PIN, 5); | ||||
| void dec_5_ISR() { dec5.isr(); } | ||||
|  | ||||
| IR_Decoder dec6(dec6_PIN, 6); | ||||
| void dec_6_ISR() { dec6.isr(); } | ||||
|  | ||||
| IR_Decoder dec7(dec7_PIN, 7); | ||||
| void dec_7_ISR() { dec7.isr(); } | ||||
|  | ||||
| // IR_Decoder dec8(dec8_PIN, 8); | ||||
| // void dec_8_ISR() { dec8.isr(); } | ||||
|  | ||||
| // IR_Decoder dec9(dec9_PIN, 9); | ||||
| // void dec_9_ISR() { dec9.isr(); } | ||||
|  | ||||
| // IR_Decoder dec10(dec10_PIN, 10); | ||||
| // void dec_10_ISR() { dec10.isr(); } | ||||
|  | ||||
| // IR_Decoder dec11(dec11_PIN, 11); | ||||
| // void dec_11_ISR() { dec11.isr(); } | ||||
|  | ||||
| // IR_Decoder dec12(dec12_PIN, 12); | ||||
| // void dec_12_ISR() { dec12.isr(); } | ||||
|  | ||||
| // IR_Decoder dec13(dec13_PIN, 13); | ||||
| // void dec_13_ISR() { dec13.isr(); } | ||||
|  | ||||
| static uint8_t* portOut; | ||||
| ISR(TIMER2_COMPA_vect) { | ||||
|     encForward.isr(); | ||||
|     // encBackward.isr(); | ||||
|     // encTree.isr(); | ||||
|     //TODO: Сделать выбор порта  | ||||
|     *portOut = (*portOut & 0b11001111) | | ||||
|         ( | ||||
|             encForward.ir_out_virtual << 5U | ||||
|             // | encBackward.ir_out_virtual << 6U | ||||
|             // | encTree.ir_out_virtual << 2U | ||||
|             ); | ||||
| } | ||||
| ///////////////////////////////////////////////////////////////////// | ||||
| uint8_t data0 [] = { }; | ||||
| uint8_t data1 [] = { 42 }; | ||||
| uint8_t data2 [] = { 42 , 127 }; | ||||
| uint8_t data3 [] = { 42 , 127, 137 }; | ||||
| uint8_t data4 [] = { 42 , 127, 137, 255 }; | ||||
| uint8_t data0[] = {}; | ||||
| uint8_t data1[] = {42}; | ||||
| uint8_t data2[] = {42, 127}; | ||||
| uint8_t data3[] = {42, 127, 137}; | ||||
| uint8_t data4[] = {42, 127, 137, 255}; | ||||
|  | ||||
| uint32_t loopTimer; | ||||
| uint8_t sig = 0; | ||||
|  | ||||
| uint16_t targetAddr = IR_Broadcast; | ||||
| Timer t1(500, millis, []() { | ||||
|  | ||||
| Timer t1(500, millis, []() | ||||
|          { | ||||
|              // Serial.println( digitalPinToBitMask(enc0.getPin()), BIN); | ||||
|             //  enc0.sendData(IR_Broadcast, data4, sizeof(data4)); | ||||
|             //  enc1.sendData(IR_Broadcast, data3, sizeof(data3)); | ||||
|             //  enc2.sendData(IR_Broadcast, data2, sizeof(data2)); | ||||
|             //  enc3.sendData(IR_Broadcast, data1, sizeof(data1)); | ||||
|             //  enc10.sendData(IR_Broadcast, data4, sizeof(data4)); | ||||
|              //  enc11.sendData(IR_Broadcast, data3, sizeof(data3)); | ||||
|              //  enc12.sendData(IR_Broadcast, data2, sizeof(data2)); | ||||
|              //  enc13.sendData(IR_Broadcast, data1, sizeof(data1)); | ||||
|  | ||||
|              // Serial.println(sig); | ||||
|  | ||||
|     switch (sig) { | ||||
|         case 0: | ||||
|             encForward.sendData(targetAddr); | ||||
|             break; | ||||
|         case 1: | ||||
|             encForward.sendData(targetAddr, data1, sizeof(data1)); | ||||
|             break; | ||||
|         case 2: | ||||
|             encForward.sendData(targetAddr, data2, sizeof(data2)); | ||||
|             break; | ||||
|         case 3: | ||||
|             encForward.sendData(targetAddr, data3, sizeof(data3)); | ||||
|             break; | ||||
|         case 4: | ||||
|             encForward.sendData(targetAddr, data4, sizeof(data4)); | ||||
|             break; | ||||
|              //  switch (sig) | ||||
|              //  { | ||||
|              //  case 0: | ||||
|              //      encForward.sendData(targetAddr); | ||||
|              //      break; | ||||
|              //  case 1: | ||||
|              //      encForward.sendData(targetAddr, data1, sizeof(data1)); | ||||
|              //      break; | ||||
|              //  case 2: | ||||
|              //      encForward.sendData(targetAddr, data2, sizeof(data2)); | ||||
|              //      break; | ||||
|              //  case 3: | ||||
|              //      encForward.sendData(targetAddr, data3, sizeof(data3)); | ||||
|              //      break; | ||||
|              //  case 4: | ||||
|              //      encForward.sendData(targetAddr, data4, sizeof(data4)); | ||||
|              //      break; | ||||
|  | ||||
|         case 10: | ||||
|             encForward.sendData(targetAddr, data0, sizeof(data0), true); | ||||
|             break; | ||||
|         case 11: | ||||
|             encForward.sendData(targetAddr, data1, sizeof(data1), true); | ||||
|             break; | ||||
|         case 12: | ||||
|             encForward.sendData(targetAddr, data2, sizeof(data2), true); | ||||
|             break; | ||||
|         case 13: | ||||
|             encForward.sendData(targetAddr, data3, sizeof(data3), true); | ||||
|             break; | ||||
|         case 14: | ||||
|             encForward.sendData(targetAddr, data4, sizeof(data4), true); | ||||
|             break; | ||||
|              //  case 10: | ||||
|              //      encForward.sendData(targetAddr, data0, sizeof(data0), true); | ||||
|              //      break; | ||||
|              //  case 11: | ||||
|              //      encForward.sendData(targetAddr, data1, sizeof(data1), true); | ||||
|              //      break; | ||||
|              //  case 12: | ||||
|              //      encForward.sendData(targetAddr, data2, sizeof(data2), true); | ||||
|              //      break; | ||||
|              //  case 13: | ||||
|              //      encForward.sendData(targetAddr, data3, sizeof(data3), true); | ||||
|              //      break; | ||||
|              //  case 14: | ||||
|              //      encForward.sendData(targetAddr, data4, sizeof(data4), true); | ||||
|              //      break; | ||||
|  | ||||
|              //  case 20: | ||||
|              //      encForward.sendBack(); | ||||
|              //      break; | ||||
|              //  case 21: | ||||
|              //      encForward.sendBack(data1, sizeof(data1)); | ||||
|              //      break; | ||||
|              //  case 22: | ||||
|              //      encForward.sendBack(data2, sizeof(data2)); | ||||
|              //      break; | ||||
|              //  case 23: | ||||
|              //      encForward.sendBack(data3, sizeof(data3)); | ||||
|              //      break; | ||||
|              //  case 24: | ||||
|              //      encForward.sendBack(data4, sizeof(data4)); | ||||
|              //      break; | ||||
|  | ||||
|              //  case 30: | ||||
|              //      encForward.sendBackTo(targetAddr); | ||||
|              //      break; | ||||
|              //  case 31: | ||||
|              //      encForward.sendBackTo(targetAddr, data1, sizeof(data1)); | ||||
|              //      break; | ||||
|              //  case 32: | ||||
|              //      encForward.sendBackTo(targetAddr, data2, sizeof(data2)); | ||||
|              //      break; | ||||
|              //  case 33: | ||||
|              //      encForward.sendBackTo(targetAddr, data3, sizeof(data3)); | ||||
|              //      break; | ||||
|              //  case 34: | ||||
|              //      encForward.sendBackTo(targetAddr, data4, sizeof(data4)); | ||||
|              //      break; | ||||
|  | ||||
|         case 20: | ||||
|             encForward.sendBack(); | ||||
|             break; | ||||
|         case 21: | ||||
|             encForward.sendBack(data1, sizeof(data1)); | ||||
|             break; | ||||
|         case 22: | ||||
|             encForward.sendBack(data2, sizeof(data2)); | ||||
|             break; | ||||
|         case 23: | ||||
|             encForward.sendBack(data3, sizeof(data3)); | ||||
|             break; | ||||
|         case 24: | ||||
|             encForward.sendBack(data4, sizeof(data4)); | ||||
|             break; | ||||
|              //  case 41: | ||||
|              //      encForward.sendRequest(targetAddr); | ||||
|              //      break; | ||||
|              //  case 42: | ||||
|              //      encForward.sendAccept(targetAddr); | ||||
|              //      break; | ||||
|  | ||||
|         case 30: | ||||
|             encForward.sendBackTo(targetAddr); | ||||
|             break; | ||||
|         case 31: | ||||
|             encForward.sendBackTo(targetAddr, data1, sizeof(data1)); | ||||
|             break; | ||||
|         case 32: | ||||
|             encForward.sendBackTo(targetAddr, data2, sizeof(data2)); | ||||
|             break; | ||||
|         case 33: | ||||
|             encForward.sendBackTo(targetAddr, data3, sizeof(data3)); | ||||
|             break; | ||||
|         case 34: | ||||
|             encForward.sendBackTo(targetAddr, data4, sizeof(data4)); | ||||
|             break; | ||||
|  | ||||
|         case 41: | ||||
|             encForward.sendRequest(targetAddr); | ||||
|             break; | ||||
|         case 42: | ||||
|             encForward.sendAccept(targetAddr); | ||||
|             break; | ||||
|  | ||||
|  | ||||
|         default: | ||||
|             break; | ||||
|     } | ||||
|              //  default: | ||||
|              //      break; | ||||
|              //  } | ||||
|              // encBackward.sendData(IR_Broadcast, data2); | ||||
|              // encTree.sendData(IR_Broadcast, rawData3); | ||||
| }); | ||||
| Timer t2(500, millis, []() { | ||||
|     digitalToggle(13); | ||||
| }); | ||||
|          }); | ||||
|  | ||||
| // Timer t2(50, millis, []() | ||||
| //          { digitalToggle(LED_BUILTIN); }); | ||||
|  | ||||
| Timer signalDetectTimer; | ||||
| ///////////////////////////////////////////////////////////////////// | ||||
| void setup() { | ||||
|     IR_Encoder::timerSetup(); | ||||
|     portOut = &PORTD; | ||||
| HardwareTimer IR_Timer(TIM3); | ||||
|  | ||||
| void setup() | ||||
| { | ||||
|     IR_Timer.setOverflow(carrierFrec * 2, HERTZ_FORMAT); | ||||
|     IR_Timer.attachInterrupt(1, EncoderISR); | ||||
|     NVIC_SetPriority(IRQn_Type::TIM3_IRQn, 0); | ||||
|     IR_Timer.resume(); | ||||
|  | ||||
|     Serial.begin(SERIAL_SPEED); | ||||
|     Serial.println(F(INFO)); | ||||
|  | ||||
|     pinMode(A0, INPUT_PULLUP); | ||||
|     pinMode(A1, INPUT_PULLUP); | ||||
|     pinMode(A2, INPUT_PULLUP); | ||||
|     pinMode(A3, INPUT_PULLUP); | ||||
|  | ||||
|     pinMode(LoopOut, OUTPUT); | ||||
|     pinMode(ISR_Out, OUTPUT); | ||||
|  | ||||
|     pinMode(2, INPUT_PULLUP); | ||||
|     pinMode(3, INPUT_PULLUP); | ||||
|     pinMode(dec0_PIN, INPUT_PULLUP); | ||||
|     pinMode(dec1_PIN, INPUT_PULLUP); | ||||
|     pinMode(dec2_PIN, INPUT_PULLUP); | ||||
|     pinMode(dec3_PIN, INPUT_PULLUP); | ||||
|     pinMode(dec4_PIN, INPUT_PULLUP); | ||||
|     pinMode(dec5_PIN, INPUT_PULLUP); | ||||
|     pinMode(dec6_PIN, INPUT_PULLUP); | ||||
|     pinMode(dec7_PIN, INPUT_PULLUP); | ||||
|     // pinMode(dec8_PIN, INPUT_PULLUP); | ||||
|     // pinMode(dec9_PIN, INPUT_PULLUP); | ||||
|     // pinMode(dec10_PIN, INPUT_PULLUP); | ||||
|     // pinMode(dec11_PIN, INPUT_PULLUP); | ||||
|     // pinMode(dec12_PIN, INPUT_PULLUP); | ||||
|     // pinMode(dec13_PIN, INPUT_PULLUP); | ||||
|  | ||||
|     pinMode(8, OUTPUT); | ||||
|     pinMode(9, OUTPUT); | ||||
|     pinMode(11, OUTPUT); | ||||
|     pinMode(13, OUTPUT); | ||||
|     pinMode(encForward_PIN, OUTPUT); | ||||
|     pinMode(encBackward_PIN, OUTPUT); | ||||
|     pinMode(13, OUTPUT); | ||||
|  | ||||
|  | ||||
|  | ||||
|     // IR_DecoderRaw* blindFromForward [] { &decForward, &decBackward }; | ||||
|     // encForward.setBlindDecoders(blindFromForward, sizeof(blindFromForward) / sizeof(IR_DecoderRaw*)); | ||||
|  | ||||
|  | ||||
|     attachInterrupt(0, decForwardISR, CHANGE);  // D2  | ||||
|     // attachInterrupt(1, decBackwardISR, CHANGE); // D3 | ||||
|     attachInterrupt(dec0_PIN, dec_0_ISR, CHANGE); | ||||
|     attachInterrupt(dec1_PIN, dec_1_ISR, CHANGE); | ||||
|     attachInterrupt(dec2_PIN, dec_2_ISR, CHANGE); | ||||
|     attachInterrupt(dec3_PIN, dec_3_ISR, CHANGE); | ||||
|     attachInterrupt(dec4_PIN, dec_4_ISR, CHANGE); | ||||
|     attachInterrupt(dec5_PIN, dec_5_ISR, CHANGE); | ||||
|     attachInterrupt(dec6_PIN, dec_6_ISR, CHANGE); | ||||
|     attachInterrupt(dec7_PIN, dec_7_ISR, CHANGE); | ||||
|     // attachInterrupt(dec8_PIN, dec_8_ISR, CHANGE); | ||||
|     // attachInterrupt(dec9_PIN, dec_9_ISR, CHANGE); | ||||
|     // attachInterrupt(dec10_PIN, dec_10_ISR, CHANGE); | ||||
|     // attachInterrupt(dec11_PIN, dec_11_ISR, CHANGE); | ||||
|     // attachInterrupt(dec12_PIN, dec_12_ISR, CHANGE); | ||||
|     // attachInterrupt(dec13_PIN, dec_13_ISR, CHANGE); | ||||
| } | ||||
|  | ||||
| void loop() { | ||||
| void loop() | ||||
| { | ||||
|     digitalToggle(LoopOut); | ||||
|     Timer::tick(); | ||||
|     IR_Decoder::tick(); | ||||
|  | ||||
|     decForward.tick(); | ||||
|     decBackward.tick(); | ||||
|     bool rx_flag = false; | ||||
|     rx_flag |= status(dec0); | ||||
|     rx_flag |= status(dec1); | ||||
|     rx_flag |= status(dec2); | ||||
|     rx_flag |= status(dec3); | ||||
|     rx_flag |= status(dec4); | ||||
|     rx_flag |= status(dec5); | ||||
|     rx_flag |= status(dec6); | ||||
|     rx_flag |= status(dec7); | ||||
|     // rx_flag |= status(dec8); | ||||
|     // rx_flag |= status(dec9); | ||||
|     // rx_flag |= status(dec10); | ||||
|     // rx_flag |= status(dec11); | ||||
|     // rx_flag |= status(dec12); | ||||
|     // rx_flag |= status(dec13); | ||||
|  | ||||
|     status(decForward); | ||||
|     // status(decBackward); | ||||
|  | ||||
|  | ||||
|     // Serial.println(micros() - loopTimer); | ||||
|     // loopTimer = micros(); | ||||
|     // delayMicroseconds(120*5); | ||||
|  | ||||
|     if (Serial.available()) { | ||||
|     if (Serial.available()) | ||||
|     { | ||||
|         uint8_t in = Serial.parseInt(); | ||||
|         switch (in) { | ||||
|         switch (in) | ||||
|         { | ||||
|         case 100: | ||||
|             targetAddr = IR_Broadcast; | ||||
|             break; | ||||
| @ -212,7 +284,6 @@ void loop() { | ||||
|         case 102: | ||||
|             targetAddr = 777; | ||||
|             break; | ||||
|  | ||||
|         default: | ||||
|             sig = in; | ||||
|             break; | ||||
| @ -221,35 +292,72 @@ void loop() { | ||||
| } | ||||
|  | ||||
|  | ||||
| Timer statusSimpleDelay; | ||||
| bool statusSimple(IR_Decoder &dec) | ||||
| { | ||||
|     bool ret; | ||||
|     if (ret = dec.gotData.available()) | ||||
|     { | ||||
|         Serial.print("DEC: "); | ||||
|         Serial.print(dec.getId()); | ||||
|         Serial.print("   err:  "); | ||||
|         Serial.print(dec.gotData.getErrorCount()); | ||||
|         Serial.print("\n"); | ||||
|         statusSimpleDelay.delay(100, millis, []() | ||||
|                                 { Serial.print("\n\n\n\n"); }); | ||||
|     } | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| void detectSignal() | ||||
| { | ||||
|     // digitalWrite(SignalDetectLed, HIGH); | ||||
|     // signalDetectTimer.delay(50, millis, []() | ||||
|     //                         { digitalWrite(SignalDetectLed, LOW); }); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| //test | ||||
| void status(IR_Decoder& dec) { | ||||
|     if (dec.gotData.available()) { | ||||
| // test | ||||
| bool status(IR_Decoder &dec) | ||||
| { | ||||
|     if (dec.gotData.available()) | ||||
|     { | ||||
|         detectSignal(); | ||||
|         // Serial.println(micros()); | ||||
|         String str; | ||||
|         if (/* dec.gotData.getDataPrt()[1] */1) { | ||||
|             str += ("Data on pin ");        str += (dec.isrPin); str += "\n"; | ||||
|         if (/* dec.gotData.getDataPrt()[1] */ 1) | ||||
|         { | ||||
|             str += ("Data on pin "); | ||||
|             str += (dec.getPin()); | ||||
|             str += "\n"; | ||||
|  | ||||
|             uint8_t msg = dec.gotData.getMsgRAW(); | ||||
|             str += ("  MSG: "); | ||||
|             for (size_t i = 0; i < 8; i++) { | ||||
|                 if (i == 3) str += " "; | ||||
|             for (size_t i = 0; i < 8; i++) | ||||
|             { | ||||
|                 if (i == 3) | ||||
|                     str += " "; | ||||
|                 str += (msg >> (7 - i)) & 1U; | ||||
|             } | ||||
|  | ||||
|             str += "\n"; | ||||
|  | ||||
|             str += ("  DATA SIZE: "); str += (dec.gotData.getDataSize()); str += "\n"; | ||||
|             str += ("  ADDRESS FROM: "); str += (dec.gotData.getAddrFrom()); str += "\n"; | ||||
|             str += ("  ADDRESS TO: "); str += (dec.gotData.getAddrTo()); str += "\n"; | ||||
|             str += ("  DATA SIZE: "); | ||||
|             str += (dec.gotData.getDataSize()); | ||||
|             str += "\n"; | ||||
|             str += ("  ADDRESS FROM: "); | ||||
|             str += (dec.gotData.getAddrFrom()); | ||||
|             str += "\n"; | ||||
|             str += ("  ADDRESS TO: "); | ||||
|             str += (dec.gotData.getAddrTo()); | ||||
|             str += "\n"; | ||||
|             // str += ("  CRC PACK: "); str += (dec.gotData.getCrcIN()); str += "\n"; | ||||
|             // str += ("  CRC CALC: "); str += (dec.gotData.getCrcCALC()); str += "\n"; | ||||
|             str += "\n"; | ||||
|  | ||||
|             for (size_t i = 0; i < min(10, dec.gotData.getDataSize()); i++) { | ||||
|                 switch (i) { | ||||
|             for (size_t i = 0; i < min(uint8_t(10), dec.gotData.getDataSize()); i++) | ||||
|             { | ||||
|                 switch (i) | ||||
|                 { | ||||
|                     // case 0: | ||||
|                     //     str += ("  ADDR: "); | ||||
|                     //     break; | ||||
| @ -258,48 +366,70 @@ void status(IR_Decoder& dec) { | ||||
|                     //     break; | ||||
|  | ||||
|                 default: | ||||
|                         str += ("  Data["); str += (i); str += ("]: "); | ||||
|                     str += ("  Data["); | ||||
|                     str += (i); | ||||
|                     str += ("]: "); | ||||
|                     break; | ||||
|                 } | ||||
|                 str += (dec.gotData.getDataPrt()[i]); str += "\n"; | ||||
|                 str += (dec.gotData.getDataPrt()[i]); | ||||
|                 str += "\n"; | ||||
|             } | ||||
|  | ||||
|  | ||||
|             str += ("\n*******ErrAll: ");     str += (dec.gotData.getErrorCount()); str += "\n"; | ||||
|             str += ("**ErrDistance: ");     str += ((int)(dec.gotData.getErrorHighSignal() - dec.gotData.getErrorLowSignal())); str += "\n"; | ||||
|             str += ("\n*******ErrAll: "); | ||||
|             str += (dec.gotData.getErrorCount()); | ||||
|             str += "\n"; | ||||
|             str += ("**ErrDistance: "); | ||||
|             str += ((int)(dec.gotData.getErrorHighSignal() - dec.gotData.getErrorLowSignal())); | ||||
|             str += "\n"; | ||||
|  | ||||
|             str += "\n"; | ||||
|         } else { | ||||
|             str += ("SELF"); str += "\n"; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             str += ("SELF"); | ||||
|             str += "\n"; | ||||
|             str += "\n"; | ||||
|         } | ||||
|         // obj->resetAvailable(); | ||||
|         Serial.write(str.c_str()); | ||||
|     } | ||||
|  | ||||
|     if (dec.gotBackData.available()) { | ||||
|     if (dec.gotBackData.available()) | ||||
|     { | ||||
|         detectSignal(); | ||||
|         String str; | ||||
|         if (/* dec.gotData.getDataPrt()[1] */1) { | ||||
|             str += ("BackData on pin ");        str += (dec.isrPin); str += "\n"; | ||||
|         if (/* dec.gotData.getDataPrt()[1] */ 1) | ||||
|         { | ||||
|             str += ("BackData on pin "); | ||||
|             str += (dec.getPin()); | ||||
|             str += "\n"; | ||||
|  | ||||
|             uint8_t msg = dec.gotBackData.getMsgRAW(); | ||||
|             str += ("  MSG: "); | ||||
|             for (size_t i = 0; i < 8; i++) { | ||||
|                 if (i == 3) str += " "; | ||||
|             for (size_t i = 0; i < 8; i++) | ||||
|             { | ||||
|                 if (i == 3) | ||||
|                     str += " "; | ||||
|                 str += (msg >> (7 - i)) & 1U; | ||||
|             } | ||||
|  | ||||
|             str += "\n"; | ||||
|  | ||||
|             str += ("  DATA SIZE: "); str += (dec.gotBackData.getDataSize()); str += "\n"; | ||||
|             str += ("  ADDRESS FROM: "); str += (dec.gotBackData.getAddrFrom()); str += "\n"; | ||||
|             str += ("  DATA SIZE: "); | ||||
|             str += (dec.gotBackData.getDataSize()); | ||||
|             str += "\n"; | ||||
|             str += ("  ADDRESS FROM: "); | ||||
|             str += (dec.gotBackData.getAddrFrom()); | ||||
|             str += "\n"; | ||||
|             // str += ("  ADDRESS TO: "); str += (dec.gotBackData.getAddrTo()); str += "\n"; | ||||
|             // str += ("  CRC PACK: "); str += (dec.gotBackData.getCrcIN()); str += "\n"; | ||||
|             // str += ("  CRC CALC: "); str += (dec.gotBackData.getCrcCALC()); str += "\n"; | ||||
|             str += "\n"; | ||||
|  | ||||
|             for (size_t i = 0; i < min(10, dec.gotBackData.getDataSize()); i++) { | ||||
|                 switch (i) { | ||||
|             for (size_t i = 0; i < min(uint8_t(10), dec.gotBackData.getDataSize()); i++) | ||||
|             { | ||||
|                 switch (i) | ||||
|                 { | ||||
|                     // case 0: | ||||
|                     //     str += ("  ADDR: "); | ||||
|                     //     break; | ||||
| @ -308,97 +438,135 @@ void status(IR_Decoder& dec) { | ||||
|                     //     break; | ||||
|  | ||||
|                 default: | ||||
|                         str += ("  Data["); str += (i); str += ("]: "); | ||||
|                     str += ("  Data["); | ||||
|                     str += (i); | ||||
|                     str += ("]: "); | ||||
|                     break; | ||||
|                 } | ||||
|                 str += (dec.gotBackData.getDataPrt()[i]); str += "\n"; | ||||
|                 str += (dec.gotBackData.getDataPrt()[i]); | ||||
|                 str += "\n"; | ||||
|             } | ||||
|  | ||||
|  | ||||
|             str += ("\n*******ErrAll: ");     str += (dec.gotBackData.getErrorCount()); str += "\n"; | ||||
|             str += ("**ErrDistance: ");     str += ((int)(dec.gotBackData.getErrorHighSignal() - dec.gotBackData.getErrorLowSignal())); str += "\n"; | ||||
|             str += ("\n*******ErrAll: "); | ||||
|             str += (dec.gotBackData.getErrorCount()); | ||||
|             str += "\n"; | ||||
|             str += ("**ErrDistance: "); | ||||
|             str += ((int)(dec.gotBackData.getErrorHighSignal() - dec.gotBackData.getErrorLowSignal())); | ||||
|             str += "\n"; | ||||
|  | ||||
|             str += "\n"; | ||||
|         } else { | ||||
|             str += ("SELF"); str += "\n"; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             str += ("SELF"); | ||||
|             str += "\n"; | ||||
|             str += "\n"; | ||||
|         } | ||||
|         // obj->resetAvailable(); | ||||
|         Serial.write(str.c_str()); | ||||
|     } | ||||
|  | ||||
|     if (dec.gotAccept.available()) { | ||||
|     if (dec.gotAccept.available()) | ||||
|     { | ||||
|         detectSignal(); | ||||
|         String str; | ||||
|         if (/* dec.gotData.getDataPrt()[1] */1) { | ||||
|             str += ("Accept on pin ");        str += (dec.isrPin); str += "\n"; | ||||
|         if (/* dec.gotData.getDataPrt()[1] */ 1) | ||||
|         { | ||||
|             str += ("Accept on pin "); | ||||
|             str += (dec.getPin()); | ||||
|             str += "\n"; | ||||
|  | ||||
|             uint8_t msg = dec.gotAccept.getMsgRAW(); | ||||
|             str += ("  MSG: "); | ||||
|             for (size_t i = 0; i < 8; i++) { | ||||
|                 if (i == 3) str += " "; | ||||
|             for (size_t i = 0; i < 8; i++) | ||||
|             { | ||||
|                 if (i == 3) | ||||
|                     str += " "; | ||||
|                 str += (msg >> (7 - i)) & 1U; | ||||
|             } | ||||
|  | ||||
|             str += "\n"; | ||||
|  | ||||
|             // str += ("  DATA SIZE: "); str += (dec.gotAccept.getDataSize()); str += "\n"; | ||||
|             str += ("  ADDRESS FROM: "); str += (dec.gotAccept.getAddrFrom()); str += "\n"; | ||||
|             str += ("  ADDRESS FROM: "); | ||||
|             str += (dec.gotAccept.getAddrFrom()); | ||||
|             str += "\n"; | ||||
|             // str += ("  ADDRESS TO: "); str += (dec.gotAccept.getAddrTo()); str += "\n"; | ||||
|             // str += ("  CRC PACK: "); str += (dec.gotAccept.getCrcIN()); str += "\n"; | ||||
|             // str += ("  CRC CALC: "); str += (dec.gotAccept.getCrcCALC()); str += "\n"; | ||||
|             str += "\n"; | ||||
|  | ||||
|             str += ("  Data: "); str += (dec.gotAccept.getCustomByte()); | ||||
|             str += ("  Data: "); | ||||
|             str += (dec.gotAccept.getCustomByte()); | ||||
|  | ||||
|  | ||||
|  | ||||
|             str += ("\n\n*******ErrAll: ");     str += (dec.gotAccept.getErrorCount()); str += "\n"; | ||||
|             str += ("**ErrDistance: ");     str += ((int)(dec.gotAccept.getErrorHighSignal() - dec.gotAccept.getErrorLowSignal())); str += "\n"; | ||||
|             str += ("\n\n*******ErrAll: "); | ||||
|             str += (dec.gotAccept.getErrorCount()); | ||||
|             str += "\n"; | ||||
|             str += ("**ErrDistance: "); | ||||
|             str += ((int)(dec.gotAccept.getErrorHighSignal() - dec.gotAccept.getErrorLowSignal())); | ||||
|             str += "\n"; | ||||
|  | ||||
|             str += "\n"; | ||||
|         } else { | ||||
|             str += ("SELF"); str += "\n"; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             str += ("SELF"); | ||||
|             str += "\n"; | ||||
|             str += "\n"; | ||||
|         } | ||||
|         // obj->resetAvailable(); | ||||
|         Serial.write(str.c_str()); | ||||
|     } | ||||
|  | ||||
|     if (dec.gotRequest.available()) { | ||||
|     if (dec.gotRequest.available()) | ||||
|     { | ||||
|         detectSignal(); | ||||
|         String str; | ||||
|         if (/* dec.gotData.getDataPrt()[1] */1) { | ||||
|             str += ("Request on pin ");        str += (dec.isrPin); str += "\n"; | ||||
|         if (/* dec.gotData.getDataPrt()[1] */ 1) | ||||
|         { | ||||
|             str += ("Request on pin "); | ||||
|             str += (dec.getPin()); | ||||
|             str += "\n"; | ||||
|  | ||||
|             uint8_t msg = dec.gotRequest.getMsgRAW(); | ||||
|             str += ("  MSG: "); | ||||
|             for (size_t i = 0; i < 8; i++) { | ||||
|                 if (i == 3) str += " "; | ||||
|             for (size_t i = 0; i < 8; i++) | ||||
|             { | ||||
|                 if (i == 3) | ||||
|                     str += " "; | ||||
|                 str += (msg >> (7 - i)) & 1U; | ||||
|             } | ||||
|  | ||||
|             str += "\n"; | ||||
|  | ||||
|             // str += ("  DATA SIZE: "); str += (dec.gotRequest.getDataSize()); str += "\n"; | ||||
|             str += ("  ADDRESS FROM: "); str += (dec.gotRequest.getAddrFrom()); str += "\n"; | ||||
|             str += ("  ADDRESS TO: "); str += (dec.gotRequest.getAddrTo()); str += "\n"; | ||||
|             str += ("  ADDRESS FROM: "); | ||||
|             str += (dec.gotRequest.getAddrFrom()); | ||||
|             str += "\n"; | ||||
|             str += ("  ADDRESS TO: "); | ||||
|             str += (dec.gotRequest.getAddrTo()); | ||||
|             str += "\n"; | ||||
|             // str += ("  CRC PACK: "); str += (dec.gotRequest.getCrcIN()); str += "\n"; | ||||
|             // str += ("  CRC CALC: "); str += (dec.gotRequest.getCrcCALC()); str += "\n"; | ||||
|             str += "\n"; | ||||
|  | ||||
|  | ||||
|             str += ("\n*******ErrAll: ");     str += (dec.gotRequest.getErrorCount()); str += "\n"; | ||||
|             str += ("**ErrDistance: ");     str += ((int)(dec.gotRequest.getErrorHighSignal() - dec.gotRequest.getErrorLowSignal())); str += "\n"; | ||||
|             str += ("\n*******ErrAll: "); | ||||
|             str += (dec.gotRequest.getErrorCount()); | ||||
|             str += "\n"; | ||||
|             str += ("**ErrDistance: "); | ||||
|             str += ((int)(dec.gotRequest.getErrorHighSignal() - dec.gotRequest.getErrorLowSignal())); | ||||
|             str += "\n"; | ||||
|  | ||||
|             str += "\n"; | ||||
|         } else { | ||||
|             str += ("SELF"); str += "\n"; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             str += ("SELF"); | ||||
|             str += "\n"; | ||||
|             str += "\n"; | ||||
|         } | ||||
|         // obj->resetAvailable(); | ||||
|         Serial.write(str.c_str()); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     return false; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
							
								
								
									
										105
									
								
								IR_Decoder.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								IR_Decoder.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,105 @@ | ||||
| #include "IR_Decoder.h" | ||||
|  | ||||
| std::list<IR_Decoder *> &IR_Decoder::get_dec_list() // определение функции | ||||
| { | ||||
|     static std::list<IR_Decoder *> dec_list; // статическая локальная переменная | ||||
|     return dec_list;                         // возвращается ссылка на переменную | ||||
| } | ||||
|  | ||||
| // IR_Decoder::IR_Decoder() {}; | ||||
| IR_Decoder::IR_Decoder(const uint8_t pin, uint16_t addr, IR_Encoder *encPair, bool autoHandle) | ||||
|     : IR_DecoderRaw(pin, addr, encPair) | ||||
| { | ||||
|     get_dec_list().push_back(this); | ||||
|     if(autoHandle){ | ||||
|         enable(); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| void IR_Decoder::enable() | ||||
| { | ||||
|     auto &dec_list = get_dec_list(); | ||||
|     if (std::find(dec_list.begin(), dec_list.end(), this) == dec_list.end()) | ||||
|     { | ||||
|         dec_list.push_back(this); | ||||
|     } | ||||
|     pinMode(pin, INPUT_PULLUP); | ||||
|     attachInterrupt(pin, (*this)(), CHANGE); | ||||
| } | ||||
|  | ||||
| void IR_Decoder::disable() | ||||
| { | ||||
|     detachInterrupt(pin); | ||||
|     pinMode(pin, INPUT); | ||||
|     auto &dec_list = get_dec_list(); | ||||
|     auto it = std::find(dec_list.begin(), dec_list.end(), this); | ||||
|     if (it != dec_list.end()) | ||||
|     { | ||||
|         dec_list.erase(it); | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| std::function<void()> IR_Decoder::operator()() | ||||
| { | ||||
|     return std::bind(&IR_Decoder::isr, this); | ||||
| } | ||||
|  | ||||
| IR_Decoder::~IR_Decoder() | ||||
| { | ||||
|     IR_Decoder::get_dec_list().remove(this); | ||||
| } | ||||
|  | ||||
| void IR_Decoder::tick() | ||||
| { | ||||
|     for (const auto &element : IR_Decoder::get_dec_list()) | ||||
|     { | ||||
|         element->_tick(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void IR_Decoder::_tick() | ||||
| { | ||||
|     IR_DecoderRaw::tick(); | ||||
|     if (availableRaw()) | ||||
|     { | ||||
| #ifdef IRDEBUG_INFO | ||||
|         Serial.println("PARSING RAW DATA"); | ||||
| #endif | ||||
|         isWaitingAcceptSend = false; | ||||
|         switch (packInfo.buffer[0] >> 5 & IR_MASK_MSG_TYPE) | ||||
|         { | ||||
|         case IR_MSG_DATA_ACCEPT: | ||||
|         case IR_MSG_DATA_NOACCEPT: | ||||
|             gotData.set(&packInfo, id); | ||||
|             break; | ||||
|         case IR_MSG_BACK: | ||||
|         case IR_MSG_BACK_TO: | ||||
|             gotBackData.set(&packInfo, id); | ||||
|             break; | ||||
|         case IR_MSG_REQUEST: | ||||
|             gotRequest.set(&packInfo, id); | ||||
|             break; | ||||
|         case IR_MSG_ACCEPT: | ||||
|             gotAccept.set(&packInfo, id); | ||||
|             break; | ||||
|  | ||||
|         default: | ||||
|             break; | ||||
|         } | ||||
|         if (gotData.isAvailable && (gotData.getMsgType() == IR_MSG_DATA_ACCEPT)) | ||||
|         { | ||||
|             acceptSendTimer = millis(); | ||||
|             addrAcceptSendTo = gotData.getAddrFrom(); | ||||
|             acceptCustomByte = crc8(gotData.getDataPrt(), 0, gotData.getDataSize(), poly1); | ||||
|             if (addrAcceptSendTo && addrAcceptSendTo < IR_Broadcast) | ||||
|                 isWaitingAcceptSend = true; | ||||
|         } | ||||
|         gotRaw.set(&packInfo, id); | ||||
|     } | ||||
|     if (isWaitingAcceptSend && millis() - acceptSendTimer > acceptDelay) | ||||
|     { | ||||
|         encoder->sendAccept(addrAcceptSendTo, acceptCustomByte); | ||||
|         isWaitingAcceptSend = false; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										65
									
								
								IR_Decoder.h
									
									
									
									
									
								
							
							
						
						
									
										65
									
								
								IR_Decoder.h
									
									
									
									
									
								
							| @ -5,11 +5,16 @@ | ||||
|  | ||||
| class IR_Decoder : public IR_DecoderRaw | ||||
| { | ||||
| private: | ||||
|     // static std::list<IR_Decoder *> dec_list; | ||||
|     static std::list<IR_Decoder*>& get_dec_list(); | ||||
|     void _tick(); | ||||
|  | ||||
|     uint32_t acceptSendTimer; | ||||
|     bool isWaitingAcceptSend; | ||||
|     uint16_t addrAcceptSendTo; | ||||
|  | ||||
|     uint16_t acceptDelay = 75; | ||||
|     uint16_t acceptDelay = IR_ResponseDelay; | ||||
|     uint8_t acceptCustomByte; | ||||
|  | ||||
| public: | ||||
| @ -19,59 +24,23 @@ public: | ||||
|     PacketTypes::Request gotRequest; | ||||
|     PacketTypes::BasePack gotRaw; | ||||
|  | ||||
|     IR_Decoder(const uint8_t isrPin, uint16_t addr, IR_Encoder *encPair = nullptr) : IR_DecoderRaw(isrPin, addr, encPair) {} | ||||
|     // IR_Decoder(); | ||||
|     IR_Decoder(const uint8_t pin, uint16_t addr = 0, IR_Encoder *encPair = nullptr, bool autoHandle = true); | ||||
|  | ||||
|     void tick() | ||||
|     { | ||||
|         IR_DecoderRaw::tick(); | ||||
|         if (availableRaw()) | ||||
|         { | ||||
| #ifdef IRDEBUG_INFO | ||||
|             Serial.println("PARSING RAW DATA"); | ||||
| #endif | ||||
|             isWaitingAcceptSend = false; | ||||
|             switch (packInfo.buffer[0] >> 5 & IR_MASK_MSG_TYPE) | ||||
|             { | ||||
|             case IR_MSG_DATA_ACCEPT: | ||||
|             case IR_MSG_DATA_NOACCEPT: | ||||
|                 gotData.set(&packInfo, id); | ||||
|                 break; | ||||
|             case IR_MSG_BACK: | ||||
|             case IR_MSG_BACK_TO: | ||||
|                 gotBackData.set(&packInfo, id); | ||||
|                 break; | ||||
|             case IR_MSG_REQUEST: | ||||
|                 gotRequest.set(&packInfo, id); | ||||
|                 break; | ||||
|             case IR_MSG_ACCEPT: | ||||
|                 gotAccept.set(&packInfo, id); | ||||
|                 break; | ||||
|     std::function<void()> operator()(); | ||||
|  | ||||
|             default: | ||||
|                 break; | ||||
|             } | ||||
|             if (gotData.isAvailable && (gotData.getMsgType() == IR_MSG_DATA_ACCEPT)) | ||||
|             { | ||||
|                 acceptSendTimer = millis(); | ||||
|                 addrAcceptSendTo = gotData.getAddrFrom(); | ||||
|                 acceptCustomByte = crc8(gotData.getDataPrt(), 0, gotData.getDataSize(), poly1); | ||||
|                 if (addrAcceptSendTo && addrAcceptSendTo < IR_Broadcast) | ||||
|                     isWaitingAcceptSend = true; | ||||
|             } | ||||
|             gotRaw.set(&packInfo, id); | ||||
|         } | ||||
|         if (isWaitingAcceptSend && millis() - acceptSendTimer > 75) | ||||
|         { | ||||
|             encoder->sendAccept(addrAcceptSendTo, acceptCustomByte); | ||||
|             isWaitingAcceptSend = false; | ||||
|         } | ||||
|     } | ||||
|     void enable(); | ||||
|     void disable(); | ||||
|  | ||||
|     void setAcceptDelay(uint16_t acceptDelay) | ||||
|     ~IR_Decoder(); | ||||
|  | ||||
|     static void tick(); | ||||
|  | ||||
|     inline void setAcceptDelay(uint16_t acceptDelay) | ||||
|     { | ||||
|         this->acceptDelay = acceptDelay; | ||||
|     } | ||||
|     uint16_t getAcceptDelay() | ||||
|     inline uint16_t getAcceptDelay() | ||||
|     { | ||||
|         return this->acceptDelay; | ||||
|     } | ||||
|  | ||||
| @ -1,58 +1,84 @@ | ||||
| #include "IR_DecoderRaw.h" | ||||
| #include "IR_Encoder.h" | ||||
|  | ||||
| IR_DecoderRaw::IR_DecoderRaw(const uint8_t isrPin, uint16_t addr, IR_Encoder *encPair = nullptr) : isrPin(isrPin), encoder(encPair) | ||||
| IR_DecoderRaw::IR_DecoderRaw(const uint8_t pin, uint16_t addr, IR_Encoder *encPair) : encoder(encPair) | ||||
| { | ||||
|     setPin(pin); | ||||
|     id = addr; | ||||
|     prevRise = prevFall = prevPrevFall = prevPrevRise = 0; | ||||
|     if (encPair != nullptr) | ||||
|     { | ||||
|         encPair->decPair = this; | ||||
|     } | ||||
|  | ||||
| #ifdef IRDEBUG | ||||
|     pinMode(wrHigh, OUTPUT); | ||||
|     pinMode(wrLow, OUTPUT); | ||||
|     pinMode(writeOp, OUTPUT); | ||||
|     pinMode(errOut, OUTPUT); | ||||
|     pinMode(up, OUTPUT); | ||||
|     pinMode(down, OUTPUT); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| bool IR_DecoderRaw::isSubOverflow() | ||||
| { | ||||
|     noInterrupts(); | ||||
|     volatile bool ret = isSubBufferOverflow; | ||||
|     interrupts(); | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| bool IR_DecoderRaw::availableRaw() | ||||
|     { | ||||
|         if (isAvailable) | ||||
|         { | ||||
|             isAvailable = false; | ||||
|             return true; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             return false; | ||||
|         } | ||||
|     }; | ||||
|  | ||||
| //////////////////////////////////// isr /////////////////////////////////////////// | ||||
| volatile uint32_t time_; | ||||
|  | ||||
| void IR_DecoderRaw::isr() | ||||
| { | ||||
|     if (isPairSending) | ||||
|     // Serial.print("ISR\n"); | ||||
|     if(isPairSending){ | ||||
|         return; | ||||
|  | ||||
|     subBuffer[currentSubBufferIndex].next = nullptr; | ||||
|     subBuffer[currentSubBufferIndex].dir = (PIND >> isrPin) & 1; | ||||
|     subBuffer[currentSubBufferIndex].time = micros(); | ||||
|  | ||||
|     if (firstUnHandledFront == nullptr) | ||||
|     { | ||||
|         firstUnHandledFront = &subBuffer[currentSubBufferIndex]; // Если нет необработанных данных - добавляем их | ||||
|         isSubBufferOverflow = false; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         if (firstUnHandledFront == &subBuffer[currentSubBufferIndex]) | ||||
|         { // Если контроллер не успел обработать новый сигнал, принудительно пропускаем его | ||||
|             firstUnHandledFront = firstUnHandledFront->next; | ||||
|             isSubBufferOverflow = true; | ||||
|  | ||||
| #ifdef IRDEBUG_INFO | ||||
|             // Serial.println(); | ||||
|             Serial.println(" ISR BUFFER OVERFLOW "); | ||||
| // Serial.println(); | ||||
|     noInterrupts(); | ||||
|     // time_ = HAL_GetTick() * 1000 + ((SysTick->LOAD + 1 - SysTick->VAL) * 1000) / SysTick->LOAD + 1; | ||||
|     time_ = micros(); | ||||
|     interrupts(); | ||||
|     if (time_ < oldTime) | ||||
|     { | ||||
|  | ||||
| #ifdef  IRDEBUG | ||||
|         Serial.print("\n"); | ||||
|         Serial.print("count:         "); | ||||
|         Serial.println(wrongCounter++); | ||||
|         Serial.print("time:                 "); | ||||
|         Serial.println(time_); | ||||
|         Serial.print("oldTime:              "); | ||||
|         Serial.println(oldTime); | ||||
|         Serial.print("sub:                        "); | ||||
|         Serial.println(max((uint32_t)time_, oldTime) - min((uint32_t)time_, oldTime)); | ||||
| #endif | ||||
|         time_ += 1000; | ||||
|     } | ||||
|     } | ||||
|     oldTime = time_; | ||||
|  | ||||
|     if (lastFront == nullptr) | ||||
|     { | ||||
|         lastFront = &subBuffer[currentSubBufferIndex]; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         lastFront->next = &subBuffer[currentSubBufferIndex]; | ||||
|         lastFront = &subBuffer[currentSubBufferIndex]; | ||||
|     } | ||||
|     FrontStorage edge; | ||||
|     edge.dir = port->IDR & mask; | ||||
|     edge.time = time_; | ||||
|  | ||||
|     currentSubBufferIndex == (subBufferSize - 1) ? currentSubBufferIndex = 0 : currentSubBufferIndex++; // Закольцовка буффера | ||||
|     subBuffer.push(edge); | ||||
| } | ||||
|  | ||||
| //////////////////////////////////////////////////////////////////////////////////// | ||||
| @ -78,7 +104,9 @@ void IR_DecoderRaw::firstRX() | ||||
|  | ||||
|     isPreamb = true; | ||||
|     riseSyncTime = bitTime /* 1100 */; | ||||
|  | ||||
| #ifdef IRDEBUG | ||||
|     wrCounter = 0; | ||||
| #endif | ||||
|     memset(dataBuffer, 0x00, dataByteSizeMax); | ||||
| } | ||||
|  | ||||
| @ -95,53 +123,113 @@ void IR_DecoderRaw::listenStart() | ||||
| void IR_DecoderRaw::tick() | ||||
| { | ||||
|     FrontStorage currentFront; | ||||
|     uint8_t oldSREG = SREG; | ||||
|     cli(); | ||||
|     noInterrupts(); | ||||
|     listenStart(); | ||||
|     if (firstUnHandledFront == nullptr) | ||||
|     FrontStorage *currentFrontPtr; | ||||
|     currentFrontPtr = subBuffer.pop(); | ||||
|     if (currentFrontPtr == nullptr) | ||||
|     { | ||||
|         isSubBufferOverflow = false; | ||||
|         SREG = oldSREG; | ||||
|         interrupts(); | ||||
|         return; | ||||
|     } // Если данных нет - ничего не делаем | ||||
|     currentFront = *((FrontStorage *)firstUnHandledFront); // найти следующий необработанный фронт/спад | ||||
|     SREG = oldSREG; | ||||
|     if (currentFront.next == nullptr) | ||||
|     { | ||||
|         isRecive = false; | ||||
|         return; | ||||
|     } | ||||
|     currentFront = *currentFrontPtr; | ||||
|     interrupts(); | ||||
|  | ||||
|     //////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
|     if (currentFront.dir) | ||||
|     { // Если __/``` ↑ | ||||
|         if (currentFront.time - prevRise > riseTimeMax / 4 || highCount || lowCount) | ||||
|         { // комплексный фикс рваной единицы | ||||
|             risePeriod = currentFront.time - prevRise; | ||||
|             highTime = currentFront.time - prevFall; | ||||
|             lowTime = prevFall - prevRise; | ||||
|             prevRise = currentFront.time; | ||||
|  | ||||
|             if ( | ||||
|                 risePeriod > UINT32_MAX - IR_timeout * 10 || | ||||
|                 highTime > UINT32_MAX - IR_timeout * 10 || | ||||
|                 lowTime > UINT32_MAX - IR_timeout * 10 || | ||||
|                 prevRise > UINT32_MAX - IR_timeout * 10) | ||||
|             { | ||||
| #ifdef IRDEBUG | ||||
|                 errPulse(down, 50); | ||||
|  | ||||
|                 // Serial.print("\n"); | ||||
|  | ||||
|                 // Serial.print("risePeriod:    "); | ||||
|                 // Serial.println(risePeriod); | ||||
|  | ||||
|                 // Serial.print("highTime:           "); | ||||
|                 // Serial.println(highTime); | ||||
|  | ||||
|                 // Serial.print("lowTime:            "); | ||||
|                 // Serial.println(lowTime); | ||||
|  | ||||
|                 // Serial.print("prevRise:                  "); | ||||
|                 // Serial.println(prevRise); | ||||
| #endif | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             errors.other++; | ||||
|         } | ||||
|     } | ||||
|     else | ||||
|     { // Если ```\__ ↓ | ||||
|  | ||||
|         if (currentFront.time - prevFall > riseTimeMin / 4) | ||||
|         { | ||||
|             prevFall = currentFront.time; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             errors.other++; | ||||
|         } | ||||
|     } | ||||
| #ifdef IRDEBUG | ||||
|     // goto END; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| #endif | ||||
|     //---------------------------------------------------------------------------------- | ||||
| #ifdef IRDEBUG | ||||
|     digitalWrite(errOut, currentFront.dir); | ||||
| #endif | ||||
|  | ||||
|     if (currentFront.time > prevRise && currentFront.time - prevRise > IR_timeout * 2 && !isRecive) | ||||
|     { // первый | ||||
|         preambFrontCounter = preambFronts - 1U; | ||||
|  | ||||
|         if (!currentFront.dir) | ||||
|         { | ||||
| #ifdef IRDEBUG_INFO | ||||
| // Serial.print(" currentFront.time: "); Serial.print(currentFront.time); | ||||
| // Serial.print(" currentFront.dir: "); Serial.print(currentFront.dir ? "UP" : "DOWN"); | ||||
| // Serial.print(" next: "); Serial.print(currentFront.next == nullptr); | ||||
| // Serial.print("   prevRise: "); Serial.print(prevRise); | ||||
| // Serial.print("   SUB: "); Serial.println(currentFront.time - prevRise); | ||||
| #ifdef IRDEBUG | ||||
|         errPulse(up, 50); | ||||
|         errPulse(down, 50); | ||||
|         errPulse(up, 150); | ||||
|         errPulse(down, 150); | ||||
| #endif | ||||
|         preambFrontCounter = preambFronts - 1U; | ||||
|         isPreamb = true; | ||||
|  | ||||
|         isRecive = true; | ||||
|         isWrongPack = false; | ||||
|     } | ||||
|     } | ||||
|  | ||||
|     //------------------------------------------------------------------------------------------------------- | ||||
|  | ||||
|     if (preambFrontCounter) | ||||
|     { // в преамбуле | ||||
|         uint32_t risePeriod; | ||||
|         risePeriod = currentFront.time - prevRise; | ||||
| #ifdef IRDEBUG | ||||
|         Serial.print("risePeriod:           "); | ||||
|         Serial.println(risePeriod); | ||||
| #endif | ||||
|         if (currentFront.dir && risePeriod < IR_timeout) | ||||
|         { //  __/``` ↑ и мы в внутри пакета | ||||
|  | ||||
|             if (risePeriod < riseTimeMin << 1) | ||||
|             if (risePeriod < riseTimeMin / 2) | ||||
|             { // fix рваной единицы | ||||
|                 preambFrontCounter += 2; | ||||
|                 errors.other++; | ||||
| #ifdef IRDEBUG | ||||
|                 errPulse(down, 350); | ||||
| #endif | ||||
|             } | ||||
|             else | ||||
|             { | ||||
| @ -162,42 +250,64 @@ void IR_DecoderRaw::tick() | ||||
|         if (isPreamb) | ||||
|         { // первый фронт после | ||||
|           // gotTune.set(riseSyncTime); | ||||
|         } | ||||
|             isPreamb = false; | ||||
| #ifdef IRDEBUG | ||||
|             errPulse(up, 50); | ||||
|             errPulse(down, 50); | ||||
| #endif | ||||
|             prevRise += risePeriod / 2; | ||||
|             // prevRise = currentFront.time + riseTime; | ||||
|             goto END; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (isPreamb) | ||||
|     { | ||||
|         goto END; | ||||
|     } | ||||
|     if (risePeriod > IR_timeout || isBufferOverflow || risePeriod < riseTimeMin || isWrongPack) | ||||
|     // ~Мы в пределах таймаута и буффер не переполнен и fix дроблёных единиц | ||||
|     { | ||||
|         goto END; | ||||
|     } | ||||
|  | ||||
|     // определить направление фронта | ||||
|     if (currentFront.dir) | ||||
|     { // Если __/``` ↑ | ||||
|  | ||||
|         uint16_t risePeriod = currentFront.time - prevRise; | ||||
|         uint16_t highTime = currentFront.time - prevFall; | ||||
|         uint16_t lowTime = prevFall - prevRise; | ||||
|  | ||||
|         int8_t highCount = 0; | ||||
|         int8_t lowCount = 0; | ||||
|         int8_t allCount = 0; | ||||
|         highCount = 0; | ||||
|         lowCount = 0; | ||||
|         allCount = 0; | ||||
|         bool invertErr = false; | ||||
| #ifdef IRDEBUG | ||||
|         Serial.print("\n"); | ||||
|  | ||||
|         if (!isPreamb) | ||||
|         { | ||||
|             if (risePeriod < IR_timeout && !isBufferOverflow && risePeriod > riseTimeMin && !isWrongPack) | ||||
|             { | ||||
|                 // Мы в пределах таймаута и буффер не переполнен и fix дроблёных единиц | ||||
|         Serial.print("wrCounter:    "); | ||||
|         Serial.println(wrCounter++); | ||||
|  | ||||
|         Serial.print("risePeriod:           "); | ||||
|         Serial.println(risePeriod); | ||||
|  | ||||
|         Serial.print("highTime:        "); | ||||
|         Serial.println(highTime); | ||||
|  | ||||
|         Serial.print("lowTime:         "); | ||||
|         Serial.println(lowTime); | ||||
| #endif | ||||
|  | ||||
|         if (aroundRise(risePeriod)) | ||||
|         { // тактирование есть, сигнал хороший - без ошибок(?) | ||||
|  | ||||
|                     if (highTime > riseTimeMin >> 1) | ||||
|             if (highTime > lowTime) | ||||
|             { // 1 | ||||
| #ifdef IRDEBUG | ||||
|                         digitalWrite(wrHigh, 1); | ||||
|                 errPulse(wrHigh, 1); | ||||
| #endif | ||||
|                 writeToBuffer(HIGH); | ||||
|             } | ||||
|             else | ||||
|             { // 0 | ||||
| #ifdef IRDEBUG | ||||
|                         digitalWrite(wrLow, 1); | ||||
|                 errPulse(wrLow, 1); | ||||
| #endif | ||||
|                 writeToBuffer(LOW); | ||||
|             } | ||||
| @ -213,7 +323,7 @@ void IR_DecoderRaw::tick() | ||||
|                 highCount++; | ||||
|                 errors.other++; | ||||
| #ifdef IRDEBUG | ||||
|                         errPulse(errOut, 2); | ||||
|                 errPulse(up, 50); | ||||
| #endif | ||||
|             } | ||||
|  | ||||
| @ -224,7 +334,10 @@ void IR_DecoderRaw::tick() | ||||
|                     lowCount = allCount - highCount; | ||||
|                     errors.lowSignal += lowCount; | ||||
| #ifdef IRDEBUG | ||||
|                             errPulse(errOut, 3); | ||||
|                     // errPulse(errOut, 3); | ||||
|                     errPulse(down, 40); | ||||
|                     errPulse(up, 10); | ||||
|                     errPulse(down, 40); | ||||
| #endif | ||||
|                 } | ||||
|                 else if (lowCount < highCount) | ||||
| @ -232,7 +345,10 @@ void IR_DecoderRaw::tick() | ||||
|                     highCount = allCount - lowCount; | ||||
|                     errors.highSignal += highCount; | ||||
| #ifdef IRDEBUG | ||||
|                             errPulse(errOut, 4); | ||||
|                     errPulse(down, 10); | ||||
|                     errPulse(up, 40); | ||||
|                     errPulse(down, 10); | ||||
| // errPulse(errOut, 4); | ||||
| #endif | ||||
|                     // неизвестный случай Инверсит след бит или соседние | ||||
|                     // Очень редко | ||||
| @ -240,6 +356,11 @@ void IR_DecoderRaw::tick() | ||||
|                 } | ||||
|                 else if (lowCount == highCount) | ||||
|                 { | ||||
| #ifdef IRDEBUG | ||||
|                     errPulse(down, 40); | ||||
|                     errPulse(up, 40); | ||||
|                     errPulse(down, 40); | ||||
| #endif | ||||
|                     invertErr = true; | ||||
|                     // Serial.print("..."); | ||||
|                     errors.other += allCount; | ||||
| @ -258,25 +379,23 @@ void IR_DecoderRaw::tick() | ||||
|                 errors.lowSignal += lowCount; | ||||
|             } | ||||
|  | ||||
| #ifdef IRDEBUG | ||||
|                     errPulse(errOut, 1); | ||||
| #endif | ||||
|             // errPulse(errOut, 1); | ||||
|  | ||||
|             for (int8_t i = 0; i < lowCount && 8 - i; i++) | ||||
|             { // отправка LOW битов, если есть | ||||
|                 if (i == lowCount - 1 && invertErr) | ||||
|                 { | ||||
|                     invertErr = false; | ||||
|                             writeToBuffer(!LOW); | ||||
|                     writeToBuffer(HIGH); | ||||
| #ifdef IRDEBUG | ||||
|                             digitalWrite(wrLow, 1); | ||||
|                     errPulse(wrHigh, 1); | ||||
| #endif | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     writeToBuffer(LOW); | ||||
| #ifdef IRDEBUG | ||||
|                             digitalWrite(wrLow, 1); | ||||
|                     errPulse(wrLow, 1); | ||||
| #endif | ||||
|                 } | ||||
|             } | ||||
| @ -286,71 +405,27 @@ void IR_DecoderRaw::tick() | ||||
|                 if (i == highCount - 1 && invertErr) | ||||
|                 { | ||||
|                     invertErr = false; | ||||
|                             writeToBuffer(!HIGH); | ||||
|                     writeToBuffer(LOW); | ||||
| #ifdef IRDEBUG | ||||
|                             digitalWrite(wrLow, 1); | ||||
|                     errPulse(wrLow, 1); | ||||
| #endif | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     writeToBuffer(HIGH); | ||||
| #ifdef IRDEBUG | ||||
|                             digitalWrite(wrHigh, 1); | ||||
|                     errPulse(wrHigh, 1); | ||||
| #endif | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| #ifdef IRDEBUG | ||||
|                 digitalWrite(wrHigh, 0); | ||||
|                 digitalWrite(wrLow, 0); | ||||
| #endif | ||||
|             } | ||||
|         } | ||||
|         if (risePeriod > riseTimeMax / 2 || highCount || lowCount) | ||||
|         { // комплексный фикс рваной единицы | ||||
|             prevPrevRise = prevRise; | ||||
|             prevRise = currentFront.time; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             errors.other++; | ||||
| #ifdef IRDEBUG | ||||
|             errPulse(errOut, 5); | ||||
| #endif | ||||
|         } | ||||
|     } | ||||
|     else | ||||
|     { // Если ```\__ ↓ | ||||
|  | ||||
|         if (currentFront.time - prevFall > riseTimeMin) | ||||
|         { | ||||
|             prevPrevFall = prevFall; | ||||
|             prevFall = currentFront.time; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
| #ifdef IRDEBUG | ||||
| // errPulse(errOut, 5); | ||||
| #endif | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (isPreamb && preambFrontCounter <= 0) | ||||
|     { | ||||
|         prevRise = currentFront.time + riseTime; | ||||
|     } | ||||
|  | ||||
| #ifdef IRDEBUG | ||||
|     digitalWrite(writeOp, isPreamb); | ||||
| #endif | ||||
|     //////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|     oldSREG = SREG; | ||||
|     cli(); | ||||
|     if (firstUnHandledFront != nullptr) | ||||
|     { | ||||
|         firstUnHandledFront = firstUnHandledFront->next; // переместить флаг на следующий элемент для обработки (next or nullptr) | ||||
|     } | ||||
|     SREG = oldSREG; | ||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| END:; | ||||
| } | ||||
|  | ||||
| void IR_DecoderRaw::writeToBuffer(bool bit) | ||||
| @ -479,7 +554,7 @@ void IR_DecoderRaw::writeToBuffer(bool bit) | ||||
|         if (packSize && (i_dataBuffer == packSize * bitPerByte)) | ||||
|         { // Конец | ||||
| #ifdef IRDEBUG_INFO | ||||
|             Serial.print("   END DATA   "); | ||||
|             Serial.print("   END DATA   " + crcCheck(packSize - crcBytes, crcValue) ? "OK   " : "ERR  "); | ||||
| #endif | ||||
|  | ||||
|             packInfo.buffer = dataBuffer; | ||||
| @ -490,6 +565,34 @@ void IR_DecoderRaw::writeToBuffer(bool bit) | ||||
|  | ||||
|             isRecive = false; | ||||
|             isAvailable = crcCheck(packSize - crcBytes, crcValue); | ||||
|  | ||||
| #ifdef BRUTEFORCE_CHECK | ||||
|             if (!isAvailable) // Исправление первого бита // Очень большая затычка... | ||||
|                 for (size_t i = 0; i < min(uint16_t(packSize - crcBytes * 2U), uint16_t(dataByteSizeMax)); ++i) | ||||
|                 { | ||||
|                     for (int j = 0; j < 8; ++j) | ||||
|                     { | ||||
|                         // инвертируем бит | ||||
|                         dataBuffer[i] ^= 1 << j; | ||||
|  | ||||
|                         isAvailable = crcCheck(min(uint16_t(packSize - crcBytes), uint16_t(dataByteSizeMax - 1U)), crcValue); | ||||
|                         // обратно инвертируем бит в исходное состояние | ||||
|  | ||||
|                         if (isAvailable) | ||||
|                         { | ||||
| #ifdef IRDEBUG_INFO | ||||
|                             Serial.println("!!!INV!!!"); | ||||
| #endif | ||||
|                             goto OUT_BRUTEFORCE; | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|                             dataBuffer[i] ^= 1 << j; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|         OUT_BRUTEFORCE:; | ||||
| #endif | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
| @ -1,15 +1,18 @@ | ||||
| #pragma once | ||||
| #include "IR_config.h" | ||||
| #include "RingBuffer.h" | ||||
|  | ||||
| // #define IRDEBUG | ||||
|  | ||||
| #ifdef IRDEBUG | ||||
| #define wrHigh A3  // Запись HIGH инициирована                     // green | ||||
| #define wrLow A3   // Запись LOW инициирована                      // blue | ||||
| #define writeOp 13 // Операция записи, 1 пульс для 0 и 2 для 1     // orange | ||||
| #define wrHigh PA1  // Запись HIGH инициирована                     // green | ||||
| #define wrLow PA0   // Запись LOW инициирована                      // blue | ||||
| #define writeOp PA5 // Операция записи, 1 пульс для 0 и 2 для 1     // orange | ||||
| // Исправленные ошибки                                              // purle | ||||
| // 1 пульс: fix | ||||
| #define errOut A3 | ||||
| #define errOut PA4 | ||||
| #define up PA3 | ||||
| #define down PA2 | ||||
| #endif | ||||
|  | ||||
| ///////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| @ -20,6 +23,7 @@ | ||||
| #define riseTimeMin (riseTime - riseTolerance) | ||||
| #define aroundRise(t) (riseTimeMin < t && t < riseTimeMax) | ||||
| #define IR_timeout (riseTimeMax * (8 + syncBits + 1)) // us // таймаут в 8 data + 3 sync + 1 | ||||
| constexpr uint16_t IR_ResponseDelay = ((uint16_t)(((bitTime+riseTolerance) * (8 + syncBits + 1))*2.7735))/1000; | ||||
|  | ||||
| class IR_Encoder; | ||||
| class IR_DecoderRaw : virtual public IR_FOX | ||||
| @ -29,42 +33,22 @@ class IR_DecoderRaw : virtual public IR_FOX | ||||
| protected: | ||||
|     PackInfo packInfo; | ||||
|     IR_Encoder *encoder; // Указатель на парный передатчик | ||||
|     bool availableRaw() | ||||
|     { | ||||
|         if (isAvailable) | ||||
|         { | ||||
|             isAvailable = false; | ||||
|             return true; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             return false; | ||||
|         } | ||||
|     }; | ||||
|     bool availableRaw(); | ||||
|  | ||||
| public: | ||||
|     const uint8_t isrPin; // Пин прерывания | ||||
|  | ||||
|     ////////////////////////////////////////////////////////////////////////// | ||||
|     /// @brief Конструктор | ||||
|     /// @param isrPin Номер вывода прерывания/данных от приёмника (2 или 3 для atmega 328p) | ||||
|     /// @param pin Номер вывода прерывания/данных от приёмника (2 или 3 для atmega 328p) | ||||
|     /// @param addr Адрес приёмника | ||||
|     /// @param encPair Указатель на передатчик, работающий в паре | ||||
|     IR_DecoderRaw(const uint8_t isrPin, uint16_t addr, IR_Encoder *encPair = nullptr); | ||||
|     IR_DecoderRaw(const uint8_t pin, uint16_t addr, IR_Encoder *encPair = nullptr); | ||||
|  | ||||
|     void isr();  // Функция прерывания | ||||
|     void tick(); // Обработка приёмника, необходима для работы | ||||
|  | ||||
|     bool isOverflow() { return isBufferOverflow; }; // Буффер переполнился | ||||
|     bool isSubOverflow() | ||||
|     { | ||||
|         uint8_t oldSREG = SREG; | ||||
|         cli(); | ||||
|         volatile bool ret = isSubBufferOverflow; | ||||
|         SREG = oldSREG; | ||||
|         return ret; | ||||
|     }; | ||||
|     bool isReciving() { return isBufferOverflow; }; // Возвращает true, если происходит приём пакета | ||||
|     inline bool isOverflow() { return isBufferOverflow; }; // Буффер переполнился | ||||
|     bool isSubOverflow(); | ||||
|     inline bool isReciving() { return isBufferOverflow; }; // Возвращает true, если происходит приём пакета | ||||
|  | ||||
|     ////////////////////////////////////////////////////////////////////////// | ||||
| private: | ||||
| @ -82,20 +66,35 @@ private: | ||||
|     uint16_t riseSyncTime = bitTime; // Подстраиваемое время бита в мкс | ||||
|  | ||||
|     //////////////////////////////////////////////////////////////////////// | ||||
|     volatile uint8_t currentSubBufferIndex; // Счетчик текущей позиции во вспомогательном буфере фронтов/спадов | ||||
|     volatile uint32_t currentSubBufferIndex; // Счетчик текущей позиции во вспомогательном буфере фронтов/спадов | ||||
|  | ||||
|     struct FrontStorage | ||||
|     {                               // Структура для хранения времени и направления фронта/спада | ||||
|         volatile uint32_t time = 0; // Время | ||||
|         volatile bool dir = false;  // Направление (true = ↑; false = ↓) | ||||
|         volatile FrontStorage *next = nullptr; // Указатель на следующий связанный фронт/спад, или nullptr если конец | ||||
|         // volatile FrontStorage *next = nullptr; // Указатель на следующий связанный фронт/спад, или nullptr если конец | ||||
|     }; | ||||
|     volatile FrontStorage *lastFront = nullptr;           // Указатель последнего фронта/спада | ||||
|     volatile FrontStorage *firstUnHandledFront = nullptr; // Указатель первого необработанного фронта/спада | ||||
|     volatile FrontStorage subBuffer[subBufferSize];       // вспомогательный буфер для хранения необработанных фронтов/спадов | ||||
|     // volatile FrontStorage subBuffer[subBufferSize];       // вспомогательный буфер для хранения необработанных фронтов/спадов | ||||
|  | ||||
|     RingBuffer<FrontStorage, subBufferSize> subBuffer; | ||||
|  | ||||
|     //////////////////////////////////////////////////////////////////////// | ||||
|     uint8_t dataBuffer[dataByteSizeMax]{0};                           // Буффер данных | ||||
|     uint32_t prevRise, prevPrevRise, prevFall, prevPrevFall; // Время предыдущих фронтов/спадов | ||||
|     volatile uint32_t prevRise, prevPrevRise, prevFall, prevPrevFall; // Время предыдущих фронтов/спадов | ||||
|  | ||||
|     volatile uint32_t risePeriod; | ||||
|     volatile uint32_t highTime; | ||||
|     volatile uint32_t lowTime; | ||||
|  | ||||
|     uint32_t oldTime; | ||||
|     uint16_t wrongCounter; | ||||
|  | ||||
|     int8_t highCount; | ||||
|     int8_t lowCount; | ||||
|     int8_t allCount; | ||||
|  | ||||
|     uint16_t errorCounter = 0;     // Счётчик ошибок | ||||
|     int8_t preambFrontCounter = 0; // Счётчик __/``` ↑ преамбулы | ||||
|     int16_t bufBitPos = 0;         // Позиция для записи бита в буффер | ||||
| @ -130,6 +129,7 @@ private: | ||||
|     uint16_t ceil_div(uint16_t val, uint16_t divider); | ||||
|  | ||||
| #ifdef IRDEBUG | ||||
|     uint32_t wrCounter; | ||||
|     inline void errPulse(uint8_t pin, uint8_t count); | ||||
|     inline void infoPulse(uint8_t pin, uint8_t count); | ||||
| #endif | ||||
|  | ||||
							
								
								
									
										217
									
								
								IR_Encoder.cpp
									
									
									
									
									
								
							
							
						
						
									
										217
									
								
								IR_Encoder.cpp
									
									
									
									
									
								
							| @ -5,8 +5,12 @@ | ||||
| #define ISR_Out 10 | ||||
| #define TestOut 13 | ||||
|  | ||||
| IR_Encoder::IR_Encoder(uint16_t addr, IR_DecoderRaw *decPair = nullptr) | ||||
| IR_Encoder *IR_Encoder::head = nullptr; | ||||
| IR_Encoder *IR_Encoder::last = nullptr; | ||||
|  | ||||
| IR_Encoder::IR_Encoder(uint8_t pin, uint16_t addr, IR_DecoderRaw *decPair, bool autoHandle) | ||||
| { | ||||
|     setPin(pin); | ||||
|     id = addr; | ||||
|     this->decPair = decPair; | ||||
|     signal = noSignal; | ||||
| @ -14,8 +18,7 @@ IR_Encoder::IR_Encoder(uint16_t addr, IR_DecoderRaw *decPair = nullptr) | ||||
| #if disablePairDec | ||||
|     if (decPair != nullptr) | ||||
|     { | ||||
|         blindDecoders = new IR_DecoderRaw *[1] | ||||
|         { decPair }; | ||||
|         blindDecoders = new IR_DecoderRaw *[1]{decPair}; | ||||
|         decodersCount = 1; | ||||
|     } | ||||
| #endif | ||||
| @ -23,7 +26,94 @@ IR_Encoder::IR_Encoder(uint16_t addr, IR_DecoderRaw *decPair = nullptr) | ||||
|     { | ||||
|         decPair->encoder = this; | ||||
|     } | ||||
|  | ||||
|     if (autoHandle) | ||||
|     { | ||||
|         if (IR_Encoder::head == nullptr) | ||||
|         { | ||||
|         IR_Encoder::head = this; | ||||
|         } | ||||
|         if (last != nullptr) | ||||
|         { | ||||
|         last->next = this; | ||||
|         } | ||||
|         last = this; | ||||
|     } | ||||
| }; | ||||
|   | ||||
| HardwareTimer* IR_Encoder::IR_Timer = nullptr; | ||||
|  | ||||
| inline HardwareTimer* IR_Encoder::get_IR_Timer(){return IR_Encoder::IR_Timer;} | ||||
|  | ||||
| void IR_Encoder::begin(HardwareTimer* timer, uint8_t channel, IRQn_Type IRQn, uint8_t priority, void(*isrCallback)()){ | ||||
|     IR_Timer = timer; | ||||
|     if(IR_Timer == nullptr) return; | ||||
|     IR_Timer->setOverflow(carrierFrec * 2, HERTZ_FORMAT); | ||||
|     IR_Timer->attachInterrupt(channel, (isrCallback == nullptr ? IR_Encoder::isr : isrCallback)); | ||||
|     NVIC_SetPriority(IRQn, priority); | ||||
|     IR_Timer->resume(); | ||||
| } | ||||
|  | ||||
|  | ||||
| void IR_Encoder::enable() | ||||
| { | ||||
|     bool exist = false; | ||||
|     IR_Encoder *current = IR_Encoder::head; | ||||
|     while (current != nullptr) | ||||
|     { | ||||
|         exist = (current == this); | ||||
|         if (exist) break; | ||||
|         current = current->next; | ||||
|     } | ||||
|     if (!exist) | ||||
|     { | ||||
|         if (IR_Encoder::head == nullptr) | ||||
|         { | ||||
|             IR_Encoder::head = this; | ||||
|             last = this; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             last->next = this; | ||||
|             last = this; | ||||
|         } | ||||
|         this->next = nullptr; // Указываем, что следующий за этим элементом — nullptr | ||||
|     } | ||||
|     pinMode(pin, OUTPUT); | ||||
| } | ||||
|  | ||||
| void IR_Encoder::disable() | ||||
| { | ||||
|     IR_Encoder *current = IR_Encoder::head; | ||||
|     IR_Encoder *prev = nullptr; | ||||
|  | ||||
|     while (current != nullptr) | ||||
|     { | ||||
|         if (current == this) break; | ||||
|         prev = current; | ||||
|         current = current->next; | ||||
|     } | ||||
|  | ||||
|     if (current != nullptr) // Элемент найден в списке | ||||
|     { | ||||
|         if (prev != nullptr) | ||||
|         { | ||||
|             prev->next = current->next; // Убираем текущий элемент из списка | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             IR_Encoder::head = current->next; // Удаляемый элемент был первым | ||||
|         } | ||||
|  | ||||
|         if (current == last) | ||||
|         { | ||||
|             last = prev; // Если удаляется последний элемент, обновляем last | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pinMode(pin, INPUT); | ||||
| } | ||||
|  | ||||
| void IR_Encoder::setBlindDecoders(IR_DecoderRaw *decoders[], uint8_t count) | ||||
| { | ||||
| #if disablePairDec | ||||
| @ -34,21 +124,18 @@ void IR_Encoder::setBlindDecoders(IR_DecoderRaw *decoders[], uint8_t count) | ||||
|     blindDecoders = decoders; | ||||
| } | ||||
|  | ||||
| IR_Encoder::~IR_Encoder() | ||||
| { | ||||
|     delete[] bitLow; | ||||
|     delete[] bitHigh; | ||||
| }; | ||||
| IR_Encoder::~IR_Encoder(){}; | ||||
|  | ||||
| void IR_Encoder::sendData(uint16_t addrTo, uint8_t dataByte, bool needAccept = false) | ||||
| void IR_Encoder::sendData(uint16_t addrTo, uint8_t dataByte, bool needAccept) | ||||
| { | ||||
|     uint8_t *dataPtr = new uint8_t[1]; | ||||
|     dataPtr[0] = dataByte; | ||||
|     sendData(addrTo, dataPtr, 1, needAccept); | ||||
|     delete[] dataPtr; | ||||
|     sendData(addrTo, &dataByte, 1, needAccept); | ||||
| } | ||||
|  | ||||
| void IR_Encoder::sendData(uint16_t addrTo, uint8_t *data = nullptr, uint8_t len = 0, bool needAccept = false) | ||||
| void IR_Encoder::sendData(uint16_t addrTo, uint8_t *data, uint8_t len, bool needAccept){ | ||||
|     sendDataFULL(id, addrTo, data, len, needAccept); | ||||
| } | ||||
|  | ||||
| void IR_Encoder::sendDataFULL(uint16_t addrFrom, uint16_t addrTo, uint8_t *data, uint8_t len, bool needAccept) | ||||
| { | ||||
|     if (len > bytePerPack) | ||||
|     { | ||||
| @ -65,8 +152,8 @@ void IR_Encoder::sendData(uint16_t addrTo, uint8_t *data = nullptr, uint8_t len | ||||
|     sendBuffer[0] = msgType; | ||||
|  | ||||
|     // addr_self | ||||
|     sendBuffer[1] = id >> 8 & 0xFF; | ||||
|     sendBuffer[2] = id & 0xFF; | ||||
|     sendBuffer[1] = addrFrom >> 8 & 0xFF; | ||||
|     sendBuffer[2] = addrFrom & 0xFF; | ||||
|  | ||||
|     // addr_to | ||||
|     sendBuffer[3] = addrTo >> 8 & 0xFF; | ||||
| @ -92,7 +179,7 @@ void IR_Encoder::sendData(uint16_t addrTo, uint8_t *data = nullptr, uint8_t len | ||||
|     rawSend(sendBuffer, packSize); | ||||
| } | ||||
|  | ||||
| void IR_Encoder::sendAccept(uint16_t addrTo, uint8_t customByte = 0) | ||||
| void IR_Encoder::sendAccept(uint16_t addrTo, uint8_t customByte) | ||||
| { | ||||
|     constexpr uint8_t packsize = msgBytes + addrBytes + 1U + crcBytes; | ||||
|     memset(sendBuffer, 0x00, dataByteSizeMax); | ||||
| @ -141,12 +228,13 @@ void IR_Encoder::sendBack(uint8_t data) | ||||
| { | ||||
|     _sendBack(false, 0, &data, 1); | ||||
| } | ||||
| void IR_Encoder::sendBack(uint8_t *data = nullptr, uint8_t len = 0) | ||||
|  | ||||
| void IR_Encoder::sendBack(uint8_t *data, uint8_t len) | ||||
| { | ||||
|     _sendBack(false, 0, data, len); | ||||
| } | ||||
|  | ||||
| void IR_Encoder::sendBackTo(uint16_t addrTo, uint8_t *data = nullptr, uint8_t len = 0) | ||||
| void IR_Encoder::sendBackTo(uint16_t addrTo, uint8_t *data, uint8_t len) | ||||
| { | ||||
|     _sendBack(true, addrTo, data, len); | ||||
| } | ||||
| @ -160,7 +248,7 @@ void IR_Encoder::_sendBack(bool isAdressed, uint16_t addrTo, uint8_t *data, uint | ||||
|     memset(sendBuffer, 0x00, dataByteSizeMax); | ||||
|     uint8_t dataStart = msgBytes + addrBytes + (isAdressed ? addrBytes : 0); | ||||
|  | ||||
|     uint8_t packSize = msgBytes + addrBytes + (isAdressed ? addrBytes : 0) + min(1, len) + crcBytes; | ||||
|     uint8_t packSize = msgBytes + addrBytes + (isAdressed ? addrBytes : 0) + min(uint8_t(1), len) + crcBytes; | ||||
|     uint8_t msgType = | ||||
|         ((isAdressed ? IR_MSG_BACK_TO : IR_MSG_BACK) << 5) | ((packSize) & (IR_MASK_MSG_INFO >> 1)); | ||||
|  | ||||
| @ -196,6 +284,10 @@ void IR_Encoder::setDecoder_isSending() | ||||
|         for (uint8_t i = 0; i < decodersCount; i++) | ||||
|         { | ||||
|             blindDecoders[i]->isPairSending ^= id; | ||||
|             // Serial.print("setDecoder_isSending()   id = "); | ||||
|             // Serial.print(id); | ||||
|             // Serial.print("   isPairSending = "); | ||||
|             // Serial.println(blindDecoders[i]->isPairSending); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -207,10 +299,10 @@ void IR_Encoder::rawSend(uint8_t *ptr, uint8_t len) | ||||
|         // TODO: Обработка повторной отправки | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     // Serial.println("START"); | ||||
|     setDecoder_isSending(); | ||||
|  | ||||
|     cli(); | ||||
|     // noInterrupts(); | ||||
|     sendLen = len; | ||||
|     toggleCounter = preambToggle; // Первая генерация для первого signal | ||||
|  | ||||
| @ -227,16 +319,29 @@ void IR_Encoder::rawSend(uint8_t *ptr, uint8_t len) | ||||
|  | ||||
|     currentBitSequence = bitHigh; | ||||
|     isSending = true; | ||||
|     sei(); | ||||
|     // interrupts(); | ||||
| } | ||||
|  | ||||
| void IR_Encoder::isr() | ||||
| { | ||||
|     IR_Encoder *current = IR_Encoder::head; | ||||
|     while (current != nullptr) | ||||
|     { | ||||
|       current->_isr(); | ||||
|       current = current->next; | ||||
|     } | ||||
| } | ||||
|  | ||||
| void IR_Encoder::_isr() | ||||
| { | ||||
|     if (!isSending) | ||||
|         return; | ||||
|  | ||||
|     ir_out_virtual = !ir_out_virtual && state; | ||||
|  | ||||
|     port->ODR &= ~(mask); | ||||
|     port->ODR |= mask & (ir_out_virtual ? (uint16_t)0xFFFF : (uint16_t)0x0000); | ||||
|  | ||||
|     if (toggleCounter) | ||||
|     { | ||||
|         toggleCounter--; | ||||
| @ -251,7 +356,9 @@ void IR_Encoder::isr() | ||||
|             // сброс счетчиков | ||||
|             // ... | ||||
|             isSending = false; | ||||
|             // Serial.println("STOP"); | ||||
|             setDecoder_isSending(); | ||||
|             // Serial.println(); | ||||
|             return; | ||||
|             break; | ||||
|  | ||||
| @ -332,32 +439,6 @@ void IR_Encoder::isr() | ||||
|     } | ||||
| } | ||||
|  | ||||
| void old() | ||||
| { /////////////////////////////////////////////////////// | ||||
|     // void IR_Encoder::rawSend(uint8_t* ptr, uint8_t len) { | ||||
|     //     /*tmp*/bool LOW_FIRST = false;/*tmp*/ | ||||
|  | ||||
|     //     if (decoders != nullptr) { decoders->isPairSending = true; } | ||||
|  | ||||
|     //     bool prev = 1; | ||||
|     //     bool next; | ||||
|  | ||||
|     //     send_EMPTY(preambPulse); // преамбула | ||||
|     //     for (uint16_t byteNum = 0; byteNum < len; byteNum++) { | ||||
|     //         sendByte(ptr[byteNum], &prev, LOW_FIRST); | ||||
|     //         if (byteNum < len - 1) { | ||||
|     //             next = ptr[byteNum + 1] & (LOW_FIRST ? 0b00000001 : 0b10000000); | ||||
|     //         } else { | ||||
|     //             next = 0; | ||||
|     //         } | ||||
|     //         addSync(&prev, &next); | ||||
|     //     } | ||||
|  | ||||
|     //     if (decoders != nullptr) { decoders->isPairSending = false; } | ||||
|  | ||||
|     // } | ||||
| } | ||||
|  | ||||
| void IR_Encoder::sendByte(uint8_t byte, bool *prev, bool LOW_FIRST) | ||||
| { | ||||
|     uint8_t mask = LOW_FIRST ? 0b00000001 : 0b10000000; | ||||
| @ -395,30 +476,16 @@ void IR_Encoder::addSync(bool *prev, bool *next) | ||||
|     } | ||||
| } | ||||
|  | ||||
| void IR_Encoder::send_HIGH(bool prevBite = 1) | ||||
| { | ||||
| uint8_t IR_Encoder::bitHigh[2] = { | ||||
|     (bitPauseTakts) * 2 - 1, | ||||
|     (bitActiveTakts) * 2 - 1}; | ||||
| uint8_t IR_Encoder::bitLow[2] = { | ||||
|     (bitPauseTakts / 2 + bitActiveTakts) * 2 - 1, | ||||
|     (bitPauseTakts)-1}; | ||||
|  | ||||
|     // if (/* prevBite */1) { | ||||
|     //     meanderBlock(bitPauseTakts * 2, halfPeriod, LOW); | ||||
|     //     meanderBlock(bitActiveTakts, halfPeriod, HIGH); | ||||
|     // } else {                                                    // более короткий HIGH после нуля | ||||
|     //     meanderBlock(bitTakts - (bitActiveTakts - bitPauseTakts), halfPeriod, LOW); | ||||
|     //     meanderBlock(bitActiveTakts - bitPauseTakts, halfPeriod, HIGH); | ||||
|     // } | ||||
| } | ||||
|  | ||||
| void IR_Encoder::send_LOW() | ||||
| { | ||||
|     // meanderBlock(bitPauseTakts, halfPeriod, LOW); | ||||
|     // meanderBlock(bitActiveTakts, halfPeriod, LOW); | ||||
|     // meanderBlock(bitPauseTakts, halfPeriod, HIGH); | ||||
| } | ||||
|  | ||||
| void IR_Encoder::send_EMPTY(uint8_t count) | ||||
| { | ||||
|     // for (size_t i = 0; i < count * 2; i++) { | ||||
|     // meanderBlock((bitPauseTakts * 2 + bitActiveTakts), halfPeriod, prevPreambBit); | ||||
|     //     prevPreambBit = !prevPreambBit; | ||||
|     // } | ||||
|     // meanderBlock(bitPauseTakts * 2 + bitActiveTakts, halfPeriod, 0); //TODO: Отодвинуть преамбулу | ||||
| } | ||||
| // uint8_t* IR_Encoder::bitHigh = new uint8_t[2]{ | ||||
| //         (bitPauseTakts) * 2 - 0, | ||||
| //         (bitActiveTakts) * 2 - 0}; | ||||
| // uint8_t* IR_Encoder::bitLow = new uint8_t[2]{ | ||||
| //         (bitPauseTakts/2 + bitActiveTakts) * 2 - 0, | ||||
| //         (bitPauseTakts) - 0}; | ||||
|  | ||||
							
								
								
									
										60
									
								
								IR_Encoder.h
									
									
									
									
									
								
							
							
						
						
									
										60
									
								
								IR_Encoder.h
									
									
									
									
									
								
							| @ -4,51 +4,36 @@ | ||||
| // TODO: Отложенная передача после завершения приема | ||||
|  | ||||
| class IR_DecoderRaw; | ||||
| class IR_Encoder : IR_FOX | ||||
| class IR_Encoder : public IR_FOX | ||||
| { | ||||
|     friend IR_DecoderRaw; | ||||
|  | ||||
|     static IR_Encoder *head; | ||||
|     static IR_Encoder *last; | ||||
|     IR_Encoder *next; | ||||
| public: | ||||
|     static HardwareTimer* IR_Timer; | ||||
| private: | ||||
|     uint16_t id; /// @brief Адрес передатчика | ||||
|  | ||||
|     // uint16_t id; /// @brief Адрес передатчика | ||||
| public: | ||||
|     /// @brief Класс передатчика | ||||
|     /// @param addr Адрес передатчика | ||||
|     /// @param pin  Вывод передатчика | ||||
|     /// @param tune Подстройка несущей частоты | ||||
|     /// @param decPair Приёмник, для которого отключается приём в момент передачи передатчиком | ||||
|     IR_Encoder(uint16_t addr, IR_DecoderRaw *decPair = nullptr); | ||||
|     IR_Encoder(uint8_t pin, uint16_t addr = 0, IR_DecoderRaw *decPair = nullptr, bool autoHandle = true); | ||||
|     static void isr(); | ||||
|     static void begin(HardwareTimer* timer, uint8_t channel, IRQn_Type IRQn, uint8_t priority, void(*isrCallback)() = nullptr); | ||||
|     static HardwareTimer* get_IR_Timer(); | ||||
|  | ||||
|     static void timerSetup() | ||||
|     { | ||||
|         // TIMER2 Ini | ||||
|         uint8_t oldSREG = SREG; // Save global interupts settings | ||||
|         cli(); | ||||
|         // DDRB |= (1 << PORTB3);  //OC2A (17) | ||||
|         TCCR2A = 0; | ||||
|         TCCR2B = 0; | ||||
|     void enable(); | ||||
|     void disable(); | ||||
|  | ||||
|         // TCCR2A |= (1 << COM2A0);                 //Переключение состояния | ||||
|  | ||||
|         TCCR2A |= (1 << WGM21);  // Clear Timer On Compare (Сброс по совпадению) | ||||
|         TCCR2B |= (1 << CS20);   // Предделитель 1 | ||||
|         TIMSK2 |= (1 << OCIE2A); // Прерывание по совпадению | ||||
|  | ||||
|         OCR2A = /* 465 */ ((F_CPU / (38000 * 2)) - 2); // 38кГц | ||||
|  | ||||
|         SREG = oldSREG; // Return interrupt settings | ||||
|     } | ||||
|     static void timerOFFSetup() | ||||
|     { | ||||
|         TIMSK2 &= ~(1 << OCIE2A); // Прерывание по совпадению выкл | ||||
|     } | ||||
|  | ||||
|     void IR_Encoder::setBlindDecoders(IR_DecoderRaw *decoders[], uint8_t count); | ||||
|     void setBlindDecoders(IR_DecoderRaw *decoders[], uint8_t count); | ||||
|     void rawSend(uint8_t *ptr, uint8_t len); | ||||
|  | ||||
|     void sendData(uint16_t addrTo, uint8_t dataByte, bool needAccept = false); | ||||
|     void sendData(uint16_t addrTo, uint8_t *data = nullptr, uint8_t len = 0, bool needAccept = false); | ||||
|     void sendDataFULL(uint16_t addrFrom, uint16_t addrTo, uint8_t *data = nullptr, uint8_t len = 0, bool needAccept = false); | ||||
|  | ||||
|  | ||||
|     void sendAccept(uint16_t addrTo, uint8_t customByte = 0); | ||||
|     void sendRequest(uint16_t addrTo); | ||||
| @ -57,15 +42,15 @@ public: | ||||
|     void sendBack(uint8_t *data = nullptr, uint8_t len = 0); | ||||
|     void sendBackTo(uint16_t addrTo, uint8_t *data = nullptr, uint8_t len = 0); | ||||
|  | ||||
|     void isr(); | ||||
|  | ||||
|     ~IR_Encoder(); | ||||
|     volatile bool ir_out_virtual; | ||||
|  | ||||
|     void _isr(); | ||||
| private: | ||||
|     void IR_Encoder::_sendBack(bool isAdressed, uint16_t addrTo, uint8_t *data, uint8_t len); | ||||
|     void _sendBack(bool isAdressed, uint16_t addrTo, uint8_t *data, uint8_t len); | ||||
|  | ||||
|     void IR_Encoder::setDecoder_isSending(); | ||||
|     void setDecoder_isSending(); | ||||
|     void sendByte(uint8_t byte, bool *prev, bool LOW_FIRST); | ||||
|     void addSync(bool *prev, bool *next); | ||||
|     void send_HIGH(bool = 1); | ||||
| @ -105,12 +90,9 @@ private: | ||||
|         uint8_t low; | ||||
|         uint8_t high; | ||||
|     }; | ||||
|     static inline uint8_t *bitHigh = new uint8_t[2]{ | ||||
|         (bitPauseTakts * 2) * 2 - 1, | ||||
|         (bitActiveTakts) * 2 - 1}; | ||||
|     static inline uint8_t *bitLow = new uint8_t[2]{ | ||||
|         (bitPauseTakts + bitActiveTakts) * 2 - 1, | ||||
|         (bitPauseTakts) * 2 - 1}; | ||||
|     static uint8_t bitHigh[2]; | ||||
|     static uint8_t bitLow[2]; | ||||
|     uint8_t *currentBitSequence = bitLow; | ||||
|     volatile SignalPart signal; | ||||
| }; | ||||
|  | ||||
|  | ||||
							
								
								
									
										33
									
								
								IR_config.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								IR_config.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,33 @@ | ||||
| #include "IR_config.h" | ||||
|  | ||||
| void IR_FOX::setPin(uint8_t pin){ | ||||
|     this->pin = pin; | ||||
|     port = digitalPinToPort(pin); | ||||
|     mask = digitalPinToBitMask(pin); | ||||
| } | ||||
|  | ||||
| void IR_FOX::checkAddressRuleApply(uint16_t address, uint16_t id, bool &flag) | ||||
| { | ||||
|     flag = false; | ||||
|     flag |= id == 0; | ||||
|     flag |= address == id; | ||||
|     flag |= address >= IR_Broadcast; | ||||
| } | ||||
|  | ||||
| uint8_t IR_FOX::crc8(uint8_t *data, uint8_t start, uint8_t end, uint8_t poly) | ||||
| { // TODO: сделать возможность межбайтовой проверки | ||||
|     uint8_t crc = 0xff; | ||||
|     size_t i, j; | ||||
|     for (i = start; i < end; i++) | ||||
|     { | ||||
|         crc ^= data[i]; | ||||
|         for (j = 0; j < 8; j++) | ||||
|         { | ||||
|             if ((crc & 0x80) != 0) | ||||
|                 crc = (uint8_t)((crc << 1) ^ poly); | ||||
|             else | ||||
|                 crc <<= 1; | ||||
|         } | ||||
|     } | ||||
|     return crc; | ||||
| }; | ||||
							
								
								
									
										183
									
								
								IR_config.h
									
									
									
									
									
								
							
							
						
						
									
										183
									
								
								IR_config.h
									
									
									
									
									
								
							| @ -1,25 +1,39 @@ | ||||
| #pragma once | ||||
| #include <Arduino.h> | ||||
|  | ||||
| #include <list> | ||||
| // #define IRDEBUG_INFO | ||||
| /*////////////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| Для работы в паре положить декодер в энкодер | ||||
|  | ||||
| */// Адресация с 1 до 65 499 | ||||
| #define IR_Broadcast 65000 // 65 500 ~ 65 535 - широковещательные пакеты (всем), возможно разделить на 35 типов  | ||||
| */ | ||||
| // Адресация с 1 до 65 499 | ||||
| #define IR_Broadcast 65000 // 65 500 ~ 65 535 - широковещательные пакеты (всем) | ||||
| /* | ||||
| Адрес 0 запрещен и зарезервирован под NULL, либо тесты | ||||
| IR_MSG_ACCEPT с адреса 0 воспринимается всеми устройствами | ||||
| *Адресное пространство: | ||||
|     Адрес 0 запрещен и зарезервирован под NULL, либо тесты | ||||
|     IR_MSG_ACCEPT с адреса 0 воспринимается всеми устройствами | ||||
| */  | ||||
| //**** Контрольные точки ****** | ||||
| #define IR_MAX_ADDR_CPU 63999 | ||||
| #define IR_MIN_ADDR_CPU 32000 | ||||
|  | ||||
| // //***** Группы машинок ******** | ||||
| // #define IR_MAX_CAR_GROUP 31999 | ||||
| // #define IR_MIN_CAR_GROUP 30000 | ||||
|  | ||||
| Адресное пространство: | ||||
|  | ||||
| Излучатели контрольных точек: 1000 ~ 1999 | ||||
| Излучатели без обратной связиЖ 2000 ~ 2999 | ||||
| Излучатели светофоров: 3000 ~ 3999 | ||||
| // //********** FREE ************* | ||||
| // #define IR_MAX_FREE 31999 | ||||
| // #define IR_MIN_FREE 2000 | ||||
|  | ||||
| //********* Машинки *********** | ||||
| #define IR_MAX_CAR 31999 | ||||
| #define IR_MIN_CAR 1 | ||||
|  | ||||
| //***** Пульты управления ***** | ||||
| #define IR_MAX_CONTROLLER 64999 | ||||
| #define IR_MIN_CONTROLLER 64000 | ||||
| /* | ||||
|  | ||||
| /```````````````````````````````````````````````` data pack `````````````````````````````````````````````\                                   | ||||
|                                                                                                           | ||||
| @ -43,56 +57,56 @@ msg type: | ||||
| #define IR_MSG_BACK 0U          //  | 000...... | = Задний сигнал машинки | ||||
| #define IR_MSG_ACCEPT 1U        //  | 001..... | = подтверждение | ||||
| #define IR_MSG_REQUEST 2U       //  | 010..... | = запрос | ||||
| #define IR_MSG_                      3U //  | 011..... | = ?? | ||||
| // #define IR_MSG_ 3U           //  | 011..... | = ?? | ||||
| #define IR_MSG_BACK_TO 4U       //  | 100..... | = Задний сигнал машинки c адресацией | ||||
| #define IR_MSG_                      5U //  | 101..... | = ?? | ||||
| // #define IR_MSG_ 5U           //  | 101..... | = ?? | ||||
| #define IR_MSG_DATA_NOACCEPT 6U //  | 110..... | = данные, не требующие подтверждения | ||||
| #define IR_MSG_DATA_ACCEPT 7U   //  | 111..... | = данные требующие подтверждения | ||||
| ;/*                                     //   ---------- | ||||
| ;                               /*                                     //   ---------- | ||||
|                                | ||||
| /``````````````````````````````` подтверждение `````````````````````````````\      /``````````````````````````````````````` запрос ``````````````````````````````````\ | ||||
|                                                                                                                        | ||||
| {``````````} [````````````````````````] [``````````````````] [``````````````]      {``````````} [````````````````````````] [````````````````````````] [``````````````] | ||||
| { msg type } [   addr_from uint16_t   ] [=== customByte ===] [   CRC Bytes  ]      { msg type } [   addr_from uint16_t   ] [    addr_to uint16_t    ] [   CRC Bytes  ] | ||||
| {..........} [........................] [..................] [..............]      {..........} [........................] [........................] [..............] | ||||
|                                                                                                                                                              | ||||
| { 001..... } [addr_from_H][addr_from_L] [=== customByte ===] [ crc1 ][ crc2 ]      { 010..... } [addr_from_H][addr_from_L] [addr_from_H][addr_from_L] [ crc1 ][ crc2 ] | ||||
| |     0            1           2                  3              4       5          |     0            1           2              3           4           5       6     | ||||
| \________________________________________________________________/       |          \_____________________________________________________________________/       |     | ||||
| |                                                                        |          |                                                                             |     | ||||
| \________________________________________________________________________/          \_____________________________________________________________________________/     | ||||
|                                /``````````````````````````````` подтверждение `````````````````````````````\      /``````````````````````````````````````` запрос ``````````````````````````````````\ | ||||
|                                                                                                                                                       | ||||
|                                {``````````} [````````````````````````] [``````````````````] [``````````````]      {``````````} [````````````````````````] [````````````````````````] [``````````````] | ||||
|                                { msg type } [   addr_from uint16_t   ] [=== customByte ===] [   CRC Bytes  ]      { msg type } [   addr_from uint16_t   ] [    addr_to uint16_t    ] [   CRC Bytes  ] | ||||
|                                {..........} [........................] [..................] [..............]      {..........} [........................] [........................] [..............] | ||||
|                                                                                                                                                                                             | ||||
|                                { 001..... } [addr_from_H][addr_from_L] [=== customByte ===] [ crc1 ][ crc2 ]      { 010..... } [addr_from_H][addr_from_L] [addr_from_H][addr_from_L] [ crc1 ][ crc2 ] | ||||
|                                |     0            1           2                  3              4       5          |     0            1           2              3           4           5       6     | ||||
|                                \________________________________________________________________/       |          \_____________________________________________________________________/       |     | ||||
|                                |                                                                        |          |                                                                             |     | ||||
|                                \________________________________________________________________________/          \_____________________________________________________________________________/     | ||||
|                                | ||||
| customByte - контрольная сумма принятых данных по poly1 | ||||
|                                customByte - контрольная сумма принятых данных по poly1 | ||||
|                                | ||||
|                                | ||||
|                                | ||||
| /`````````````````````` Задний сигнал машинки без адресации ``````````````````````\         | ||||
|                                                                                             | ||||
| {``````````} [````````````````````````] [````````````````````````] [``````````````]         | ||||
| { msg type } [   addr_from uint16_t   ] [====== data bytes ======] [   CRC Bytes  ]         | ||||
| {..........} [........................] [........................] [..............]         | ||||
|                                                                                             | ||||
| { 0000xxxx } [addr_from_H][addr_from_L] [data_H][data_n..][data_L] [ crc1 ][ crc2 ]         | ||||
| |     0           1            2            3                         |       |             | ||||
| \_____________________________________________________________________/       |             | ||||
| |                                                                             |             | ||||
| \_____________________________________________________________________________/             | ||||
|                                /`````````````````````` Задний сигнал машинки без адресации ``````````````````````\         | ||||
|                                                                                                                            | ||||
|                                {``````````} [````````````````````````] [````````````````````````] [``````````````]         | ||||
|                                { msg type } [   addr_from uint16_t   ] [====== data bytes ======] [   CRC Bytes  ]         | ||||
|                                {..........} [........................] [........................] [..............]         | ||||
|                                                                                                                            | ||||
|                                { 0000xxxx } [addr_from_H][addr_from_L] [data_H][data_n..][data_L] [ crc1 ][ crc2 ]         | ||||
|                                |     0           1            2            3                         |       |             | ||||
|                                \_____________________________________________________________________/       |             | ||||
|                                |                                                                             |             | ||||
|                                \_____________________________________________________________________________/             | ||||
|                                | ||||
|                                | ||||
|                                | ||||
| /```````````````````````````````````` Задний сигнал машинки с адресацией ````````````````````````````````````\  | ||||
|                                                                                      | ||||
| {``````````} [````````````````````````] [````````````````````````] [````````````````````````] [``````````````]  | ||||
| { msg type } [   addr_from uint16_t   ] [    addr_to uint16_t    ] [====== data bytes ======] [   CRC Bytes  ]  | ||||
| {..........} [........................] [........................] [........................] [..............]  | ||||
|                                                                                                                 | ||||
| { 0001xxxx } [addr_from_H][addr_from_L] [addr_from_H][addr_from_L] [data_H][data_n..][data_L] [ crc1 ][ crc2 ]  | ||||
| |     0           1            2              3           4            5                         |       |      | ||||
| \________________________________________________________________________________________________/       |      | ||||
| |                                                                                                        |      | ||||
| \________________________________________________________________________________________________________/      | ||||
|                                /```````````````````````````````````` Задний сигнал машинки с адресацией ````````````````````````````````````\  | ||||
|                                                                                                                     | ||||
|                                {``````````} [````````````````````````] [````````````````````````] [````````````````````````] [``````````````]  | ||||
|                                { msg type } [   addr_from uint16_t   ] [    addr_to uint16_t    ] [====== data bytes ======] [   CRC Bytes  ]  | ||||
|                                {..........} [........................] [........................] [........................] [..............]  | ||||
|                                                                                                                                                | ||||
|                                { 0001xxxx } [addr_from_H][addr_from_L] [addr_from_H][addr_from_L] [data_H][data_n..][data_L] [ crc1 ][ crc2 ]  | ||||
|                                |     0           1            2              3           4            5                         |       |      | ||||
|                                \________________________________________________________________________________________________/       |      | ||||
|                                |                                                                                                        |      | ||||
|                                \________________________________________________________________________________________________________/      | ||||
|                                | ||||
| */ | ||||
|                                */ | ||||
|  | ||||
| #define IR_MASK_MSG_TYPE 0b00000111 | ||||
| #define IR_MASK_MSG_INFO 0b00011111 | ||||
| @ -101,13 +115,14 @@ customByte - контрольная сумма принятых данных п | ||||
| /////////////////////////////////////////////////////////////////////////////////////*/ | ||||
| typedef uint16_t crc_t; | ||||
|  | ||||
| // #define BRUTEFORCE_CHECK                            // Перепроверяет пакет на 1 битные ошибки //TODO: зависает | ||||
| #define bytePerPack 16 // колличество байтов в пакете | ||||
| #ifndef freeFrec | ||||
| #define freeFrec true | ||||
| #define freeFrec false | ||||
| #endif | ||||
|  | ||||
| #ifndef subBufferSize | ||||
| #define subBufferSize 35 //Буфер для складирования фронтов, пока их не обработают (передатчик) | ||||
| #define subBufferSize 50 // Буфер для складирования фронтов, пока их не обработают (передатчик) | ||||
| #endif | ||||
|  | ||||
| #define preambPulse 3 | ||||
| @ -126,23 +141,30 @@ typedef uint16_t crc_t; | ||||
|  | ||||
| #define dataByteSizeMax (msgBytes + addrBytes + addrBytes + bytePerPack + crcBytes) | ||||
|  | ||||
| #define preambFronts (preambPulse*2)                        // количество фронтов преамбулы (Приём) | ||||
| #define preambFronts (preambPulse * 2)                              // количество фронтов преамбулы (Приём) | ||||
| #define preambToggle ((bitPauseTakts * 2 + bitActiveTakts) * 2 - 1) // колличество переключений преамбулы (Передача) | ||||
|  | ||||
| #define carrierFrec 38000U                     // частота несущей (Приём/Передача) | ||||
| #define carrierPeriod (1000000U/carrierFrec)                // период несущей в us (Приём) | ||||
| #define carrierPeriod (1000000U / carrierFrec) // период несущей в us (Приём) | ||||
|  | ||||
| // В процессе работы значения будут отклонятся в соответствии с предыдущим битом | ||||
| #define bitActiveTakts 25U // длительность высокого уровня в тактах | ||||
| #define bitPauseTakts 6U                                    // длительность низкого уровня в тактах | ||||
| #define bitPauseTakts 12U  // длительность низкого уровня в тактах | ||||
|  | ||||
| #define bitTakts (bitActiveTakts+(bitPauseTakts*2U))          // Общая длительность бита в тактах | ||||
| #define bitTime (bitTakts*carrierPeriod)                    // Общая длительность бита | ||||
| #define bitTakts (bitActiveTakts + bitPauseTakts) // Общая длительность бита в тактах | ||||
| #define bitTime (bitTakts * carrierPeriod)        // Общая длительность бита | ||||
| #define tolerance 300U | ||||
|  | ||||
| class IR_FOX { | ||||
| constexpr uint16_t test_all_Time = bitTime; | ||||
| constexpr uint16_t test_all_Takts = bitTakts * 2; | ||||
| constexpr uint16_t test_hi = ((bitPauseTakts) * 2 - 0) + ((bitActiveTakts) * 2 - 0); | ||||
| constexpr uint16_t test_low = ((bitPauseTakts / 2 + bitActiveTakts) * 2 - 0) + ((bitPauseTakts)-0); | ||||
|  | ||||
| class IR_FOX | ||||
| { | ||||
| public: | ||||
|     struct PackOffsets { | ||||
|     struct PackOffsets | ||||
|     { | ||||
|         uint8_t msgOffset; | ||||
|         uint8_t addrFromOffset; | ||||
|         uint8_t addrToOffset; | ||||
| @ -150,54 +172,41 @@ public: | ||||
|         uint8_t crcOffset; | ||||
|     }; | ||||
|  | ||||
|     struct ErrorsStruct { | ||||
|     struct ErrorsStruct | ||||
|     { | ||||
|         uint8_t lowSignal = 0; | ||||
|         uint8_t highSignal = 0; | ||||
|         uint8_t other = 0; | ||||
|  | ||||
|         void reset() { | ||||
|         void reset() | ||||
|         { | ||||
|             lowSignal = 0; | ||||
|             highSignal = 0; | ||||
|             other = 0; | ||||
|         } | ||||
|         uint16_t all() { return lowSignal + highSignal + other; } | ||||
|  | ||||
|     }; | ||||
|  | ||||
|     struct PackInfo { | ||||
|         uint8_t* buffer = nullptr; | ||||
|     struct PackInfo | ||||
|     { | ||||
|         uint8_t *buffer = nullptr; | ||||
|         uint8_t packSize = 0; | ||||
|         uint16_t crc = 0; | ||||
|         ErrorsStruct err; | ||||
|         uint16_t rTime = 0; | ||||
|     }; | ||||
|  | ||||
|     static void checkAddressRuleApply(uint16_t address, uint16_t id, bool& flag) { | ||||
|         flag = false; | ||||
|         flag |= id == 0; | ||||
|         flag |= address == id; | ||||
|         flag |= address >= IR_Broadcast; | ||||
|     } | ||||
|  | ||||
|     uint16_t getId() { return id; } | ||||
|     void setId(uint16_t id) { this->id = id; } | ||||
|     inline uint16_t getId() const { return id; } | ||||
|     inline void setId(uint16_t id) { this->id = id; } | ||||
|     static void checkAddressRuleApply(uint16_t address, uint16_t id, bool &flag); | ||||
|     void setPin(uint8_t pin); | ||||
|     inline uint8_t getPin() { return pin; }; | ||||
|  | ||||
| protected: | ||||
|     ErrorsStruct errors; | ||||
|     uint16_t id; | ||||
|     uint8_t crc8(uint8_t* data, uint8_t start, uint8_t end, uint8_t poly) { //TODO: сделать возможность межбайтовой проверки | ||||
|         uint8_t crc = 0xff; | ||||
|         size_t i, j; | ||||
|         for (i = start; i < end; i++) { | ||||
|             crc ^= data[i]; | ||||
|             for (j = 0; j < 8; j++) { | ||||
|                 if ((crc & 0x80) != 0) | ||||
|                     crc = (uint8_t)((crc << 1) ^ poly); | ||||
|                 else | ||||
|                     crc <<= 1; | ||||
|             } | ||||
|         } | ||||
|         return crc; | ||||
|     } | ||||
|  | ||||
|     uint8_t pin; | ||||
|     GPIO_TypeDef *port; | ||||
|     uint16_t mask; | ||||
|     ErrorsStruct errors; | ||||
|     uint8_t crc8(uint8_t *data, uint8_t start, uint8_t end, uint8_t poly); | ||||
| }; | ||||
|  | ||||
							
								
								
									
										107
									
								
								PacketTypes.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								PacketTypes.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,107 @@ | ||||
| #include "PacketTypes.h" | ||||
|  | ||||
| namespace PacketTypes | ||||
| { | ||||
|     bool BasePack::checkAddress() { return true; }; | ||||
|     void BasePack::set(IR_FOX::PackInfo *packInfo, uint16_t id) | ||||
|     { | ||||
|         this->packInfo = packInfo; | ||||
|         this->id = id; | ||||
|  | ||||
|         if (checkAddress()) | ||||
|         { | ||||
|             isAvailable = true; | ||||
|             isRawAvailable = true; | ||||
| #ifdef IRDEBUG_INFO | ||||
|             Serial.print("  OK  "); | ||||
| #endif | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             isRawAvailable = true; | ||||
| #ifdef IRDEBUG_INFO | ||||
|             Serial.print("  NOT-OK  "); | ||||
| #endif | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     uint16_t BasePack::_getAddrFrom(BasePack *obj) | ||||
|     { | ||||
|         return (obj->packInfo->buffer[obj->addressFromOffset] << 8) | obj->packInfo->buffer[obj->addressFromOffset + 1]; | ||||
|     }; | ||||
|     uint16_t BasePack::_getAddrTo(BasePack *obj) | ||||
|     { | ||||
|         return (obj->packInfo->buffer[obj->addressToOffset] << 8) | obj->packInfo->buffer[obj->addressToOffset + 1]; | ||||
|     }; | ||||
|  | ||||
|     uint8_t BasePack::_getDataSize(BasePack *obj) | ||||
|     { | ||||
|         return obj->packInfo->packSize - crcBytes - obj->DataOffset; | ||||
|     }; | ||||
|     uint8_t *BasePack::_getDataPrt(BasePack *obj) | ||||
|     { | ||||
|         return obj->packInfo->buffer + obj->DataOffset; | ||||
|     }; | ||||
|     uint8_t BasePack::_getDataRawSize(BasePack *obj) | ||||
|     { | ||||
|         return obj->packInfo->packSize; | ||||
|     }; | ||||
|  | ||||
|     bool BasePack::available() | ||||
|     { | ||||
|         if (isAvailable) | ||||
|         { | ||||
|             isAvailable = false; | ||||
|             isRawAvailable = false; | ||||
|             return true; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             return false; | ||||
|         } | ||||
|     }; | ||||
|     bool BasePack::availableRaw() | ||||
|     { | ||||
|         if (isRawAvailable) | ||||
|         { | ||||
|             isRawAvailable = false; | ||||
|             return true; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             return false; | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     bool Data::checkAddress() | ||||
|     { | ||||
|         bool ret; | ||||
|         IR_FOX::checkAddressRuleApply(getAddrTo(), this->id, ret); | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     bool DataBack::checkAddress() | ||||
|     { | ||||
|         bool ret; | ||||
|         if (getMsgType() == IR_MSG_BACK_TO) | ||||
|         { | ||||
|             DataOffset = 5; | ||||
|             IR_FOX::checkAddressRuleApply((packInfo->buffer[addressToOffset] << 8) | packInfo->buffer[addressToOffset + 1], this->id, ret); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             DataOffset = 3; | ||||
|             ret = true; | ||||
|         } | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     bool Accept::checkAddress() { return true; } | ||||
|  | ||||
|     bool Request::checkAddress() | ||||
|     { | ||||
|         bool ret; | ||||
|         IR_FOX::checkAddressRuleApply(getAddrTo(), this->id, ret); | ||||
|         return ret; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										308
									
								
								PacketTypes.h
									
									
									
									
									
								
							
							
						
						
									
										308
									
								
								PacketTypes.h
									
									
									
									
									
								
							| @ -21,86 +21,28 @@ namespace PacketTypes | ||||
|         IR_FOX::PackInfo *packInfo; | ||||
|         uint16_t id; | ||||
|  | ||||
|         virtual bool checkAddress() { return true; }; | ||||
|         void set(IR_FOX::PackInfo *packInfo, uint16_t id) | ||||
|         { | ||||
|             this->packInfo = packInfo; | ||||
|             this->id = id; | ||||
|         virtual bool checkAddress(); | ||||
|         void set(IR_FOX::PackInfo *packInfo, uint16_t id); | ||||
|  | ||||
|             if (checkAddress()) | ||||
|             { | ||||
|                 isAvailable = true; | ||||
|                 isRawAvailable = true; | ||||
| #ifdef IRDEBUG_INFO | ||||
|                 Serial.print("  OK  "); | ||||
| #endif | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 isRawAvailable = true; | ||||
| #ifdef IRDEBUG_INFO | ||||
|                 Serial.print("  NOT-OK  "); | ||||
| #endif | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         static uint16_t _getAddrFrom(BasePack *obj) | ||||
|         { | ||||
|             return (obj->packInfo->buffer[obj->addressFromOffset] << 8) | obj->packInfo->buffer[obj->addressFromOffset + 1]; | ||||
|         }; | ||||
|         static uint16_t _getAddrTo(BasePack *obj) | ||||
|         { | ||||
|             return (obj->packInfo->buffer[obj->addressToOffset] << 8) | obj->packInfo->buffer[obj->addressToOffset + 1]; | ||||
|         }; | ||||
|  | ||||
|         static uint8_t _getDataSize(BasePack *obj) | ||||
|         { | ||||
|             return obj->packInfo->packSize - crcBytes - obj->DataOffset; | ||||
|         }; | ||||
|         static uint8_t *_getDataPrt(BasePack *obj) | ||||
|         { | ||||
|             return obj->packInfo->buffer + obj->DataOffset; | ||||
|         }; | ||||
|         static uint8_t _getDataRawSize(BasePack *obj) | ||||
|         { | ||||
|             return obj->packInfo->packSize; | ||||
|         }; | ||||
|         static uint16_t _getAddrFrom(BasePack *obj); | ||||
|         static uint16_t _getAddrTo(BasePack *obj); | ||||
|         static uint8_t _getDataSize(BasePack *obj); | ||||
|         static uint8_t *_getDataPrt(BasePack *obj); | ||||
|         static uint8_t _getDataRawSize(BasePack *obj); | ||||
|  | ||||
|     public: | ||||
|         bool available() | ||||
|         { | ||||
|             if (isAvailable) | ||||
|             { | ||||
|                 isAvailable = false; | ||||
|                 isRawAvailable = false; | ||||
|                 return true; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 return false; | ||||
|             } | ||||
|         }; | ||||
|         bool availableRaw() | ||||
|         { | ||||
|             if (isRawAvailable) | ||||
|             { | ||||
|                 isRawAvailable = false; | ||||
|                 return true; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 return false; | ||||
|             } | ||||
|         }; | ||||
|         uint8_t getMsgInfo() { return packInfo->buffer[0] & IR_MASK_MSG_INFO; }; | ||||
|         uint8_t getMsgType() { return (packInfo->buffer[0] >> 5) & IR_MASK_MSG_TYPE; }; | ||||
|         uint8_t getMsgRAW() { return packInfo->buffer[0]; }; | ||||
|         uint16_t getErrorCount() { return packInfo->err.all(); }; | ||||
|         uint8_t getErrorLowSignal() { return packInfo->err.lowSignal; }; | ||||
|         uint8_t getErrorHighSignal() { return packInfo->err.highSignal; }; | ||||
|         uint8_t getErrorOther() { return packInfo->err.other; }; | ||||
|         uint16_t getTunerTime() { return packInfo->rTime; }; | ||||
|         uint8_t *getDataRawPtr() { return packInfo->buffer; }; | ||||
|         bool available(); | ||||
|         bool availableRaw(); | ||||
|  | ||||
|         inline uint8_t getMsgInfo() { return packInfo->buffer[0] & IR_MASK_MSG_INFO; }; | ||||
|         inline uint8_t getMsgType() { return (packInfo->buffer[0] >> 5) & IR_MASK_MSG_TYPE; }; | ||||
|         inline uint8_t getMsgRAW() { return packInfo->buffer[0]; }; | ||||
|         inline uint16_t getErrorCount() { return packInfo->err.all(); }; | ||||
|         inline uint8_t getErrorLowSignal() { return packInfo->err.lowSignal; }; | ||||
|         inline uint8_t getErrorHighSignal() { return packInfo->err.highSignal; }; | ||||
|         inline uint8_t getErrorOther() { return packInfo->err.other; }; | ||||
|         inline uint16_t getTunerTime() { return packInfo->rTime; }; | ||||
|         inline uint8_t *getDataRawPtr() { return packInfo->buffer; }; | ||||
|     }; | ||||
|  | ||||
|     class Data : public BasePack | ||||
| @ -114,20 +56,15 @@ namespace PacketTypes | ||||
|             DataOffset = 5; | ||||
|         } | ||||
|  | ||||
|         uint16_t getAddrFrom() { return _getAddrFrom(this); }; | ||||
|         uint16_t getAddrTo() { return _getAddrTo(this); }; | ||||
|         inline uint16_t getAddrFrom() { return _getAddrFrom(this); }; | ||||
|         inline uint16_t getAddrTo() { return _getAddrTo(this); }; | ||||
|  | ||||
|         uint8_t getDataSize() { return _getDataSize(this); }; | ||||
|         uint8_t *getDataPrt() { return _getDataPrt(this); }; | ||||
|         uint8_t getDataRawSize() { return _getDataRawSize(this); }; | ||||
|         inline uint8_t getDataSize() { return _getDataSize(this); }; | ||||
|         inline uint8_t *getDataPrt() { return _getDataPrt(this); }; | ||||
|         inline uint8_t getDataRawSize() { return _getDataRawSize(this); }; | ||||
|  | ||||
|     private: | ||||
|         bool checkAddress() override | ||||
|         { | ||||
|             bool ret; | ||||
|             IR_FOX::checkAddressRuleApply(getAddrTo(), this->id, ret); | ||||
|             return ret; | ||||
|         } | ||||
|         bool checkAddress() override; | ||||
|     }; | ||||
|  | ||||
|     class DataBack : public BasePack | ||||
| @ -141,29 +78,15 @@ namespace PacketTypes | ||||
|             DataOffset = 3; | ||||
|         } | ||||
|  | ||||
|         uint16_t getAddrFrom() { return _getAddrFrom(this); }; | ||||
|         uint16_t getAddrTo() { return _getAddrTo(this); }; | ||||
|         inline uint16_t getAddrFrom() { return _getAddrFrom(this); }; | ||||
|         inline uint16_t getAddrTo() { return _getAddrTo(this); }; | ||||
|  | ||||
|         uint8_t getDataSize() { return _getDataSize(this); }; | ||||
|         uint8_t *getDataPrt() { return _getDataPrt(this); }; | ||||
|         uint8_t getDataRawSize() { return _getDataRawSize(this); }; | ||||
|         inline uint8_t getDataSize() { return _getDataSize(this); }; | ||||
|         inline uint8_t *getDataPrt() { return _getDataPrt(this); }; | ||||
|         inline uint8_t getDataRawSize() { return _getDataRawSize(this); }; | ||||
|  | ||||
|     private: | ||||
|         bool checkAddress() override | ||||
|         { | ||||
|             bool ret; | ||||
|             if (getMsgType() == IR_MSG_BACK_TO) | ||||
|             { | ||||
|                 DataOffset = 5; | ||||
|                 IR_FOX::checkAddressRuleApply((packInfo->buffer[addressToOffset] << 8) | packInfo->buffer[addressToOffset + 1], this->id, ret); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 DataOffset = 3; | ||||
|                 ret = true; | ||||
|             } | ||||
|             return ret; | ||||
|         } | ||||
|         bool checkAddress() override; | ||||
|     }; | ||||
|  | ||||
|     class Accept : public BasePack | ||||
| @ -176,11 +99,11 @@ namespace PacketTypes | ||||
|             DataOffset = 3; | ||||
|         } | ||||
|  | ||||
|         uint16_t getAddrFrom() { return _getAddrFrom(this); }; | ||||
|         uint8_t getCustomByte() { return packInfo->buffer[DataOffset]; }; | ||||
|        inline uint16_t getAddrFrom() { return _getAddrFrom(this); }; | ||||
|        inline uint8_t getCustomByte() { return packInfo->buffer[DataOffset]; }; | ||||
|  | ||||
|     private: | ||||
|         bool checkAddress() override { return true; } | ||||
|         bool checkAddress() override; | ||||
|     }; | ||||
|  | ||||
|     class Request : public BasePack | ||||
| @ -194,168 +117,11 @@ namespace PacketTypes | ||||
|             DataOffset = 3; | ||||
|         } | ||||
|  | ||||
|         uint16_t getAddrFrom() { return _getAddrFrom(this); }; | ||||
|         uint16_t getAddrTo() { return _getAddrTo(this); }; | ||||
|         inline uint16_t getAddrFrom() { return _getAddrFrom(this); }; | ||||
|         inline uint16_t getAddrTo() { return _getAddrTo(this); }; | ||||
|  | ||||
|     private: | ||||
|         bool checkAddress() override | ||||
|         { | ||||
|             bool ret; | ||||
|             IR_FOX::checkAddressRuleApply(getAddrTo(), this->id, ret); | ||||
|             return ret; | ||||
|         } | ||||
|         bool checkAddress() override; | ||||
|     }; | ||||
|  | ||||
| } | ||||
|  | ||||
| // class IOffsets { | ||||
| // protected: | ||||
| //     uint8_t msgOffset; | ||||
| //     uint8_t addressFromOffset; | ||||
| //     uint8_t addressToOffset; | ||||
| //     uint8_t DataOffset; | ||||
| // }; | ||||
|  | ||||
| // class IPackInfo { | ||||
| // public: | ||||
| //     IR_FOX::PackInfo* packInfo; | ||||
| // }; | ||||
|  | ||||
| // class IBaseEmptyPack : virtual public IOffsets, virtual public IPackInfo { | ||||
| // }; | ||||
|  | ||||
| // class IR_Decoder; | ||||
| // class IEmptyPack : virtual protected IBaseEmptyPack, virtual public IR_FOX { | ||||
| //     friend IR_Decoder; | ||||
| //     bool isAvailable; | ||||
| //     bool isRawAvailable; | ||||
| //     bool isNeedAccept; | ||||
|  | ||||
| // protected: | ||||
| //     uint16_t id; | ||||
|  | ||||
| //     virtual bool checkAddress() {}; | ||||
|  | ||||
| //     virtual void set(IR_FOX::PackInfo* packInfo, uint16_t id, bool isNeedAccept = false) { | ||||
| //         IBaseEmptyPack::IPackInfo::packInfo = packInfo; | ||||
| //         this->id = id; | ||||
| //         this->isNeedAccept = isNeedAccept; | ||||
|  | ||||
| //         if (isAvailable = checkAddress()) { | ||||
| //             isAvailable = true; | ||||
| //             isRawAvailable = true; | ||||
| //             Serial.print("  OK  "); | ||||
| //         } else { | ||||
| //             isRawAvailable = true; | ||||
| //             Serial.print("  NOT-OK  "); | ||||
| //         } | ||||
| //     } | ||||
|  | ||||
| // public: | ||||
| //     virtual bool available() { if (isAvailable) { isAvailable = false; isRawAvailable = false; return true; } else { return false; } }; | ||||
| //     virtual bool availableRaw() { if (isRawAvailable) { isRawAvailable = false; return true; } else { return false; } }; | ||||
| //     virtual uint8_t getMsgInfo() { return packInfo->buffer[0] & IR_MASK_MSG_INFO; }; | ||||
| //     virtual uint8_t getMsgType() { return (packInfo->buffer[0] >> 5) & IR_MASK_MSG_TYPE; }; | ||||
| //     virtual uint8_t getMsgRAW() { return packInfo->buffer[0]; }; | ||||
| //     virtual uint16_t getErrorCount() { return packInfo->err.all(); }; | ||||
| //     virtual uint8_t getErrorLowSignal() { return packInfo->err.lowSignal; }; | ||||
| //     virtual uint8_t getErrorHighSignal() { return packInfo->err.highSignal; }; | ||||
| //     virtual uint8_t getErrorOther() { return packInfo->err.other; }; | ||||
| //     virtual uint16_t getTunerTime() { return packInfo->rTime; }; | ||||
| // }; | ||||
|  | ||||
| // class IHasAddresFrom : virtual protected IBaseEmptyPack { | ||||
| // public: | ||||
| //     virtual uint16_t getAddrFrom() { return (packInfo->buffer[addressFromOffset] << 8) | packInfo->buffer[addressFromOffset + 1]; }; | ||||
| // }; | ||||
|  | ||||
| // class IHasAddresTo : virtual protected IBaseEmptyPack { | ||||
| // public: | ||||
| //     virtual uint16_t getAddrTo() { return (packInfo->buffer[addressToOffset] << 8) | packInfo->buffer[addressToOffset + 1]; }; | ||||
| // }; | ||||
|  | ||||
| // class IHasAddresData : virtual protected IBaseEmptyPack { | ||||
| // public: | ||||
| //     virtual uint8_t getDataSize() { return packInfo->packSize - crcBytes - DataOffset; }; | ||||
| //     virtual uint8_t* getDataPrt() { return packInfo->buffer + DataOffset; }; | ||||
| //     virtual uint8_t getDataRawSize() { return packInfo->packSize; }; | ||||
| //     virtual uint8_t* getDataRawPtr() { return packInfo->buffer; }; | ||||
| // }; | ||||
|  | ||||
| // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| // class Data : | ||||
| //     virtual public IEmptyPack, | ||||
| //     virtual public IHasAddresFrom, | ||||
| //     virtual public IHasAddresTo, | ||||
| //     virtual public IHasAddresData { | ||||
| // public: | ||||
| //     Data() { | ||||
| //         msgOffset = 0; | ||||
| //         addressFromOffset = 1; | ||||
| //         addressToOffset = 3; | ||||
| //         DataOffset = 5; | ||||
| //     } | ||||
| // protected: | ||||
| //     bool checkAddress() override { | ||||
| //         bool ret; | ||||
| //         checkAddressRuleApply(getAddrTo(), this->id, ret); | ||||
| //         return ret; | ||||
| //     } | ||||
| // }; | ||||
|  | ||||
| // class DataBack : | ||||
| //     virtual public IEmptyPack, | ||||
| //     virtual public IHasAddresFrom, | ||||
| //     virtual public IHasAddresData { | ||||
| // public: | ||||
| //     DataBack() { | ||||
| //         msgOffset = 0; | ||||
| //         addressFromOffset = 1; | ||||
| //         addressToOffset = 3; | ||||
| //         DataOffset = 3; | ||||
| //     } | ||||
| // protected: | ||||
| //     bool checkAddress() override { | ||||
| //         bool ret; | ||||
| //         if (getMsgType() == IR_MSG_BACK_TO) { | ||||
| //             DataOffset = 5; | ||||
| //             checkAddressRuleApply((packInfo->buffer[addressToOffset] << 8) | packInfo->buffer[addressToOffset + 1], this->id, ret); | ||||
| //         } else { | ||||
| //             DataOffset = 3; | ||||
| //             ret = true; | ||||
| //         } | ||||
| //         return ret; | ||||
| //     } | ||||
| // }; | ||||
|  | ||||
| // class Request : | ||||
| //     virtual public IEmptyPack, | ||||
| //     virtual public IHasAddresFrom, | ||||
| //     virtual public IHasAddresTo { | ||||
| // public: | ||||
| //     Request() { | ||||
| //         msgOffset = 0; | ||||
| //         addressFromOffset = 1; | ||||
| //         addressToOffset = 3; | ||||
| //         DataOffset = 3; | ||||
| //     } | ||||
| // protected: | ||||
| //     bool checkAddress() override { | ||||
| //         bool ret; | ||||
| //         checkAddressRuleApply(getAddrTo(), this->id, ret); | ||||
| //         return ret; | ||||
| //     } | ||||
| // }; | ||||
|  | ||||
| // class Accept : | ||||
| //     virtual public IEmptyPack, | ||||
| //     virtual public IHasAddresFrom { | ||||
| // public: | ||||
| //     Accept() { | ||||
| //         msgOffset = 0; | ||||
| //         addressFromOffset = 1; | ||||
| //         DataOffset = 1; | ||||
| //     } | ||||
| // protected: | ||||
| // }; | ||||
|  | ||||
							
								
								
									
										39
									
								
								RingBuffer.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								RingBuffer.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,39 @@ | ||||
| #pragma once | ||||
| #include "Arduino.h" | ||||
| template <typename T, unsigned int BufferSize> | ||||
| class RingBuffer { | ||||
| public: | ||||
|     RingBuffer() : start(0), end(0) {} | ||||
|  | ||||
|     bool isFull() const { | ||||
|         return ((end + 1) % BufferSize) == start; | ||||
|     } | ||||
|  | ||||
|     bool isEmpty() const { | ||||
|         return start == end; | ||||
|     } | ||||
|  | ||||
|     void push(T element) { | ||||
|         noInterrupts(); | ||||
|         if (!isFull()) { | ||||
|             data[end] = element; | ||||
|             end = (end + 1) % BufferSize; | ||||
|         } | ||||
|         interrupts(); | ||||
|     } | ||||
|  | ||||
|     T* pop() { | ||||
|         noInterrupts(); | ||||
|         T* value = nullptr; | ||||
|         if (!isEmpty()) { | ||||
|             value = &data[start]; | ||||
|             start = (start + 1) % BufferSize; | ||||
|         } | ||||
|         interrupts(); | ||||
|         return value; | ||||
|     } | ||||
|  | ||||
| private: | ||||
|     T data[BufferSize]; | ||||
|     unsigned int start, end; | ||||
| }; | ||||
		Reference in New Issue
	
	Block a user
	