mirror of
				https://github.com/Show-maket/IR-protocol.git
				synced 2025-10-31 02:52:36 +00:00 
			
		
		
		
	Merge pull request #4 from Show-maket:STM32_BRUTEFORCE_FIXHACK
STM32 works
This commit is contained in:
		
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1 +1,5 @@ | |||||||
| .vscode/* | .vscode/* | ||||||
|  | bin/* | ||||||
|  | !.vscode/arduino.json | ||||||
|  | !.vscode/launch.json | ||||||
|  | log/* | ||||||
							
								
								
									
										8
									
								
								.vscode/arduino.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								.vscode/arduino.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | |||||||
|  | { | ||||||
|  |     "configuration": "pnum=BLUEPILL_F103C8,upload_method=swdMethod,xserial=none,usb=CDCgen,xusb=FS,opt=osstd,dbg=none,rtlib=nano", | ||||||
|  |     "board": "STMicroelectronics:stm32:GenF1", | ||||||
|  |     "port": "COM17", | ||||||
|  |     "output": "bin", | ||||||
|  |     "prebuild": "if exist bin rd /s /q bin", | ||||||
|  |     "sketch": "IR-protocol.ino" | ||||||
|  | } | ||||||
							
								
								
									
										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" | ||||||
|  |       } | ||||||
|  |     ] | ||||||
|  |   } | ||||||
| @ -72,7 +72,6 @@ uint8_t data4[] = {42, 127, 137, 255}; | |||||||
|  |  | ||||||
| uint32_t loopTimer; | uint32_t loopTimer; | ||||||
| uint8_t sig = 0; | uint8_t sig = 0; | ||||||
|  |  | ||||||
| uint16_t targetAddr = IR_Broadcast; | uint16_t targetAddr = IR_Broadcast; | ||||||
| Timer t1(500, millis, []() | Timer t1(500, millis, []() | ||||||
|          { |          { | ||||||
| @ -157,17 +156,24 @@ Timer t1(500, millis, []() | |||||||
|              // encBackward.sendData(IR_Broadcast, data2); |              // encBackward.sendData(IR_Broadcast, data2); | ||||||
|              // encTree.sendData(IR_Broadcast, rawData3); |              // encTree.sendData(IR_Broadcast, rawData3); | ||||||
|          }); |          }); | ||||||
| Timer t2(500, millis, []() | // Timer t2(50, millis, []() | ||||||
|          { digitalToggle(LED_BUILTIN); }); | //          { digitalToggle(LED_BUILTIN); }); | ||||||
|  |  | ||||||
| Timer signalDetectTimer; | Timer signalDetectTimer; | ||||||
| ///////////////////////////////////////////////////////////////////// | ///////////////////////////////////////////////////////////////////// | ||||||
|  | HardwareTimer IR_Timer(TIM3); | ||||||
|  | HardwareTimer MicrosTimer(TIM1); | ||||||
|  |  | ||||||
|  | void MicrosTimerISR(){ | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
| void setup() | void setup() | ||||||
| { | { | ||||||
|     // disableDebugPorts(); |     // MicrosTimer.setOve | ||||||
|  |  | ||||||
|     Timer3.setPeriod(1000000U / carrierFrec / 2); |     IR_Timer.setOverflow(carrierFrec*2, HERTZ_FORMAT); | ||||||
|     // Timer3.attachCompare1Interrupt(EncoderISR); |     IR_Timer.attachInterrupt(1, EncoderISR); | ||||||
|      |      | ||||||
|  |  | ||||||
|     Serial.begin(SERIAL_SPEED); |     Serial.begin(SERIAL_SPEED); | ||||||
| @ -244,6 +250,7 @@ void status(IR_Decoder &dec) | |||||||
|     if (dec.gotData.available()) |     if (dec.gotData.available()) | ||||||
|     { |     { | ||||||
|         detectSignal(); |         detectSignal(); | ||||||
|  |         Serial.println(micros()); | ||||||
|         String str; |         String str; | ||||||
|         if (/* dec.gotData.getDataPrt()[1] */ 1) |         if (/* dec.gotData.getDataPrt()[1] */ 1) | ||||||
|         { |         { | ||||||
| @ -275,7 +282,7 @@ void status(IR_Decoder &dec) | |||||||
|             // str += ("  CRC CALC: "); str += (dec.gotData.getCrcCALC()); str += "\n"; |             // str += ("  CRC CALC: "); str += (dec.gotData.getCrcCALC()); str += "\n"; | ||||||
|             str += "\n"; |             str += "\n"; | ||||||
|  |  | ||||||
|             for (size_t i = 0; i < min(10, dec.gotData.getDataSize()); i++) |             for (size_t i = 0; i < min(uint8_t(10), dec.gotData.getDataSize()); i++) | ||||||
|             { |             { | ||||||
|                 switch (i) |                 switch (i) | ||||||
|                 { |                 { | ||||||
| @ -347,7 +354,7 @@ void status(IR_Decoder &dec) | |||||||
|             // str += ("  CRC CALC: "); str += (dec.gotBackData.getCrcCALC()); str += "\n"; |             // str += ("  CRC CALC: "); str += (dec.gotBackData.getCrcCALC()); str += "\n"; | ||||||
|             str += "\n"; |             str += "\n"; | ||||||
|  |  | ||||||
|             for (size_t i = 0; i < min(10, dec.gotBackData.getDataSize()); i++) |             for (size_t i = 0; i < min(uint8_t(10), dec.gotBackData.getDataSize()); i++) | ||||||
|             { |             { | ||||||
|                 switch (i) |                 switch (i) | ||||||
|                 { |                 { | ||||||
|  | |||||||
| @ -15,55 +15,47 @@ IR_DecoderRaw::IR_DecoderRaw(const uint8_t isrPin, uint16_t addr, IR_Encoder *en | |||||||
|     pinMode(wrLow, OUTPUT); |     pinMode(wrLow, OUTPUT); | ||||||
|     pinMode(writeOp, OUTPUT); |     pinMode(writeOp, OUTPUT); | ||||||
|     pinMode(errOut, OUTPUT); |     pinMode(errOut, OUTPUT); | ||||||
|  |     pinMode(up, OUTPUT); | ||||||
|  |     pinMode(down, OUTPUT); | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
|  |  | ||||||
| //////////////////////////////////// isr /////////////////////////////////////////// | //////////////////////////////////// isr /////////////////////////////////////////// | ||||||
|  | volatile uint32_t time_; | ||||||
|  |  | ||||||
| void IR_DecoderRaw::isr() | void IR_DecoderRaw::isr() | ||||||
| { | { | ||||||
|     if (isPairSending) |     noInterrupts(); | ||||||
|         return; |     // time_ = HAL_GetTick() * 1000 + ((SysTick->LOAD + 1 - SysTick->VAL) * 1000) / SysTick->LOAD + 1; | ||||||
|  |     time_ = micros(); | ||||||
|     subBuffer[currentSubBufferIndex].next = nullptr; |     interrupts(); | ||||||
|     subBuffer[currentSubBufferIndex].dir = digitalRead(isrPin); |     if (time_ < oldTime) | ||||||
|     subBuffer[currentSubBufferIndex].time = micros(); |  | ||||||
|  |  | ||||||
|     if (firstUnHandledFront == nullptr) |  | ||||||
|     { |     { | ||||||
|         firstUnHandledFront = &subBuffer[currentSubBufferIndex]; // Если нет необработанных данных - добавляем их | #ifdef IRDEBUG | ||||||
|         isSubBufferOverflow = false; |         Serial.print("\n"); | ||||||
|     } |         Serial.print("count:         "); | ||||||
|     else |         Serial.println(wrongCounter++); | ||||||
|     { |         Serial.print("time:                 "); | ||||||
|         if (firstUnHandledFront == &subBuffer[currentSubBufferIndex]) |         Serial.println(time_); | ||||||
|         { // Если контроллер не успел обработать новый сигнал, принудительно пропускаем его |         Serial.print("oldTime:              "); | ||||||
|             firstUnHandledFront = firstUnHandledFront->next; |         Serial.println(oldTime); | ||||||
|             isSubBufferOverflow = true; |         Serial.print("sub:                        "); | ||||||
|  |         Serial.println(max((uint32_t)time_, oldTime) - min((uint32_t)time_, oldTime)); | ||||||
| #ifdef IRDEBUG_INFO |  | ||||||
|             // Serial.println(); |  | ||||||
|             Serial.println(" ISR BUFFER OVERFLOW "); |  | ||||||
| // Serial.println(); |  | ||||||
| #endif | #endif | ||||||
|  |         time_ += 1000; | ||||||
|     } |     } | ||||||
|     } |     oldTime = time_; | ||||||
|  |  | ||||||
|     if (lastFront == nullptr) |     FrontStorage edge; | ||||||
|     { |     edge.dir = digitalRead(isrPin); | ||||||
|         lastFront = &subBuffer[currentSubBufferIndex]; |     edge.time = time_; | ||||||
|     } |  | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         lastFront->next = &subBuffer[currentSubBufferIndex]; |  | ||||||
|         lastFront = &subBuffer[currentSubBufferIndex]; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     currentSubBufferIndex == (subBufferSize - 1) ? currentSubBufferIndex = 0 : currentSubBufferIndex++; // Закольцовка буффера |     subBuffer.push(edge); | ||||||
| } | } | ||||||
|  |  | ||||||
| //////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////// | ||||||
|  |  | ||||||
|  | uint32_t wrCounter; | ||||||
| void IR_DecoderRaw::firstRX() | void IR_DecoderRaw::firstRX() | ||||||
| { | { | ||||||
|  |  | ||||||
| @ -86,6 +78,8 @@ void IR_DecoderRaw::firstRX() | |||||||
|     isPreamb = true; |     isPreamb = true; | ||||||
|     riseSyncTime = bitTime /* 1100 */; |     riseSyncTime = bitTime /* 1100 */; | ||||||
|  |  | ||||||
|  |     wrCounter = 0; | ||||||
|  |  | ||||||
|     memset(dataBuffer, 0x00, dataByteSizeMax); |     memset(dataBuffer, 0x00, dataByteSizeMax); | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -98,56 +92,116 @@ void IR_DecoderRaw::listenStart() | |||||||
|         firstRX(); |         firstRX(); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| void IR_DecoderRaw::tick() | void IR_DecoderRaw::tick() | ||||||
| { | { | ||||||
|     FrontStorage currentFront; |     FrontStorage currentFront; | ||||||
|     noInterrupts(); |     noInterrupts(); | ||||||
|     listenStart(); |     listenStart(); | ||||||
|     if (firstUnHandledFront == nullptr) |     FrontStorage *currentFrontPtr; | ||||||
|  |     currentFrontPtr = subBuffer.pop(); | ||||||
|  |     if (currentFrontPtr == nullptr) | ||||||
|     { |     { | ||||||
|         isSubBufferOverflow = false; |         isSubBufferOverflow = false; | ||||||
|         interrupts(); |         interrupts(); | ||||||
|         return; |         return; | ||||||
|     } // Если данных нет - ничего не делаем |     } // Если данных нет - ничего не делаем | ||||||
|     currentFront = *((FrontStorage *)firstUnHandledFront); // найти следующий необработанный фронт/спад |     currentFront = *currentFrontPtr; | ||||||
|     interrupts(); |     interrupts(); | ||||||
|     if (currentFront.next == nullptr) |  | ||||||
|     { |  | ||||||
|         isRecive = false; |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
|     //////////////////////////////////////////////////////////////////////////////////////////////////////////// |     //////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||||
|  |  | ||||||
|  |     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) |     if (currentFront.time > prevRise && currentFront.time - prevRise > IR_timeout * 2 && !isRecive) | ||||||
|     { // первый |     { // первый | ||||||
|         preambFrontCounter = preambFronts - 1U; | #ifdef IRDEBUG | ||||||
|  |         errPulse(up, 50); | ||||||
|         if (!currentFront.dir) |         errPulse(down, 50); | ||||||
|         { |         errPulse(up, 150); | ||||||
| #ifdef IRDEBUG_INFO |         errPulse(down, 150); | ||||||
| // 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); |  | ||||||
| #endif | #endif | ||||||
|  |         preambFrontCounter = preambFronts - 1U; | ||||||
|  |         isPreamb = true; | ||||||
|  |  | ||||||
|         isRecive = true; |         isRecive = true; | ||||||
|         isWrongPack = false; |         isWrongPack = false; | ||||||
|     } |     } | ||||||
|     } |  | ||||||
|  |     //------------------------------------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|     if (preambFrontCounter) |     if (preambFrontCounter) | ||||||
|     { // в преамбуле |     { // в преамбуле | ||||||
|         uint32_t risePeriod; | #ifdef IRDEBUG | ||||||
|         risePeriod = currentFront.time - prevRise; |         Serial.print("risePeriod:           "); | ||||||
|  |         Serial.println(risePeriod); | ||||||
|  | #endif | ||||||
|         if (currentFront.dir && risePeriod < IR_timeout) |         if (currentFront.dir && risePeriod < IR_timeout) | ||||||
|         { //  __/``` ↑ и мы в внутри пакета |         { //  __/``` ↑ и мы в внутри пакета | ||||||
|  |  | ||||||
|             if (risePeriod < riseTimeMin << 1) |             if (risePeriod < riseTimeMin / 2) | ||||||
|             { // fix рваной единицы |             { // fix рваной единицы | ||||||
|                 preambFrontCounter += 2; |                 preambFrontCounter += 2; | ||||||
|                 errors.other++; |                 errors.other++; | ||||||
|  | #ifdef IRDEBUG | ||||||
|  |                 errPulse(down, 350); | ||||||
|  | #endif | ||||||
|             } |             } | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
| @ -168,42 +222,64 @@ void IR_DecoderRaw::tick() | |||||||
|         if (isPreamb) |         if (isPreamb) | ||||||
|         { // первый фронт после |         { // первый фронт после | ||||||
|           // gotTune.set(riseSyncTime); |           // gotTune.set(riseSyncTime); | ||||||
|         } |  | ||||||
|             isPreamb = false; |             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) |     if (currentFront.dir) | ||||||
|     { // Если __/``` ↑ |     { // Если __/``` ↑ | ||||||
|  |         highCount = 0; | ||||||
|         uint16_t risePeriod = currentFront.time - prevRise; |         lowCount = 0; | ||||||
|         uint16_t highTime = currentFront.time - prevFall; |         allCount = 0; | ||||||
|         uint16_t lowTime = prevFall - prevRise; |  | ||||||
|  |  | ||||||
|         int8_t highCount = 0; |  | ||||||
|         int8_t lowCount = 0; |  | ||||||
|         int8_t allCount = 0; |  | ||||||
|         bool invertErr = false; |         bool invertErr = false; | ||||||
|  | #ifdef IRDEBUG | ||||||
|  |         Serial.print("\n"); | ||||||
|  |  | ||||||
|         if (!isPreamb) |         Serial.print("wrCounter:    "); | ||||||
|         { |         Serial.println(wrCounter++); | ||||||
|             if (risePeriod < IR_timeout && !isBufferOverflow && risePeriod > riseTimeMin && !isWrongPack) |  | ||||||
|             { |         Serial.print("risePeriod:           "); | ||||||
|                 // Мы в пределах таймаута и буффер не переполнен и fix дроблёных единиц |         Serial.println(risePeriod); | ||||||
|  |  | ||||||
|  |         Serial.print("highTime:        "); | ||||||
|  |         Serial.println(highTime); | ||||||
|  |  | ||||||
|  |         Serial.print("lowTime:         "); | ||||||
|  |         Serial.println(lowTime); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|         if (aroundRise(risePeriod)) |         if (aroundRise(risePeriod)) | ||||||
|         { // тактирование есть, сигнал хороший - без ошибок(?) |         { // тактирование есть, сигнал хороший - без ошибок(?) | ||||||
|  |  | ||||||
|                     if (highTime > riseTimeMin / 2U) |             if (highTime > lowTime) | ||||||
|             { // 1 |             { // 1 | ||||||
| #ifdef IRDEBUG | #ifdef IRDEBUG | ||||||
|                         digitalWrite(wrHigh, 1); |                 errPulse(wrHigh, 1); | ||||||
| #endif | #endif | ||||||
|                 writeToBuffer(HIGH); |                 writeToBuffer(HIGH); | ||||||
|             } |             } | ||||||
|             else |             else | ||||||
|             { // 0 |             { // 0 | ||||||
| #ifdef IRDEBUG | #ifdef IRDEBUG | ||||||
|                         digitalWrite(wrLow, 1); |                 errPulse(wrLow, 1); | ||||||
| #endif | #endif | ||||||
|                 writeToBuffer(LOW); |                 writeToBuffer(LOW); | ||||||
|             } |             } | ||||||
| @ -219,7 +295,7 @@ void IR_DecoderRaw::tick() | |||||||
|                 highCount++; |                 highCount++; | ||||||
|                 errors.other++; |                 errors.other++; | ||||||
| #ifdef IRDEBUG | #ifdef IRDEBUG | ||||||
|                         errPulse(errOut, 2); |                 errPulse(up, 50); | ||||||
| #endif | #endif | ||||||
|             } |             } | ||||||
|  |  | ||||||
| @ -230,7 +306,10 @@ void IR_DecoderRaw::tick() | |||||||
|                     lowCount = allCount - highCount; |                     lowCount = allCount - highCount; | ||||||
|                     errors.lowSignal += lowCount; |                     errors.lowSignal += lowCount; | ||||||
| #ifdef IRDEBUG | #ifdef IRDEBUG | ||||||
|                             errPulse(errOut, 3); |                     // errPulse(errOut, 3); | ||||||
|  |                     errPulse(down, 40); | ||||||
|  |                     errPulse(up, 10); | ||||||
|  |                     errPulse(down, 40); | ||||||
| #endif | #endif | ||||||
|                 } |                 } | ||||||
|                 else if (lowCount < highCount) |                 else if (lowCount < highCount) | ||||||
| @ -238,7 +317,10 @@ void IR_DecoderRaw::tick() | |||||||
|                     highCount = allCount - lowCount; |                     highCount = allCount - lowCount; | ||||||
|                     errors.highSignal += highCount; |                     errors.highSignal += highCount; | ||||||
| #ifdef IRDEBUG | #ifdef IRDEBUG | ||||||
|                             errPulse(errOut, 4); |                     errPulse(down, 10); | ||||||
|  |                     errPulse(up, 40); | ||||||
|  |                     errPulse(down, 10); | ||||||
|  | // errPulse(errOut, 4); | ||||||
| #endif | #endif | ||||||
|                     // неизвестный случай Инверсит след бит или соседние |                     // неизвестный случай Инверсит след бит или соседние | ||||||
|                     // Очень редко |                     // Очень редко | ||||||
| @ -246,6 +328,11 @@ void IR_DecoderRaw::tick() | |||||||
|                 } |                 } | ||||||
|                 else if (lowCount == highCount) |                 else if (lowCount == highCount) | ||||||
|                 { |                 { | ||||||
|  | #ifdef IRDEBUG | ||||||
|  |                     errPulse(down, 40); | ||||||
|  |                     errPulse(up, 40); | ||||||
|  |                     errPulse(down, 40); | ||||||
|  | #endif | ||||||
|                     invertErr = true; |                     invertErr = true; | ||||||
|                     // Serial.print("..."); |                     // Serial.print("..."); | ||||||
|                     errors.other += allCount; |                     errors.other += allCount; | ||||||
| @ -264,25 +351,23 @@ void IR_DecoderRaw::tick() | |||||||
|                 errors.lowSignal += lowCount; |                 errors.lowSignal += lowCount; | ||||||
|             } |             } | ||||||
|  |  | ||||||
| #ifdef IRDEBUG |             // errPulse(errOut, 1); | ||||||
|                     errPulse(errOut, 1); |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
|             for (int8_t i = 0; i < lowCount && 8 - i; i++) |             for (int8_t i = 0; i < lowCount && 8 - i; i++) | ||||||
|             { // отправка LOW битов, если есть |             { // отправка LOW битов, если есть | ||||||
|                 if (i == lowCount - 1 && invertErr) |                 if (i == lowCount - 1 && invertErr) | ||||||
|                 { |                 { | ||||||
|                     invertErr = false; |                     invertErr = false; | ||||||
|                             writeToBuffer(!LOW); |                     writeToBuffer(HIGH); | ||||||
| #ifdef IRDEBUG | #ifdef IRDEBUG | ||||||
|                             digitalWrite(wrLow, 1); |                     errPulse(wrHigh, 1); | ||||||
| #endif | #endif | ||||||
|                 } |                 } | ||||||
|                 else |                 else | ||||||
|                 { |                 { | ||||||
|                     writeToBuffer(LOW); |                     writeToBuffer(LOW); | ||||||
| #ifdef IRDEBUG | #ifdef IRDEBUG | ||||||
|                             digitalWrite(wrLow, 1); |                     errPulse(wrLow, 1); | ||||||
| #endif | #endif | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| @ -292,70 +377,27 @@ void IR_DecoderRaw::tick() | |||||||
|                 if (i == highCount - 1 && invertErr) |                 if (i == highCount - 1 && invertErr) | ||||||
|                 { |                 { | ||||||
|                     invertErr = false; |                     invertErr = false; | ||||||
|                             writeToBuffer(!HIGH); |                     writeToBuffer(LOW); | ||||||
| #ifdef IRDEBUG | #ifdef IRDEBUG | ||||||
|                             digitalWrite(wrLow, 1); |                     errPulse(wrLow, 1); | ||||||
| #endif | #endif | ||||||
|                 } |                 } | ||||||
|                 else |                 else | ||||||
|                 { |                 { | ||||||
|                     writeToBuffer(HIGH); |                     writeToBuffer(HIGH); | ||||||
| #ifdef IRDEBUG | #ifdef IRDEBUG | ||||||
|                             digitalWrite(wrHigh, 1); |                     errPulse(wrHigh, 1); | ||||||
| #endif | #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 |     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 |  | ||||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||||
|     // noInterrupts(); | END:; | ||||||
|     if (firstUnHandledFront != nullptr) |  | ||||||
|     { |  | ||||||
|         firstUnHandledFront = firstUnHandledFront->next; // переместить флаг на следующий элемент для обработки (next or nullptr) |  | ||||||
|     } |  | ||||||
|     // interrupts(); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void IR_DecoderRaw::writeToBuffer(bool bit) | void IR_DecoderRaw::writeToBuffer(bool bit) | ||||||
| @ -484,7 +526,7 @@ void IR_DecoderRaw::writeToBuffer(bool bit) | |||||||
|         if (packSize && (i_dataBuffer == packSize * bitPerByte)) |         if (packSize && (i_dataBuffer == packSize * bitPerByte)) | ||||||
|         { // Конец |         { // Конец | ||||||
| #ifdef IRDEBUG_INFO | #ifdef IRDEBUG_INFO | ||||||
|             Serial.print("   END DATA   "); |             Serial.print("   END DATA   " + crcCheck(packSize - crcBytes, crcValue) ? "OK   " : "ERR  "); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|             packInfo.buffer = dataBuffer; |             packInfo.buffer = dataBuffer; | ||||||
| @ -495,6 +537,34 @@ void IR_DecoderRaw::writeToBuffer(bool bit) | |||||||
|  |  | ||||||
|             isRecive = false; |             isRecive = false; | ||||||
|             isAvailable = crcCheck(packSize - crcBytes, crcValue); |             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,7 +1,8 @@ | |||||||
| #pragma once | #pragma once | ||||||
| #include "IR_config.h" | #include "IR_config.h" | ||||||
|  | #include "RingBuffer.h" | ||||||
|  |  | ||||||
| #define IRDEBUG | // #define IRDEBUG | ||||||
|  |  | ||||||
| #ifdef IRDEBUG | #ifdef IRDEBUG | ||||||
| #define wrHigh PA1  // Запись HIGH инициирована                     // green | #define wrHigh PA1  // Запись HIGH инициирована                     // green | ||||||
| @ -10,7 +11,11 @@ | |||||||
| // Исправленные ошибки                                              // purle | // Исправленные ошибки                                              // purle | ||||||
| // 1 пульс: fix | // 1 пульс: fix | ||||||
| #define errOut PA4 | #define errOut PA4 | ||||||
|  | #define up PA3 | ||||||
|  | #define down PA2 | ||||||
| #endif | #endif | ||||||
|  | #define up PA3 | ||||||
|  | #define down PA2 | ||||||
|  |  | ||||||
| ///////////////////////////////////////////////////////////////////////////////////////////////// | ///////////////////////////////////////////////////////////////////////////////////////////////// | ||||||
|  |  | ||||||
| @ -54,6 +59,7 @@ public: | |||||||
|  |  | ||||||
|     void isr();  // Функция прерывания |     void isr();  // Функция прерывания | ||||||
|     void tick(); // Обработка приёмника, необходима для работы |     void tick(); // Обработка приёмника, необходима для работы | ||||||
|  |     void tickOld(); | ||||||
|  |  | ||||||
|     bool isOverflow() { return isBufferOverflow; }; // Буффер переполнился |     bool isOverflow() { return isBufferOverflow; }; // Буффер переполнился | ||||||
|     bool isSubOverflow() |     bool isSubOverflow() | ||||||
| @ -82,20 +88,35 @@ private: | |||||||
|     uint16_t riseSyncTime = bitTime; // Подстраиваемое время бита в мкс |     uint16_t riseSyncTime = bitTime; // Подстраиваемое время бита в мкс | ||||||
|  |  | ||||||
|     //////////////////////////////////////////////////////////////////////// |     //////////////////////////////////////////////////////////////////////// | ||||||
|     volatile uint8_t currentSubBufferIndex; // Счетчик текущей позиции во вспомогательном буфере фронтов/спадов |     volatile uint32_t currentSubBufferIndex; // Счетчик текущей позиции во вспомогательном буфере фронтов/спадов | ||||||
|  |  | ||||||
|     struct FrontStorage |     struct FrontStorage | ||||||
|     {                               // Структура для хранения времени и направления фронта/спада |     {                               // Структура для хранения времени и направления фронта/спада | ||||||
|         volatile uint32_t time = 0; // Время |         volatile uint32_t time = 0; // Время | ||||||
|         volatile bool dir = false;  // Направление (true = ↑; false = ↓) |         volatile bool dir = false;  // Направление (true = ↑; false = ↓) | ||||||
|         volatile FrontStorage *next = nullptr; // Указатель на следующий связанный фронт/спад, или nullptr если конец |         // volatile FrontStorage *next = nullptr; // Указатель на следующий связанный фронт/спад, или nullptr если конец | ||||||
|     }; |     }; | ||||||
|     volatile FrontStorage *lastFront = nullptr;           // Указатель последнего фронта/спада |     volatile FrontStorage *lastFront = nullptr;           // Указатель последнего фронта/спада | ||||||
|     volatile FrontStorage *firstUnHandledFront = nullptr; // Указатель первого необработанного фронта/спада |     volatile FrontStorage *firstUnHandledFront = nullptr; // Указатель первого необработанного фронта/спада | ||||||
|     volatile FrontStorage subBuffer[subBufferSize];       // вспомогательный буфер для хранения необработанных фронтов/спадов |     // volatile FrontStorage subBuffer[subBufferSize];       // вспомогательный буфер для хранения необработанных фронтов/спадов | ||||||
|  |  | ||||||
|  |     RingBuffer<FrontStorage, subBufferSize> subBuffer; | ||||||
|  |  | ||||||
|     //////////////////////////////////////////////////////////////////////// |     //////////////////////////////////////////////////////////////////////// | ||||||
|     uint8_t dataBuffer[dataByteSizeMax]{0};                           // Буффер данных |     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;     // Счётчик ошибок |     uint16_t errorCounter = 0;     // Счётчик ошибок | ||||||
|     int8_t preambFrontCounter = 0; // Счётчик __/``` ↑ преамбулы |     int8_t preambFrontCounter = 0; // Счётчик __/``` ↑ преамбулы | ||||||
|     int16_t bufBitPos = 0;         // Позиция для записи бита в буффер |     int16_t bufBitPos = 0;         // Позиция для записи бита в буффер | ||||||
| @ -129,7 +150,7 @@ private: | |||||||
|     /// @return Результат |     /// @return Результат | ||||||
|     uint16_t ceil_div(uint16_t val, uint16_t divider); |     uint16_t ceil_div(uint16_t val, uint16_t divider); | ||||||
|  |  | ||||||
| #ifdef IRDEBUG | #if true //def IRDEBUG | ||||||
|     inline void errPulse(uint8_t pin, uint8_t count); |     inline void errPulse(uint8_t pin, uint8_t count); | ||||||
|     inline void infoPulse(uint8_t pin, uint8_t count); |     inline void infoPulse(uint8_t pin, uint8_t count); | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -160,7 +160,7 @@ void IR_Encoder::_sendBack(bool isAdressed, uint16_t addrTo, uint8_t *data, uint | |||||||
|     memset(sendBuffer, 0x00, dataByteSizeMax); |     memset(sendBuffer, 0x00, dataByteSizeMax); | ||||||
|     uint8_t dataStart = msgBytes + addrBytes + (isAdressed ? addrBytes : 0); |     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 = |     uint8_t msgType = | ||||||
|         ((isAdressed ? IR_MSG_BACK_TO : IR_MSG_BACK) << 5) | ((packSize) & (IR_MASK_MSG_INFO >> 1)); |         ((isAdressed ? IR_MSG_BACK_TO : IR_MSG_BACK) << 5) | ((packSize) & (IR_MASK_MSG_INFO >> 1)); | ||||||
|  |  | ||||||
| @ -398,8 +398,8 @@ void IR_Encoder::send_EMPTY(uint8_t count) | |||||||
| } | } | ||||||
|  |  | ||||||
| uint8_t* IR_Encoder::bitHigh = new uint8_t[2]{ | uint8_t* IR_Encoder::bitHigh = new uint8_t[2]{ | ||||||
|         (bitPauseTakts * 2) * 2 - 1, |         (bitPauseTakts) * 2 - 1, | ||||||
|         (bitActiveTakts) * 2 - 1}; |         (bitActiveTakts) * 2 - 1}; | ||||||
| uint8_t* IR_Encoder::bitLow = new uint8_t[2]{ | uint8_t* IR_Encoder::bitLow = new uint8_t[2]{ | ||||||
|         (bitPauseTakts + bitActiveTakts) * 2 - 1, |         (bitPauseTakts/2 + bitActiveTakts) * 2 - 1, | ||||||
|         (bitPauseTakts) * 2 - 1}; |         (bitPauseTakts) - 1}; | ||||||
							
								
								
									
										10
									
								
								IR_config.h
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								IR_config.h
									
									
									
									
									
								
							| @ -101,13 +101,14 @@ customByte - контрольная сумма принятых данных п | |||||||
| /////////////////////////////////////////////////////////////////////////////////////*/ | /////////////////////////////////////////////////////////////////////////////////////*/ | ||||||
| typedef uint16_t crc_t; | typedef uint16_t crc_t; | ||||||
|  |  | ||||||
|  | #define BRUTEFORCE_CHECK                            // Перепроверяет пакет на 1 битные ошибки //TODO: зависает | ||||||
| #define bytePerPack 16                              // колличество байтов в пакете | #define bytePerPack 16                              // колличество байтов в пакете | ||||||
| #ifndef freeFrec | #ifndef freeFrec | ||||||
| #define freeFrec true | #define freeFrec false | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifndef subBufferSize | #ifndef subBufferSize | ||||||
| #define subBufferSize 11 //Буфер для складирования фронтов, пока их не обработают (передатчик) | #define subBufferSize 5 //Буфер для складирования фронтов, пока их не обработают (передатчик) | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #define preambPulse 3 | #define preambPulse 3 | ||||||
| @ -134,12 +135,11 @@ typedef uint16_t crc_t; | |||||||
|  |  | ||||||
| // В процессе работы значения будут отклонятся в соответствии с предыдущим битом | // В процессе работы значения будут отклонятся в соответствии с предыдущим битом | ||||||
| #define bitActiveTakts 25U                                  // длительность высокого уровня в тактах  | #define bitActiveTakts 25U                                  // длительность высокого уровня в тактах  | ||||||
| #define bitPauseTakts 6U                                    // длительность низкого уровня в тактах | #define bitPauseTakts 12U                                    // длительность низкого уровня в тактах | ||||||
|  |  | ||||||
| #define bitTakts (bitActiveTakts+(bitPauseTakts*2U))          // Общая длительность бита в тактах | #define bitTakts (bitActiveTakts+bitPauseTakts)          // Общая длительность бита в тактах | ||||||
| #define bitTime (bitTakts*carrierPeriod)                    // Общая длительность бита | #define bitTime (bitTakts*carrierPeriod)                    // Общая длительность бита | ||||||
| #define tolerance 300U | #define tolerance 300U | ||||||
|  |  | ||||||
| class IR_FOX { | class IR_FOX { | ||||||
| public: | public: | ||||||
|     struct PackOffsets { |     struct PackOffsets { | ||||||
|  | |||||||
							
								
								
									
										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
	 DashyFox
					DashyFox