Mercurial > public > ostc4
view Small_CPU/Src/wireless.c @ 90:83857eb3b12b kittz
+- stable
author | Dmitry Romanov <kitt@bk.ru> |
---|---|
date | Fri, 23 Nov 2018 18:14:56 +0300 |
parents | 5f11787b4f42 |
children |
line wrap: on
line source
/** ****************************************************************************** * @file wireless.c * @author heinrichs weikamp gmbh * @date 02-July-2015 * @version V0.0.2 * @since 24-March-2016 * @brief Data transfer via magnetic field using Manchester code * @verbatim ============================================================================== ##### How to use ##### ============================================================================== history: 160324 V 0.0.2 für Bonex Sender (Only in old hardware. No longer supported) PA2 triggers to falling edge PA1 triggers to rising edge see baseCPU2.c definitions of ports for details time base is the systick of CMSIS with SysTick->VAL for sub ms info start id is 4 ms low (fall to rise time) old: followed by 2 ms high (but can continue with high on sending '0' next (Hi->Lo) 160324: followed by bit 0: high to low of byte 1 even index numbers are falling edge odd index numbers are rising edge first bit ('1' or '0' can be evaluated with triggerTimeDiffArray[2] (falling edge) if it is much longer than 2ms than the first bit is '0' if it is 2ms than it is '1' // Manchester code: 1 = low to high; 0 = high to low; bits are either rising edge at the middle of the bit transfer -> 1 falling edge at the middle of the bit transfer -> 0 an array is used with even index for falling and odd for rising the next time difference array entry is set to 0 to identify the loss of any edge the time index is stored as microseconds and generated by systick and SysTick->VAL (that is counting down from ->LOAD) old: startTime is the first falling edge, hence the ver first falling edge of the start byte) 160324: startTime is the first rising edge 160324: total transfer time (excluding start with 8 ms) 10*8*2ms + 2ms (stop bit) = 162 ms Definition: first bit is always '0' old: to recognize second start bit easily! old: hence after 2 ms there is a falling edge! 160324: after 1 ms is a falling edge of first bit with value 0 160324: Measurement of send data: length 162 ms including stop bit 81 bit @endverbatim ****************************************************************************** * @attention * * <h2><center>© COPYRIGHT(c) 2016 heinrichs weikamp</center></h2> * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "stm32f4xx_hal.h" #include "wireless.h" #include "scheduler.h" /* array starts with first falling edge * old: beginning of first start byte, * old: data starts on 3 * new: beginning of first bit that is always 0 -> high->low * new: data starts on 0 */ #define ttdaSize (1200) #define TIMEOUTSIZE (20000) #define WIRELESS_OK (0) #define WIRELESS_FAIL (1) #define FALLING (0) #define RISING (1) //#define STEP_HALFBIT (1010) #define STEP_HALFBIT (1000) #define LIMIT_STARTBIT (5000) #define MIN_TIME_STARTBIT (3800) #define MAX_TIME_FIRST_STARTBIT (5200) #define MIN_TIME_BOTH_STARTBITS (MIN_TIME_STARTBIT + MIN_TIME_STARTBIT) #define MAX_TIME_BOTH_STARTBITS (MAX_TIME_FIRST_STARTBIT + 4200) // includes necessary start bit (2000 us) and timing issues #define HELPER_MAX_DATA_LENGTH_TOLERANCE (10*STEP_HALFBIT) #define HELPER_MAX_DATA_BYTES (10) ///< 160324: 10, before 8 #define MAX_DATA_BITS (HELPER_MAX_DATA_BYTES*8) #define MAX_DATA_LENGTH ((STEP_HALFBIT*2*MAX_DATA_BITS) + HELPER_MAX_DATA_LENGTH_TOLERANCE) #define MAX_DIFF_IN_MS ((MAX_DATA_LENGTH+999)/1000) void wireless_reset(uint32_t timeMain, uint32_t timeSub); /* triggerTimeDiffArray in us with max 65 ms */ int32_t triggerNewArray[ttdaSize][2]; int32_t triggerNewArrayDebugStartBits[20][2]; //uint16_t triggerTimeDiffArray[ttdaSize]; uint16_t ttdaPointer; uint32_t startTimeMain; uint32_t subDivisorX1000; uint8_t blockDataCapture = 0; uint8_t evaluateRequest = 0; ///< uint8_t found_first_4ms_high = 0; ///< uint8_t found_second_4ms_low = 0; ///< // =============================================================================== // wireless_init /// @brief has to be called once to initialize the variables // =============================================================================== void wireless_init(void) { subDivisorX1000 = SysTick->LOAD; ///< never changes wireless_reset(0,0); ttdaPointer = 0; ///< is set back again by timeout or on error blockDataCapture = 0; //triggerTimeDiffArray[0] = 0; } /** ****************************************************************************** * @brief RECORDING functions * @author heinrichs weikamp gmbh * @date 03-July-2015 * @version V0.0.1 * @since 03-July-2015 ****************************************************************************** */ // =============================================================================== // wireless_getTime /// @brief RECORDING /// /// @param // =============================================================================== void wireless_getTime(uint32_t *timeMain, uint32_t *timeSub) { uint32_t timeSub2, timeMain2; *timeSub = SysTick->VAL; *timeMain = HAL_GetTick(); timeSub2 = SysTick->VAL; timeMain2 = HAL_GetTick(); /* static uint32_t difference = 0; if(ttdaPointer == 1) difference = 7; //& breakpoint */ if((timeSub2 > *timeSub) && (timeMain2 == *timeMain)) *timeMain -= 1; *timeSub = subDivisorX1000 - *timeSub; *timeSub *= 1000; *timeSub /= subDivisorX1000; } /* stored value _could be_ in multiples of 2 us * to have 1000 for each byte * 0000 is beginning of start bit (always 1) * 1000 is beginning of first bit (if timing is perfect, otherwise less or more) * ... * XXXX000 is beginning of XXXX bit * */ // =============================================================================== // wireless_time0keeper /// @brief RECORDING /// /// @param /// @return still in us // =============================================================================== int32_t wireless_time0keeper(uint8_t store1_or_diffOut0, uint32_t timeMain, uint32_t timeSub) { static uint32_t storeMain = 0, storeSub = 0; /* store time0 */ if(store1_or_diffOut0) { storeMain = timeMain; storeSub = timeSub; return 0; } /* evaluate time difference */ int32_t diff = 0; if((timeMain < storeMain) || ((timeMain - storeMain) > MAX_DIFF_IN_MS)) return -1; diff = timeMain - storeMain; diff *= 1000; diff += timeSub; diff -= storeSub; return diff; } // =============================================================================== // wireless_save_time0 /// @brief RECORDING /// /// @param // =============================================================================== void wireless_save_time0(uint32_t timeMain, uint32_t timeSub) { wireless_time0keeper(1, timeMain, timeSub); } // =============================================================================== // wireless_get_time_since_time0 /// @brief RECORDING /// /// @param /// @return // =============================================================================== int32_t wireless_get_time_since_time0(uint32_t timeMain, uint32_t timeSub) { return wireless_time0keeper(0, timeMain, timeSub); } // =============================================================================== // wireless_get_time_since_previous /// @brief RECORDING /// /// @param /// @return // =============================================================================== int32_t wireless_get_time_since_previous(uint8_t fallingOrRising, uint32_t timeMain, uint32_t timeSub) { int32_t absoluteTimeDiff = wireless_time0keeper(0, timeMain, timeSub); if(fallingOrRising == FALLING) // same array { return (absoluteTimeDiff - triggerNewArray[ttdaPointer][FALLING]); } else if(ttdaPointer > 0) { return (absoluteTimeDiff - triggerNewArray[ttdaPointer - 1][RISING]); } else // not possible return -1; } // =============================================================================== // wireless_reset /// @brief RECORDING /// /// @param // =============================================================================== void wireless_reset(uint32_t timeMain, uint32_t timeSub) { found_first_4ms_high = 0; found_second_4ms_low = 0; ttdaPointer = 0; startTimeMain = 0; evaluateRequest = 0; wireless_save_time0(timeMain, timeSub); triggerNewArray[ttdaPointer][FALLING] = 0; triggerNewArray[ttdaPointer][RISING] = 0; } // =============================================================================== // wireless_trigger_FallingEdgeSignalHigh /// @brief RECORDING /// // =============================================================================== void wireless_trigger_FallingEdgeSignalHigh(void) { uint32_t timeSub, timeMain; int32_t timeDifference; wireless_getTime(&timeMain, &timeSub); if((blockDataCapture) || (evaluateRequest == 1)) return; if(evaluateRequest == 2) wireless_reset(0, 0); if(!found_first_4ms_high) // trying to get first start 4ms { if(ttdaPointer == 0) { wireless_reset(timeMain, timeSub); } else { timeDifference = wireless_get_time_since_time0(timeMain, timeSub); if((timeDifference > 0) && (timeDifference <= LIMIT_STARTBIT)) { triggerNewArray[ttdaPointer][0] = timeDifference; } else { wireless_reset(timeMain, timeSub); } } } else // here comes the very important time0 for all following data if(!found_second_4ms_low) ///< the beginning of the very first is recorded here :-) { timeDifference = wireless_get_time_since_time0(timeMain, timeSub); if((timeDifference > 0) && (timeDifference >= MIN_TIME_BOTH_STARTBITS) && (timeDifference <= MAX_TIME_BOTH_STARTBITS)) { // now we are ready for data for(int i=0;i<20;i++) { if(i <= ttdaPointer) { triggerNewArrayDebugStartBits[i][FALLING] = triggerNewArray[i][FALLING]; triggerNewArrayDebugStartBits[i][RISING] = triggerNewArray[i][FALLING]; } else { triggerNewArrayDebugStartBits[i][FALLING] = 0; triggerNewArrayDebugStartBits[i][RISING] = 0; } } wireless_reset(timeMain, timeSub); ///< reset all including ttdaPointer and more startTimeMain = timeMain; ///< set again found_first_4ms_high = 1; ///< set again found_second_4ms_low = 1; ///< set now: ready for recording } } else { timeDifference = wireless_get_time_since_time0(timeMain, timeSub); if((timeDifference > MAX_DATA_LENGTH) || (ttdaPointer > (ttdaSize - 2))) { evaluateRequest = 1; } else { triggerNewArray[ttdaPointer][FALLING] = timeDifference; triggerNewArray[ttdaPointer][RISING] = 0; } } } // =============================================================================== // wireless_trigger_RisingEdgeSilence /// @brief RECORDING /// // =============================================================================== void wireless_trigger_RisingEdgeSilence(void) { uint32_t timeSub, timeMain; int32_t timeDifference; wireless_getTime(&timeMain, &timeSub); if((blockDataCapture) || (evaluateRequest == 1)) return; if(evaluateRequest == 2) { wireless_reset(0, 0); return; // Falling Edge first } timeDifference = wireless_get_time_since_time0(timeMain, timeSub); if(!found_first_4ms_high) { if((timeDifference > 0) && (timeDifference <= MAX_TIME_FIRST_STARTBIT)) { triggerNewArray[ttdaPointer++][RISING] = timeDifference; triggerNewArray[ttdaPointer][FALLING] = 0; if(timeDifference >= MIN_TIME_STARTBIT) ///< start bit is the 4 ms { found_first_4ms_high = 1; found_second_4ms_low = 0; } } } else { if((timeDifference > MAX_DATA_LENGTH) || (ttdaPointer > (ttdaSize - 2))) { evaluateRequest = 1; } else { triggerNewArray[ttdaPointer++][RISING] = timeDifference; triggerNewArray[ttdaPointer][FALLING] = 0; } } } // =============================================================================== // wireless_position_next /// @brief RECORDING /// /// @param /// @return // =============================================================================== uint8_t wireless_position_next(uint16_t *ttdaPointerNow, uint8_t *typeNow) { if(*typeNow == FALLING) *typeNow = RISING; else if(*ttdaPointerNow < (ttdaSize - 1)) { *ttdaPointerNow += 1; *typeNow = FALLING; } else { return WIRELESS_FAIL; } return WIRELESS_OK; } // =============================================================================== // wireless_position_previous /// @brief RECORDING /// /// @param /// @return // =============================================================================== uint8_t wireless_position_previous(uint16_t *ttdaPointerNow, uint8_t *typeNow) { if(*typeNow == RISING) *typeNow = FALLING; else if(*ttdaPointerNow > 0) { *ttdaPointerNow -= 1; *typeNow = RISING; } else { return WIRELESS_FAIL; } return WIRELESS_OK; } // =============================================================================== // wireless_position_compare /// @brief RECORDING /// /// @param /// @return // =============================================================================== int8_t wireless_position_compare(uint16_t ttdaPointerLeft, uint8_t typeLeft, uint16_t ttdaPointerRight, uint8_t typeRight) { if(ttdaPointerLeft < ttdaPointerRight) return -1; else if(ttdaPointerLeft > ttdaPointerRight) return 1; else if(typeLeft < typeRight) return -1; else if(typeLeft > typeRight) return 1; else return 0; } // =============================================================================== // wireless_debug /// @brief /// /// @param /// @return // =============================================================================== /* outlined because of errors while compiling void wireless_debug(int8_t *adcData, uint16_t max_size_adc) { // debug uint32_t dataVisual[201]; uint8_t dataVisualValue[201]; int8_t dataVisualResult[201]; dataVisualValue[0] = 1; for(int i=0;i<201;i++) dataVisualResult[i] = -1; for(int i=0;i<201-4;i +=4) { dataVisualValue[i] = 1; dataVisualValue[i+1] = 1; dataVisualValue[i+2] = 0; dataVisualValue[i+3] = 0; } dataVisual[0] = triggerNewArray[0][FALLING]; int j = 1; uint32_t valueStore = 0; for(int i=0;i<50;i++) { valueStore = triggerNewArray[i][FALLING]; dataVisual[j++] = valueStore; dataVisual[j++] = valueStore + 1; valueStore = triggerNewArray[i][RISING]; dataVisual[j++] = valueStore; dataVisual[j++] = valueStore + 1; } if(max_size_adc > 0) { int jStep = 0; int jData = 0; for(int i=0;i<201;i++) { if(dataVisual[i] >= jStep) { if(adcData[jData] > 0) dataVisualResult[i] = 1; else dataVisualResult[i] = 0; jStep += STEP_HALFBIT + STEP_HALFBIT; jData++; if(jData >= max_size_adc) break; } } } } */ // =============================================================================== // wireless_debug_test_failed_AACCF1010203 /// @brief /// /// @param /// @return // =============================================================================== uint8_t wireless_debug_test_failed_AACCF1010203(uint8_t *data) { if(data[0] != 0xAA) return 1; if(data[1] != 0xCC) return 1; if(data[2] != 0xF1) return 1; if(data[3] != 0x01) return 1; if(data[4] != 0x02) return 0; if(data[5] != 0x03) return 1; return 0; } // =============================================================================== // wireless_check_crc_failed /// @brief /// /// @param /// @return // =============================================================================== uint8_t wireless_check_crc_failed(uint8_t *dataOut, uint8_t maxData) { return (wireless_debug_test_failed_AACCF1010203(dataOut)); } /** ****************************************************************************** * @brief EVALUATION functions * @author heinrichs weikamp gmbh * @date 03-July-2015 * @version V0.0.2 * @since 14-July-2015 ****************************************************************************** */ // =============================================================================== // wireless_time0keeper /// @brief EVALUATION /// /// @param /// @return // =============================================================================== uint8_t wireless_evaluate_internal_loop(uint8_t *dataOut, uint8_t maxData, int32_t shift, uint8_t *confidence) { // variables int iOut = 0; int jAdc = 0; int8_t adcData[MAX_DATA_BITS]; uint16_t adcPointer = 0; int8_t bitLeft = 0; int8_t bitRight = 0; uint16_t ttdaPointerStart = 0; uint16_t ttdaPointerEnd = 0; uint8_t typeStart = RISING; uint8_t typeEnd = RISING; int32_t startTimeHalfBit = 0; int32_t endTimeHalfBit = 0; int32_t startOfThisPeak = 0; int32_t endOfThisPeak = 0; uint8_t wirelessErrorStatus = 0; uint8_t timeToStop = 0; int32_t valueSingle = 0; int32_t halfbitTemp = 0; int confidenceTemp = 0; // safety end for all loops coming triggerNewArray[ttdaPointer][RISING] = INT32_MAX; ttdaPointerStart = 0; ttdaPointerEnd = 0; typeStart = RISING; typeEnd = RISING; startTimeHalfBit = 0; endTimeHalfBit = shift; adcPointer = 0; while(!timeToStop) { // start is latest start ttdaPointerEnd = ttdaPointerStart; typeEnd = typeStart; for(int doItTwice=0;doItTwice<2;doItTwice++) { startTimeHalfBit = endTimeHalfBit; endTimeHalfBit += STEP_HALFBIT; // find the end for this half bit; this will include values that continue to the next halfbit and negative values while(triggerNewArray[ttdaPointerEnd][typeEnd] < endTimeHalfBit) wireless_position_next(&ttdaPointerEnd,&typeEnd); if(triggerNewArray[ttdaPointerEnd][typeEnd] == INT32_MAX) { timeToStop = 1; break; } startOfThisPeak = startTimeHalfBit; wirelessErrorStatus = 0; halfbitTemp = 0; while(!wirelessErrorStatus && (wireless_position_compare(ttdaPointerStart,typeStart, ttdaPointerEnd,typeEnd) <= 0)) { endOfThisPeak = triggerNewArray[ttdaPointerStart][typeStart]; if(endOfThisPeak <= startOfThisPeak) { wireless_position_next(&ttdaPointerStart,&typeStart); } else { // TODO: what about time difference errors? if(endOfThisPeak >= endTimeHalfBit) valueSingle = endTimeHalfBit - startOfThisPeak; else valueSingle = endOfThisPeak - startOfThisPeak; if(typeStart == RISING) { halfbitTemp += valueSingle; } // next, also valid for every next halfbit if(endOfThisPeak <= endTimeHalfBit) { startOfThisPeak = endOfThisPeak; wireless_position_next(&ttdaPointerStart,&typeStart); } else { startOfThisPeak = endTimeHalfBit; } // should not be necessary, anyway if(startOfThisPeak == endTimeHalfBit) break; } } // store halfbitTemp *= 100; halfbitTemp /= STEP_HALFBIT; if(halfbitTemp > 100) halfbitTemp = 100; if(doItTwice == 0) { bitLeft = halfbitTemp; } else { bitRight = halfbitTemp; } } // Gewichtung und Bit Generierung adcData[adcPointer++] = (int8_t)((bitLeft - bitRight)); // possitive value if(adcPointer >= MAX_DATA_BITS) timeToStop = 1; } // Auswertung jAdc = 0; iOut = 0; for(int i=0;i<maxData;i++) { dataOut[i] = 0; for(int j=0;j<8;j++) { dataOut[i] *= 2; if((adcData[jAdc++] > 0)) dataOut[i] |= 1; if(jAdc >= adcPointer) { j++; while(j<8) { jAdc = adcPointer + 1; // end signal dataOut[i] *= 2; j++; } break; } } if(jAdc > adcPointer) break; iOut++; } confidenceTemp = 0; for(int i=0;i<adcPointer;i++) { if(adcData[i] < 0) confidenceTemp -= adcData[i]; else confidenceTemp += adcData[i]; } // confidence in adcData is 0 to 127 only confidenceTemp *= 2; *confidence = (uint8_t)(confidenceTemp/adcPointer); /* if( (iOut>= 5) && wireless_debug_test_failed_AACCF1010203(dataOut)) wireless_debug(adcData,MAX_DATA_BITS); */ return iOut; } // =============================================================================== // wireless_evaluate_crc_error /// @brief EVALUATION /// /// @param /// @return // =============================================================================== uint8_t wireless_evaluate_crc_error(uint8_t *dataIn, uint8_t maxData) { uint8_t crcTest = 0; for(int i=0; i< maxData; i++) crcTest ^= dataIn[i]; return crcTest; } // =============================================================================== // wireless_evaluate /// @brief EVALUATION /// /// @param /// @return // =============================================================================== uint8_t wireless_evaluate(uint8_t *dataOut, uint8_t maxData, uint8_t *confidence) { uint32_t timeTick; uint32_t timeElapsed; timeTick = HAL_GetTick(); timeElapsed = time_elapsed_ms(startTimeMain,timeTick); uint8_t start = 0; int iOut = 0; // check condition for start if(evaluateRequest == 2) return 0; if(evaluateRequest == 1) start = 1; if((ttdaPointer > 10) && (timeElapsed > (MAX_DATA_LENGTH/1000))) start = 1; if(!start) return 0; // start blockDataCapture = 1; // evaluate iOut = wireless_evaluate_internal_loop(dataOut, maxData, 0, confidence); /* for(int i=0; i>=-500; i -= 100) { iOut = wireless_evaluate_internal_loop(dataOut, maxData, i, confidence); if(iOut < 5) break; if(wireless_check_crc_failed(dataOut,iOut) == 0) break; } */ // end evaluateRequest = 2; blockDataCapture = 0; return iOut; } /************************ (C) COPYRIGHT heinrichs weikamp *****END OF FILE****/