Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
lifiReceiver.cpp@35:dcddce1fe126, 2019-04-10 (annotated)
- Committer:
- JongYongPark
- Date:
- Wed Apr 10 11:58:29 2019 +0900
- Revision:
- 35:dcddce1fe126
- Parent:
- 34:d704131107dd
- Parent:
- 30:75cb79acdcff
add struct
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| JongYongPark | 0:488aa8153e15 | 1 | #include "app.h" |
| JongYongPark | 0:488aa8153e15 | 2 | //#include "../arduino.h" |
| JongYongPark | 0:488aa8153e15 | 3 | //#include "mbed.h" |
| JongYongPark | 0:488aa8153e15 | 4 | //#include <string> |
| JongYongPark | 0:488aa8153e15 | 5 | |
| JongYongPark | 0:488aa8153e15 | 6 | #include "lifiTranceiver.h" |
| JongYongPark | 0:488aa8153e15 | 7 | #include "lifiTranceiverLocal.h" |
| JongYongPark | 0:488aa8153e15 | 8 | |
| JongYongPark | 0:488aa8153e15 | 9 | //#define USE_SLOW_TXRX_DEMO |
| JongYongPark | 0:488aa8153e15 | 10 | //#define USE_SERIAL_COMMAND |
| JongYongPark | 0:488aa8153e15 | 11 | |
| JongYongPark | 0:488aa8153e15 | 12 | //// OLED를 활성화 시키면 FreeRTOS가 정상 동작 안한다. 이문제는 다음에 해결하기로 하자. |
| JongYongPark | 0:488aa8153e15 | 13 | //// 한글 입력이 잘 되네. |
| JongYongPark | 0:488aa8153e15 | 14 | |
| JongYongPark | 0:488aa8153e15 | 15 | // TODO 1 : ADCREF 3.3 Volt - Done |
| JongYongPark | 0:488aa8153e15 | 16 | // TODO 2 : Check Max/Max ADC |
| JongYongPark | 0:488aa8153e15 | 17 | /////////////////////////////////////////////////////// |
| JongYongPark | 0:488aa8153e15 | 18 | ///////// HEADER ////////////////////////////////////// |
| JongYongPark | 0:488aa8153e15 | 19 | |
| JongYongPark | 0:488aa8153e15 | 20 | enum op_mode { |
| JongYongPark | 26:26474003e443 | 21 | OP_HF, OP_LF, OP_PLOT_ADC, OP_RESERVED |
| JongYongPark | 0:488aa8153e15 | 22 | }; |
| JongYongPark | 0:488aa8153e15 | 23 | |
| JongYongPark | 0:488aa8153e15 | 24 | |
| JongYongPark | 0:488aa8153e15 | 25 | /////////////////////////////////////////////////////// |
| JongYongPark | 0:488aa8153e15 | 26 | //////////// GLOBAL VARIABLES ////////////////////// |
| JongYongPark | 26:26474003e443 | 27 | int waiting_count_for_all_channel_finished =0 ; |
| JongYongPark | 0:488aa8153e15 | 28 | unsigned char incomingByte; |
| JongYongPark | 0:488aa8153e15 | 29 | int lines = 0; |
| JongYongPark | 0:488aa8153e15 | 30 | int chars = 0; |
| JongYongPark | 0:488aa8153e15 | 31 | |
| JongYongPark | 0:488aa8153e15 | 32 | //////////// |
| JongYongPark | 0:488aa8153e15 | 33 | |
| JongYongPark | 0:488aa8153e15 | 34 | //manechester decoder state variable |
| JongYongPark | 0:488aa8153e15 | 35 | //long shift_reg = 0; |
| JongYongPark | 0:488aa8153e15 | 36 | // |
| JongYongPark | 0:488aa8153e15 | 37 | //int oldValue = 0 ; |
| JongYongPark | 0:488aa8153e15 | 38 | //int steady_count = 0 ; |
| JongYongPark | 0:488aa8153e15 | 39 | //int dist_last_sync = 0 ; |
| JongYongPark | 0:488aa8153e15 | 40 | //unsigned int detected_word = 0; |
| JongYongPark | 0:488aa8153e15 | 41 | //int new_word = 0; |
| JongYongPark | 0:488aa8153e15 | 42 | //int old_edge_val = 0 ; |
| JongYongPark | 0:488aa8153e15 | 43 | //int probe_adc_high = 0; |
| JongYongPark | 0:488aa8153e15 | 44 | //int probe_adc_low = 0; |
| JongYongPark | 0:488aa8153e15 | 45 | //int probe_adc_gap = 0; |
| JongYongPark | 0:488aa8153e15 | 46 | |
| JongYongPark | 34:d704131107dd | 47 | |
| JongYongPark | 0:488aa8153e15 | 48 | |
| JongYongPark | 34:d704131107dd | 49 | static LIFI_RECEIVING_FRAME rx_vars[LIFI_MIMO_CHANNEL_NUM]; |
| JongYongPark | 34:d704131107dd | 50 | static LIFI_RX_FRAME rx_vars_received[LIFI_MIMO_CHANNEL_NUM]; |
| JongYongPark | 26:26474003e443 | 51 | |
| JongYongPark | 26:26474003e443 | 52 | void LifiRx_CopyAdcInfo_FromReceivedFrame(int channel, int high, int low) |
| JongYongPark | 26:26474003e443 | 53 | { |
| JongYongPark | 26:26474003e443 | 54 | rx_vars_received[channel].probe_adc_high = high ; |
| JongYongPark | 26:26474003e443 | 55 | rx_vars_received[channel].probe_adc_low = low ; |
| JongYongPark | 26:26474003e443 | 56 | rx_vars_received[channel].probe_adc_gap = high - low ; |
| JongYongPark | 26:26474003e443 | 57 | } |
| JongYongPark | 26:26474003e443 | 58 | |
| JongYongPark | 26:26474003e443 | 59 | void LifiRx_CopyData_FromReceivedFrame(int channel) |
| JongYongPark | 26:26474003e443 | 60 | { |
| JongYongPark | 26:26474003e443 | 61 | rx_vars_received[channel].is_received = rx_vars[channel].is_received ; |
| JongYongPark | 26:26474003e443 | 62 | rx_vars_received[channel].is_valid = rx_vars[channel].is_valid ; |
| JongYongPark | 26:26474003e443 | 63 | |
| JongYongPark | 26:26474003e443 | 64 | rx_vars_received[channel].rx_frame_size = rx_vars[channel].rx_frame_size ; |
| JongYongPark | 26:26474003e443 | 65 | rx_vars_received[channel].pdu_length = rx_vars[channel].pdu_length ; |
| JongYongPark | 26:26474003e443 | 66 | rx_vars_received[channel].pdu_length_count = rx_vars[channel].pdu_length_count ; |
| JongYongPark | 26:26474003e443 | 67 | rx_vars_received[channel].frame_length = rx_vars[channel].frame_length ; |
| JongYongPark | 26:26474003e443 | 68 | |
| JongYongPark | 26:26474003e443 | 69 | memcpy( rx_vars_received[channel].rx_frame_buffer, rx_vars[channel].rx_frame_buffer, FRAME_BUFFER_SIZE) ; |
| JongYongPark | 26:26474003e443 | 70 | } |
| JongYongPark | 26:26474003e443 | 71 | |
| JongYongPark | 26:26474003e443 | 72 | void LifiRx_CopyAll_FromReceivedFrame(int channel) |
| JongYongPark | 26:26474003e443 | 73 | { |
| JongYongPark | 26:26474003e443 | 74 | LifiRx_CopyAdcInfo_FromReceivedFrame(channel, rx_vars[channel].probe_adc_high, rx_vars[channel].probe_adc_low ); |
| JongYongPark | 26:26474003e443 | 75 | LifiRx_CopyData_FromReceivedFrame(channel); |
| JongYongPark | 26:26474003e443 | 76 | } |
| JongYongPark | 26:26474003e443 | 77 | |
| JongYongPark | 26:26474003e443 | 78 | void print_frame_data(uint8_t* frame, int length) |
| JongYongPark | 26:26474003e443 | 79 | { |
| JongYongPark | 26:26474003e443 | 80 | printf(" frame (%d) = ",length); |
| JongYongPark | 26:26474003e443 | 81 | for(int i=0; i < length; i++) { |
| JongYongPark | 26:26474003e443 | 82 | // https://simple.wikipedia.org/wiki/ASCII |
| JongYongPark | 26:26474003e443 | 83 | if(frame[i] >= 0x20 && frame[i] <= 0x7E ) { |
| JongYongPark | 26:26474003e443 | 84 | //printf("[%d]%c_%02x ",i,frame[i],frame[i]); |
| JongYongPark | 26:26474003e443 | 85 | printf("%c",frame[i]); |
| JongYongPark | 26:26474003e443 | 86 | } else { |
| JongYongPark | 26:26474003e443 | 87 | //printf("[%d]_%02x ",i,frame[i]); |
| JongYongPark | 26:26474003e443 | 88 | printf(" x%02x ",frame[i]); |
| JongYongPark | 26:26474003e443 | 89 | } |
| JongYongPark | 26:26474003e443 | 90 | } |
| JongYongPark | 26:26474003e443 | 91 | } |
| JongYongPark | 26:26474003e443 | 92 | |
| JongYongPark | 26:26474003e443 | 93 | void print_pdu_data(uint8_t* frame, int length) |
| JongYongPark | 26:26474003e443 | 94 | { |
| JongYongPark | 26:26474003e443 | 95 | printf(" pdu (%d) = ",length); |
| JongYongPark | 26:26474003e443 | 96 | for(int i=0; i < length; i++) { |
| JongYongPark | 26:26474003e443 | 97 | // https://simple.wikipedia.org/wiki/ASCII |
| JongYongPark | 26:26474003e443 | 98 | if(frame[i] >= 0x20 && frame[i] <= 0x7E ) { |
| JongYongPark | 26:26474003e443 | 99 | printf("%c",frame[i]); |
| JongYongPark | 26:26474003e443 | 100 | } else { |
| JongYongPark | 26:26474003e443 | 101 | printf(" "); |
| JongYongPark | 26:26474003e443 | 102 | } |
| JongYongPark | 26:26474003e443 | 103 | } |
| JongYongPark | 26:26474003e443 | 104 | } |
| JongYongPark | 0:488aa8153e15 | 105 | |
| JongYongPark | 14:07669aafe0e4 | 106 | inline int is_a_word_4ch(int channel, long * manchester_word, |
| JongYongPark | 26:26474003e443 | 107 | int time_from_last_sync, unsigned int * detected_word) |
| JongYongPark | 26:26474003e443 | 108 | { |
| JongYongPark | 0:488aa8153e15 | 109 | #if RX_DEBUG_BIN |
| JongYongPark | 26:26474003e443 | 110 | printf("\t %d[%4x] ",channel+1, *detected_word ); |
| JongYongPark | 0:488aa8153e15 | 111 | #endif |
| JongYongPark | 26:26474003e443 | 112 | if (time_from_last_sync >= 20 |
| JongYongPark | 26:26474003e443 | 113 | || rx_vars[channel].frame_state == IDLE_STATE) { // we received enough bits to test the sync |
| JongYongPark | 26:26474003e443 | 114 | if (((*manchester_word) & START_STOP_MASK) == (START_STOP_MASK)) { // testing first position |
| JongYongPark | 26:26474003e443 | 115 | (*detected_word) = ((*manchester_word) >> 2) & 0xFFFF; |
| JongYongPark | 0:488aa8153e15 | 116 | |
| JongYongPark | 26:26474003e443 | 117 | if (rx_vars[channel].frame_state == IDLE_STATE) { |
| JongYongPark | 26:26474003e443 | 118 | if ((*detected_word) == SYNC_SYMBOL_MANCHESTER) { |
| JongYongPark | 26:26474003e443 | 119 | return 2; |
| JongYongPark | 26:26474003e443 | 120 | } |
| JongYongPark | 26:26474003e443 | 121 | } |
| JongYongPark | 26:26474003e443 | 122 | return 1; |
| JongYongPark | 26:26474003e443 | 123 | // byte with correct framing |
| JongYongPark | 26:26474003e443 | 124 | } else if (rx_vars[channel].frame_state != IDLE_STATE |
| JongYongPark | 26:26474003e443 | 125 | && time_from_last_sync == 20) { |
| JongYongPark | 26:26474003e443 | 126 | (*detected_word) = ((*manchester_word) >> 2) & 0xFFFF; |
| JongYongPark | 26:26474003e443 | 127 | return 1; |
| JongYongPark | 26:26474003e443 | 128 | } |
| JongYongPark | 26:26474003e443 | 129 | } |
| JongYongPark | 26:26474003e443 | 130 | return 0; |
| JongYongPark | 0:488aa8153e15 | 131 | } |
| JongYongPark | 0:488aa8153e15 | 132 | |
| JongYongPark | 14:07669aafe0e4 | 133 | inline int insert_edge_4ch(int channel, long * manchester_word, int edge, |
| JongYongPark | 26:26474003e443 | 134 | int edge_period, int * time_from_last_sync, |
| JongYongPark | 26:26474003e443 | 135 | unsigned int * detected_word) |
| JongYongPark | 26:26474003e443 | 136 | { |
| JongYongPark | 26:26474003e443 | 137 | int new_word = 0; |
| JongYongPark | 26:26474003e443 | 138 | int is_a_word_value = 0; |
| JongYongPark | 26:26474003e443 | 139 | int sync_word_detect = 0; |
| JongYongPark | 26:26474003e443 | 140 | if (((*manchester_word) & 0x01) != edge) { //mak sure we don't have same edge ... |
| JongYongPark | 26:26474003e443 | 141 | if (edge_period > (LIFI_RX_SAMPLE_PER_SYMBOL + 1)) { |
| JongYongPark | 26:26474003e443 | 142 | unsigned char last_bit = (*manchester_word) & 0x01; |
| JongYongPark | 26:26474003e443 | 143 | (*manchester_word) = ((*manchester_word) << 1) | last_bit; // signal was steady for longer than a single symbol, |
| JongYongPark | 26:26474003e443 | 144 | (*time_from_last_sync) += 1; |
| JongYongPark | 26:26474003e443 | 145 | is_a_word_value = is_a_word_4ch(channel, manchester_word, |
| JongYongPark | 26:26474003e443 | 146 | (*time_from_last_sync), detected_word); |
| JongYongPark | 26:26474003e443 | 147 | if (is_a_word_value > 0) { //found start stop framing |
| JongYongPark | 26:26474003e443 | 148 | new_word = 1; |
| JongYongPark | 26:26474003e443 | 149 | (*time_from_last_sync) = 0; |
| JongYongPark | 26:26474003e443 | 150 | if (is_a_word_value > 1) { |
| JongYongPark | 26:26474003e443 | 151 | sync_word_detect = 1; //we detected framing and sync word in manchester format |
| JongYongPark | 0:488aa8153e15 | 152 | #if RX_DEBUG_BIN |
| JongYongPark | 26:26474003e443 | 153 | printf("\n%dS",channel+1); |
| JongYongPark | 0:488aa8153e15 | 154 | #endif |
| JongYongPark | 26:26474003e443 | 155 | } |
| JongYongPark | 26:26474003e443 | 156 | } |
| JongYongPark | 26:26474003e443 | 157 | } |
| JongYongPark | 26:26474003e443 | 158 | ///////////////////////////// |
| JongYongPark | 26:26474003e443 | 159 | //storing edge value in word |
| JongYongPark | 26:26474003e443 | 160 | if (edge < 0) { |
| JongYongPark | 26:26474003e443 | 161 | (*manchester_word) = ((*manchester_word) << 1) | 0x00; // signal goes down |
| JongYongPark | 0:488aa8153e15 | 162 | #if RX_DEBUG_BIN |
| JongYongPark | 26:26474003e443 | 163 | printf("%d[0]",channel+1); |
| JongYongPark | 0:488aa8153e15 | 164 | #endif |
| JongYongPark | 26:26474003e443 | 165 | } else { |
| JongYongPark | 26:26474003e443 | 166 | (*manchester_word) = ((*manchester_word) << 1) | 0x01; // signal goes up |
| JongYongPark | 0:488aa8153e15 | 167 | #if RX_DEBUG_BIN |
| JongYongPark | 26:26474003e443 | 168 | printf("%d[1]",channel+1); |
| JongYongPark | 0:488aa8153e15 | 169 | #endif |
| JongYongPark | 26:26474003e443 | 170 | } |
| JongYongPark | 26:26474003e443 | 171 | ///////////////////////////////////// |
| JongYongPark | 26:26474003e443 | 172 | (*time_from_last_sync) += 1; |
| JongYongPark | 26:26474003e443 | 173 | is_a_word_value = is_a_word_4ch(channel, manchester_word, |
| JongYongPark | 26:26474003e443 | 174 | (*time_from_last_sync), detected_word); |
| JongYongPark | 26:26474003e443 | 175 | if (sync_word_detect == 0 && is_a_word_value > 0) { //if sync word was detected at previous position, don't take word detection into account |
| JongYongPark | 26:26474003e443 | 176 | new_word = 1; |
| JongYongPark | 26:26474003e443 | 177 | (*time_from_last_sync) = 0; |
| JongYongPark | 0:488aa8153e15 | 178 | #if RX_DEBUG_BIN |
| JongYongPark | 26:26474003e443 | 179 | printf("%dD",channel+1); |
| JongYongPark | 0:488aa8153e15 | 180 | #endif |
| JongYongPark | 26:26474003e443 | 181 | } |
| JongYongPark | 26:26474003e443 | 182 | } else { |
| JongYongPark | 26:26474003e443 | 183 | new_word = -1; |
| JongYongPark | 0:488aa8153e15 | 184 | #if RX_DEBUG_BIN |
| JongYongPark | 26:26474003e443 | 185 | printf("%d_",channel+1); |
| JongYongPark | 0:488aa8153e15 | 186 | #endif |
| JongYongPark | 26:26474003e443 | 187 | } |
| JongYongPark | 26:26474003e443 | 188 | return new_word; |
| JongYongPark | 0:488aa8153e15 | 189 | } |
| JongYongPark | 0:488aa8153e15 | 190 | |
| JongYongPark | 26:26474003e443 | 191 | void sample_signal_edge_4ch(int channel, int sensorValue) |
| JongYongPark | 26:26474003e443 | 192 | { |
| JongYongPark | 26:26474003e443 | 193 | rx_vars[channel].sensorValue = sensorValue; |
| JongYongPark | 26:26474003e443 | 194 | //int sensorValue = analogRead(SENSOR_PIN_PORT); // this is too slow and should be replaced with interrupt-driven ADC |
| JongYongPark | 26:26474003e443 | 195 | //t sensorValue = LifiRx_AdcRead(0); // read result of previously triggered conversion |
| JongYongPark | 26:26474003e443 | 196 | //ADC_start_conversion(SENSOR_PIN); // start a conversion for next loop |
| JongYongPark | 0:488aa8153e15 | 197 | |
| JongYongPark | 0:488aa8153e15 | 198 | #if RX_DEBUG_ANALOG_SENSOR_VALUE |
| JongYongPark | 26:26474003e443 | 199 | printf(" adc:%d ",rx_vars[channel].sensorValue); |
| JongYongPark | 0:488aa8153e15 | 200 | #endif |
| JongYongPark | 26:26474003e443 | 201 | if ((rx_vars[channel].sensorValue - rx_vars[channel].oldValue) |
| JongYongPark | 26:26474003e443 | 202 | > LIFI_RX_EDGE_THRESHOLD) { |
| JongYongPark | 26:26474003e443 | 203 | rx_vars[channel].edge_val = 1; |
| JongYongPark | 26:26474003e443 | 204 | |
| JongYongPark | 26:26474003e443 | 205 | #if CHECK_EDGE_WITH_DEBUG_LED |
| JongYongPark | 26:26474003e443 | 206 | if( int LifiRx_GetDebugLed() == 0 ) printf("\n Edge Detect Fail (Up / 0) !!!"); |
| JongYongPark | 0:488aa8153e15 | 207 | #endif |
| JongYongPark | 0:488aa8153e15 | 208 | |
| JongYongPark | 0:488aa8153e15 | 209 | #if RX_DEBUG_EDGE |
| JongYongPark | 26:26474003e443 | 210 | printf("%d/ %d-%d",channel+1,rx_vars[channel].sensorValue,rx_vars[channel].oldValue); |
| JongYongPark | 0:488aa8153e15 | 211 | #endif |
| JongYongPark | 26:26474003e443 | 212 | if (rx_vars[channel].probe_adc_high < rx_vars[channel].sensorValue) |
| JongYongPark | 26:26474003e443 | 213 | rx_vars[channel].probe_adc_high = rx_vars[channel].sensorValue; |
| JongYongPark | 26:26474003e443 | 214 | } else if ((rx_vars[channel].oldValue - rx_vars[channel].sensorValue) |
| JongYongPark | 26:26474003e443 | 215 | > LIFI_RX_EDGE_THRESHOLD) { |
| JongYongPark | 26:26474003e443 | 216 | rx_vars[channel].edge_val = -1; |
| JongYongPark | 26:26474003e443 | 217 | |
| JongYongPark | 26:26474003e443 | 218 | #if CHECK_EDGE_WITH_DEBUG_LED |
| JongYongPark | 26:26474003e443 | 219 | if( int LifiRx_GetDebugLed() == 1 ) printf("\n Edge Detect Fail (Down / 1) !!!"); |
| JongYongPark | 26:26474003e443 | 220 | #endif |
| JongYongPark | 0:488aa8153e15 | 221 | |
| JongYongPark | 0:488aa8153e15 | 222 | #if RX_DEBUG_EDGE |
| JongYongPark | 26:26474003e443 | 223 | printf("%d| %d-%d",channel+1,rx_vars[channel].oldValue,rx_vars[channel].sensorValue); |
| JongYongPark | 26:26474003e443 | 224 | #endif |
| JongYongPark | 26:26474003e443 | 225 | if (rx_vars[channel].probe_adc_low > rx_vars[channel].sensorValue) |
| JongYongPark | 26:26474003e443 | 226 | rx_vars[channel].probe_adc_low = rx_vars[channel].sensorValue; |
| JongYongPark | 26:26474003e443 | 227 | } else { |
| JongYongPark | 26:26474003e443 | 228 | #if RX_DEBUG_EDGE |
| JongYongPark | 26:26474003e443 | 229 | printf("%d=",channel+1); |
| JongYongPark | 0:488aa8153e15 | 230 | #endif |
| JongYongPark | 26:26474003e443 | 231 | rx_vars[channel].edge_val = 0; |
| JongYongPark | 26:26474003e443 | 232 | } |
| JongYongPark | 26:26474003e443 | 233 | |
| JongYongPark | 26:26474003e443 | 234 | ///////////// |
| JongYongPark | 26:26474003e443 | 235 | rx_vars[channel].oldValue = rx_vars[channel].sensorValue; |
| JongYongPark | 26:26474003e443 | 236 | if (rx_vars[channel].edge_val == 0 |
| JongYongPark | 26:26474003e443 | 237 | || rx_vars[channel].edge_val == rx_vars[channel].old_edge_val |
| JongYongPark | 26:26474003e443 | 238 | || (rx_vars[channel].edge_val != rx_vars[channel].old_edge_val |
| JongYongPark | 26:26474003e443 | 239 | && rx_vars[channel].steady_count < 2)) { |
| JongYongPark | 26:26474003e443 | 240 | if (rx_vars[channel].steady_count < (4 * LIFI_RX_SAMPLE_PER_SYMBOL)) { |
| JongYongPark | 26:26474003e443 | 241 | #if RX_DEBUG_EDGE |
| JongYongPark | 26:26474003e443 | 242 | printf("%d+",channel+1); |
| JongYongPark | 26:26474003e443 | 243 | #endif |
| JongYongPark | 26:26474003e443 | 244 | rx_vars[channel].steady_count++; |
| JongYongPark | 26:26474003e443 | 245 | } |
| JongYongPark | 26:26474003e443 | 246 | } else { |
| JongYongPark | 26:26474003e443 | 247 | |
| JongYongPark | 26:26474003e443 | 248 | #if RX_DEBUG_EDGE |
| JongYongPark | 26:26474003e443 | 249 | if(rx_vars[channel].edge_val == 1) printf("%dH",channel+1); |
| JongYongPark | 26:26474003e443 | 250 | else if(rx_vars[channel].edge_val == -1) printf("%dL",channel+1); |
| JongYongPark | 26:26474003e443 | 251 | #endif |
| JongYongPark | 26:26474003e443 | 252 | //inline int insert_edge_4ch(int channel, long * manchester_word, int edge, int edge_period, int * time_from_last_sync, unsigned int * detected_word) |
| JongYongPark | 26:26474003e443 | 253 | rx_vars[channel].new_word = insert_edge_4ch(channel, |
| JongYongPark | 26:26474003e443 | 254 | &rx_vars[channel].shift_reg, rx_vars[channel].edge_val, |
| JongYongPark | 26:26474003e443 | 255 | rx_vars[channel].steady_count, |
| JongYongPark | 26:26474003e443 | 256 | &(rx_vars[channel].dist_last_sync), |
| JongYongPark | 26:26474003e443 | 257 | &rx_vars[channel].detected_word); |
| JongYongPark | 26:26474003e443 | 258 | if (rx_vars[channel].dist_last_sync > (8 * LIFI_RX_SAMPLE_PER_SYMBOL)) { // limit dist_last_sync to avoid overflow problems |
| JongYongPark | 26:26474003e443 | 259 | rx_vars[channel].dist_last_sync = 32; |
| JongYongPark | 0:488aa8153e15 | 260 | #if RX_DEBUG_FRAME |
| JongYongPark | 0:488aa8153e15 | 261 | // println("\t %dRESET avoid overlow ",channel+1); |
| JongYongPark | 0:488aa8153e15 | 262 | #endif |
| JongYongPark | 26:26474003e443 | 263 | } |
| JongYongPark | 14:07669aafe0e4 | 264 | |
| JongYongPark | 0:488aa8153e15 | 265 | // if(new_word >= 0) { |
| JongYongPark | 0:488aa8153e15 | 266 | #if RX_DEBUG_FRAME |
| JongYongPark | 0:488aa8153e15 | 267 | // println("\t %dRESET COUNTER ",channel+1); |
| JongYongPark | 0:488aa8153e15 | 268 | #endif |
| JongYongPark | 26:26474003e443 | 269 | rx_vars[channel].steady_count = 0; |
| JongYongPark | 0:488aa8153e15 | 270 | // } |
| JongYongPark | 26:26474003e443 | 271 | } |
| JongYongPark | 26:26474003e443 | 272 | rx_vars[channel].old_edge_val = rx_vars[channel].edge_val; |
| JongYongPark | 14:07669aafe0e4 | 273 | |
| JongYongPark | 26:26474003e443 | 274 | #if (USE_MBED_OS5 && USE_LIFI_RX_CHECK_QUEUE) |
| JongYongPark | 26:26474003e443 | 275 | if((rx_vars[channel].new_word == 1) && (channel == LIFI_ACTUAL_MAX_CHANNEL_NUM_INDEX)) { |
| JongYongPark | 26:26474003e443 | 276 | //printf("!"); |
| JongYongPark | 26:26474003e443 | 277 | // https://os.mbed.com/forum/bugs-suggestions/topic/28244/?page=1#comment-53612 |
| JongYongPark | 26:26474003e443 | 278 | lifi_tx_check_queue.call(LifiRx_LoopOOK); |
| JongYongPark | 26:26474003e443 | 279 | } |
| JongYongPark | 26:26474003e443 | 280 | #endif |
| JongYongPark | 0:488aa8153e15 | 281 | } |
| JongYongPark | 0:488aa8153e15 | 282 | |
| JongYongPark | 34:d704131107dd | 283 | int add_byte_to_frame_v1(int channel,uint8_t * rx_frame_buffer, int * rx_frame_index, int * rx_frame_size, enum lifi_rx_state * frame_state,unsigned char data) |
| JongYongPark | 16:c551ee1092f5 | 284 | { |
| JongYongPark | 16:c551ee1092f5 | 285 | if(data == SYNC_SYMBOL/* && (*rx_frame_index) < 0*/) { |
| JongYongPark | 16:c551ee1092f5 | 286 | (*rx_frame_index) = 0 ; |
| JongYongPark | 16:c551ee1092f5 | 287 | (*rx_frame_size) = 0 ; |
| JongYongPark | 16:c551ee1092f5 | 288 | (*frame_state) = SYNC_STATE ; |
| JongYongPark | 16:c551ee1092f5 | 289 | #if RX_DEBUG_FRAME |
| JongYongPark | 16:c551ee1092f5 | 290 | printf("\n%dSYNC ",channel+1); |
| JongYongPark | 16:c551ee1092f5 | 291 | #endif |
| JongYongPark | 16:c551ee1092f5 | 292 | return 0 ; |
| JongYongPark | 16:c551ee1092f5 | 293 | } |
| JongYongPark | 16:c551ee1092f5 | 294 | if((*frame_state) != IDLE_STATE) { // we are synced |
| JongYongPark | 16:c551ee1092f5 | 295 | rx_frame_buffer[*rx_frame_index] = data ; |
| JongYongPark | 16:c551ee1092f5 | 296 | (*rx_frame_index) ++ ; |
| JongYongPark | 16:c551ee1092f5 | 297 | if(data == STX) { |
| JongYongPark | 16:c551ee1092f5 | 298 | #if RX_DEBUG_FRAME |
| JongYongPark | 16:c551ee1092f5 | 299 | printf("%dSTART ",channel+1); |
| JongYongPark | 16:c551ee1092f5 | 300 | #endif |
| JongYongPark | 16:c551ee1092f5 | 301 | (*frame_state) = START_STATE ; |
| JongYongPark | 16:c551ee1092f5 | 302 | return 0 ; |
| JongYongPark | 16:c551ee1092f5 | 303 | } else if(data == ETX) { |
| JongYongPark | 16:c551ee1092f5 | 304 | #if RX_DEBUG_FRAME |
| JongYongPark | 16:c551ee1092f5 | 305 | printf("%dEND IDLE ",channel+1); |
| JongYongPark | 16:c551ee1092f5 | 306 | #endif |
| JongYongPark | 16:c551ee1092f5 | 307 | (*rx_frame_size) = (*rx_frame_index) ; |
| JongYongPark | 16:c551ee1092f5 | 308 | (*rx_frame_index) = -1 ; |
| JongYongPark | 16:c551ee1092f5 | 309 | (*frame_state) = IDLE_STATE ; |
| JongYongPark | 16:c551ee1092f5 | 310 | |
| JongYongPark | 16:c551ee1092f5 | 311 | return 1 ; |
| JongYongPark | 16:c551ee1092f5 | 312 | } else if((*rx_frame_index) >= FRAME_BUFFER_SIZE) { //frame is larger than max size of frame ... |
| JongYongPark | 16:c551ee1092f5 | 313 | #if RX_DEBUG_FRAME |
| JongYongPark | 16:c551ee1092f5 | 314 | printf("%dIDLE - over FRAME_BUFFER_SIZE ",channel+1); |
| JongYongPark | 16:c551ee1092f5 | 315 | #endif |
| JongYongPark | 16:c551ee1092f5 | 316 | (*rx_frame_index) = -1 ; |
| JongYongPark | 16:c551ee1092f5 | 317 | (*rx_frame_size) = -1 ; |
| JongYongPark | 16:c551ee1092f5 | 318 | (*frame_state) = IDLE_STATE ; |
| JongYongPark | 16:c551ee1092f5 | 319 | return -1 ; |
| JongYongPark | 16:c551ee1092f5 | 320 | } else { |
| JongYongPark | 16:c551ee1092f5 | 321 | #if RX_DEBUG_FRAME |
| JongYongPark | 16:c551ee1092f5 | 322 | printf("%dD=%c[%x] ",channel+1,data,data); |
| JongYongPark | 16:c551ee1092f5 | 323 | #endif |
| JongYongPark | 16:c551ee1092f5 | 324 | (*frame_state) = DATA_STATE ; |
| JongYongPark | 16:c551ee1092f5 | 325 | } |
| JongYongPark | 16:c551ee1092f5 | 326 | return 0 ; |
| JongYongPark | 16:c551ee1092f5 | 327 | } |
| JongYongPark | 16:c551ee1092f5 | 328 | return -1 ; |
| JongYongPark | 16:c551ee1092f5 | 329 | } |
| JongYongPark | 16:c551ee1092f5 | 330 | |
| JongYongPark | 18:2f7b820324c3 | 331 | int add_byte_to_frame(int channel, uint8_t * rx_frame_buffer, |
| JongYongPark | 26:26474003e443 | 332 | int * rx_frame_index, int * rx_frame_size, |
| JongYongPark | 34:d704131107dd | 333 | enum lifi_rx_state * frame_state, unsigned char data) |
| JongYongPark | 26:26474003e443 | 334 | { |
| JongYongPark | 26:26474003e443 | 335 | if (data == SYNC_SYMBOL/* && (*rx_frame_index) < 0*/) { |
| JongYongPark | 26:26474003e443 | 336 | (*rx_frame_index) = 0; |
| JongYongPark | 26:26474003e443 | 337 | (*rx_frame_size) = 0; |
| JongYongPark | 26:26474003e443 | 338 | (*frame_state) = SYNC_STATE; |
| JongYongPark | 0:488aa8153e15 | 339 | #if RX_DEBUG_FRAME |
| JongYongPark | 26:26474003e443 | 340 | printf("\n%dSYNC ",channel+1); |
| JongYongPark | 0:488aa8153e15 | 341 | #endif |
| JongYongPark | 27:19ee6e15ba5e | 342 | printf("\n *** Channel[%d] Rx Started !!! *** ", channel +1 ); |
| JongYongPark | 26:26474003e443 | 343 | return 0; |
| JongYongPark | 26:26474003e443 | 344 | } |
| JongYongPark | 26:26474003e443 | 345 | if ((*frame_state) != IDLE_STATE) { // we are synced |
| JongYongPark | 26:26474003e443 | 346 | rx_frame_buffer[*rx_frame_index] = data; |
| JongYongPark | 26:26474003e443 | 347 | (*rx_frame_index)++; |
| JongYongPark | 11:8ffa8a36126f | 348 | |
| JongYongPark | 26:26474003e443 | 349 | if ((*frame_state) == SYNC_STATE) { |
| JongYongPark | 26:26474003e443 | 350 | if (data == STX) { |
| JongYongPark | 0:488aa8153e15 | 351 | #if RX_DEBUG_FRAME |
| JongYongPark | 26:26474003e443 | 352 | printf("%dSTART ",channel+1); |
| JongYongPark | 0:488aa8153e15 | 353 | #endif |
| JongYongPark | 26:26474003e443 | 354 | (*frame_state) = START_STATE; |
| JongYongPark | 26:26474003e443 | 355 | return 0; |
| JongYongPark | 26:26474003e443 | 356 | } else if (data == SYNC_SYMBOL) { |
| JongYongPark | 26:26474003e443 | 357 | // do nothing |
| JongYongPark | 26:26474003e443 | 358 | } else { |
| JongYongPark | 26:26474003e443 | 359 | printf("\n Error # got wrong data after SYNC. it should be STX"); |
| JongYongPark | 26:26474003e443 | 360 | (*frame_state) = IDLE_STATE; |
| JongYongPark | 26:26474003e443 | 361 | return -1; |
| JongYongPark | 26:26474003e443 | 362 | } |
| JongYongPark | 11:8ffa8a36126f | 363 | |
| JongYongPark | 34:d704131107dd | 364 | } |
| JongYongPark | 34:d704131107dd | 365 | else if ((*frame_state) == START_STATE) { |
| JongYongPark | 11:8ffa8a36126f | 366 | |
| JongYongPark | 34:d704131107dd | 367 | rx_vars[channel].pdu_length = data ; |
| JongYongPark | 26:26474003e443 | 368 | rx_vars[channel].pdu_length_count = 0; |
| JongYongPark | 26:26474003e443 | 369 | rx_vars[channel].frame_length = rx_vars[channel].pdu_length + LIFI_FRAME_HEADER_SIZE; |
| JongYongPark | 16:c551ee1092f5 | 370 | #if RX_DEBUG_FRAME |
| JongYongPark | 34:d704131107dd | 371 | printf("%dLENGTH(%d) length=%d ",channel+1,data, rx_vars[channel].pdu_length); |
| JongYongPark | 11:8ffa8a36126f | 372 | #endif |
| JongYongPark | 26:26474003e443 | 373 | (*frame_state) = DATA_STATE; |
| JongYongPark | 34:d704131107dd | 374 | } |
| JongYongPark | 34:d704131107dd | 375 | else if ((*frame_state) == DATA_STATE) { |
| JongYongPark | 26:26474003e443 | 376 | rx_vars[channel].pdu_length_count++; |
| JongYongPark | 26:26474003e443 | 377 | // when ETX |
| JongYongPark | 26:26474003e443 | 378 | if (rx_vars[channel].pdu_length_count |
| JongYongPark | 26:26474003e443 | 379 | > rx_vars[channel].pdu_length) { |
| JongYongPark | 26:26474003e443 | 380 | |
| JongYongPark | 26:26474003e443 | 381 | rx_vars[channel].pdu_length_count--; // ETX is not included on data length |
| JongYongPark | 26:26474003e443 | 382 | //// rx_vars[channel].pdu_length_count_save = rx_vars[channel].pdu_length_count; |
| JongYongPark | 26:26474003e443 | 383 | // rx_vars[channel].pdu_length_save = rx_vars[channel].pdu_length; |
| JongYongPark | 26:26474003e443 | 384 | //// rx_vars[channel].frame_length_save = rx_vars[channel].frame_length; |
| JongYongPark | 18:2f7b820324c3 | 385 | |
| JongYongPark | 26:26474003e443 | 386 | if (data == ETX) { |
| JongYongPark | 17:847e9b792c72 | 387 | #if RX_DEBUG_FRAME |
| JongYongPark | 26:26474003e443 | 388 | printf("%dEND IDLE ",channel+1); |
| JongYongPark | 17:847e9b792c72 | 389 | #endif |
| JongYongPark | 26:26474003e443 | 390 | (*rx_frame_size) = (*rx_frame_index); |
| JongYongPark | 26:26474003e443 | 391 | (*rx_frame_index) = -1; |
| JongYongPark | 26:26474003e443 | 392 | (*frame_state) = IDLE_STATE; |
| JongYongPark | 26:26474003e443 | 393 | return 1; |
| JongYongPark | 26:26474003e443 | 394 | } else { |
| JongYongPark | 26:26474003e443 | 395 | printf("\n CH(%d) Error : got wrong data (0x%2x). it should be ETX (0x03)",channel,data); |
| JongYongPark | 26:26474003e443 | 396 | print_frame_data(rx_vars[channel].rx_frame_buffer, rx_vars[channel].frame_length); |
| JongYongPark | 26:26474003e443 | 397 | (*frame_state) = IDLE_STATE; |
| JongYongPark | 26:26474003e443 | 398 | return -1; |
| JongYongPark | 26:26474003e443 | 399 | } |
| JongYongPark | 26:26474003e443 | 400 | } |
| JongYongPark | 26:26474003e443 | 401 | // normal DATA |
| JongYongPark | 26:26474003e443 | 402 | else { |
| JongYongPark | 0:488aa8153e15 | 403 | #if RX_DEBUG_FRAME |
| JongYongPark | 26:26474003e443 | 404 | printf("%dD=%c[%x] ",channel+1,data,data); |
| JongYongPark | 26:26474003e443 | 405 | #endif |
| JongYongPark | 26:26474003e443 | 406 | } |
| JongYongPark | 26:26474003e443 | 407 | } else if ((*rx_frame_index) >= FRAME_BUFFER_SIZE) { //frame is larger than max size of frame ... |
| JongYongPark | 26:26474003e443 | 408 | #if RX_DEBUG_FRAME |
| JongYongPark | 26:26474003e443 | 409 | printf("%dIDLE - over FRAME_BUFFER_SIZE ",channel+1); |
| JongYongPark | 0:488aa8153e15 | 410 | #endif |
| JongYongPark | 26:26474003e443 | 411 | (*rx_frame_index) = -1; |
| JongYongPark | 26:26474003e443 | 412 | (*rx_frame_size) = -1; |
| JongYongPark | 26:26474003e443 | 413 | (*frame_state) = IDLE_STATE; |
| JongYongPark | 26:26474003e443 | 414 | return -1; |
| JongYongPark | 26:26474003e443 | 415 | } else { |
| JongYongPark | 26:26474003e443 | 416 | printf("\n CH(%d) Error : unknown state (%d)", channel+1 , *frame_state); |
| JongYongPark | 26:26474003e443 | 417 | (*frame_state) = IDLE_STATE; |
| JongYongPark | 26:26474003e443 | 418 | return 1; |
| JongYongPark | 26:26474003e443 | 419 | } |
| JongYongPark | 26:26474003e443 | 420 | return 0; // normal |
| JongYongPark | 26:26474003e443 | 421 | } |
| JongYongPark | 26:26474003e443 | 422 | return -1; // error |
| JongYongPark | 0:488aa8153e15 | 423 | } |
| JongYongPark | 0:488aa8153e15 | 424 | |
| JongYongPark | 0:488aa8153e15 | 425 | int counter = 0; |
| JongYongPark | 0:488aa8153e15 | 426 | |
| JongYongPark | 26:26474003e443 | 427 | void setup_ADC() |
| JongYongPark | 26:26474003e443 | 428 | { |
| JongYongPark | 0:488aa8153e15 | 429 | // |
| JongYongPark | 0:488aa8153e15 | 430 | // if( (m_op_mode != OP_HW_TEST) && (m_op_mode != OP_PLOT_ADC)) |
| JongYongPark | 0:488aa8153e15 | 431 | // { |
| JongYongPark | 0:488aa8153e15 | 432 | // //analogReference(INTERNAL); // internal reference is 1.1v, should give better accuracy for the mv range of the led output. |
| JongYongPark | 0:488aa8153e15 | 433 | // Timer1.initialize(LIFI_RX_SYMBOL_PERIOD_US/LIFI_RX_SAMPLE_PER_SYMBOL); //1200 bauds oversampled by factor 4 |
| JongYongPark | 0:488aa8153e15 | 434 | // Timer1.attachInterrupt(sample_signal_edge); |
| JongYongPark | 0:488aa8153e15 | 435 | // } |
| JongYongPark | 0:488aa8153e15 | 436 | } |
| JongYongPark | 0:488aa8153e15 | 437 | |
| JongYongPark | 0:488aa8153e15 | 438 | // the setup routine runs once when you press reset: |
| JongYongPark | 0:488aa8153e15 | 439 | |
| JongYongPark | 0:488aa8153e15 | 440 | //bool isValidNumber(string str) |
| JongYongPark | 0:488aa8153e15 | 441 | //{ |
| JongYongPark | 0:488aa8153e15 | 442 | // bool isNum=true; |
| JongYongPark | 0:488aa8153e15 | 443 | // for(byte i=0; i<str.length(); i++) { |
| JongYongPark | 0:488aa8153e15 | 444 | // //isNum = isDigit(str.charAt(i)) || str.charAt(i) == '+' || str.charAt(i) == '.' || str.charAt(i) == '-'; |
| JongYongPark | 0:488aa8153e15 | 445 | //// isNum = isDigit(str.charAt(i)); // || str.charAt(i) == '+' || str.charAt(i) == '.' || str.charAt(i) == '-'; |
| JongYongPark | 0:488aa8153e15 | 446 | // if(!isNum) return false; |
| JongYongPark | 0:488aa8153e15 | 447 | // } |
| JongYongPark | 0:488aa8153e15 | 448 | // return isNum; |
| JongYongPark | 0:488aa8153e15 | 449 | //} |
| JongYongPark | 0:488aa8153e15 | 450 | |
| JongYongPark | 26:26474003e443 | 451 | bool rx_loop_ook_4ch(int channel) |
| JongYongPark | 26:26474003e443 | 452 | { |
| JongYongPark | 26:26474003e443 | 453 | int i; |
| JongYongPark | 26:26474003e443 | 454 | bool got_all_frame = false; |
| JongYongPark | 26:26474003e443 | 455 | unsigned char received_data; |
| JongYongPark | 26:26474003e443 | 456 | //unsigned char received_data_print ; |
| JongYongPark | 26:26474003e443 | 457 | //int nb_shift ; |
| JongYongPark | 26:26474003e443 | 458 | int byte_added = 0; |
| JongYongPark | 26:26474003e443 | 459 | bool valid_chars; |
| JongYongPark | 26:26474003e443 | 460 | if (rx_vars[channel].new_word == 1) { |
| JongYongPark | 26:26474003e443 | 461 | received_data = 0; |
| JongYongPark | 26:26474003e443 | 462 | for (i = 0; i < 16; i = i + 2) { //decoding Manchester |
| JongYongPark | 26:26474003e443 | 463 | received_data = received_data << 1; |
| JongYongPark | 26:26474003e443 | 464 | if (((rx_vars[channel].detected_word >> i) & 0x03) == 0x01) { |
| JongYongPark | 26:26474003e443 | 465 | received_data |= 0x01; |
| JongYongPark | 26:26474003e443 | 466 | } else { |
| JongYongPark | 26:26474003e443 | 467 | received_data &= ~0x01; |
| JongYongPark | 26:26474003e443 | 468 | } |
| JongYongPark | 26:26474003e443 | 469 | } |
| JongYongPark | 26:26474003e443 | 470 | received_data = received_data & 0xFF; |
| JongYongPark | 0:488aa8153e15 | 471 | #if RX_DEBUG_MAIN_LOOP |
| JongYongPark | 26:26474003e443 | 472 | // printf("%dRx:%c[%x]",channel+1,(unsigned char) received_data,received_data & 0xFF); |
| JongYongPark | 0:488aa8153e15 | 473 | #endif |
| JongYongPark | 26:26474003e443 | 474 | rx_vars[channel].new_word = 0; |
| JongYongPark | 26:26474003e443 | 475 | |
| JongYongPark | 26:26474003e443 | 476 | // return 1 from add_byte_to_frame() means got ETX |
| JongYongPark | 26:26474003e443 | 477 | if ((byte_added = add_byte_to_frame(channel, |
| JongYongPark | 26:26474003e443 | 478 | rx_vars[channel].rx_frame_buffer, |
| JongYongPark | 26:26474003e443 | 479 | &rx_vars[channel].rx_frame_index, |
| JongYongPark | 26:26474003e443 | 480 | &rx_vars[channel].rx_frame_size, &rx_vars[channel].frame_state, |
| JongYongPark | 26:26474003e443 | 481 | received_data)) > 0) |
| JongYongPark | 34:d704131107dd | 482 | |
| JongYongPark | 26:26474003e443 | 483 | { |
| JongYongPark | 26:26474003e443 | 484 | valid_chars = true; |
| JongYongPark | 26:26474003e443 | 485 | // 여기서 ETX를 0으로 변경해 버린다. |
| JongYongPark | 26:26474003e443 | 486 | //rx_vars[channel].rx_frame_buffer[rx_vars[channel].rx_frame_size - 1] = '\0'; |
| JongYongPark | 0:488aa8153e15 | 487 | #if RX_DEBUG_MAIN_LOOP |
| JongYongPark | 26:26474003e443 | 488 | //printf("%dAdc[Max=%d Min=%d]",channel+1,rx_vars[channel].probe_adc_high,rx_vars[channel].probe_adc_low); |
| JongYongPark | 0:488aa8153e15 | 489 | #endif |
| JongYongPark | 26:26474003e443 | 490 | |
| JongYongPark | 26:26474003e443 | 491 | LifiRx_CopyAdcInfo_FromReceivedFrame( channel, rx_vars[channel].probe_adc_high , rx_vars[channel].probe_adc_low); |
| JongYongPark | 0:488aa8153e15 | 492 | |
| JongYongPark | 26:26474003e443 | 493 | rx_vars[channel].probe_adc_high = 0; |
| JongYongPark | 26:26474003e443 | 494 | rx_vars[channel].probe_adc_low = 1024; |
| JongYongPark | 18:2f7b820324c3 | 495 | #if 1 |
| JongYongPark | 18:2f7b820324c3 | 496 | // for (int i = 1; i < (rx_vars[channel].rx_frame_size - 1); i++) { |
| JongYongPark | 18:2f7b820324c3 | 497 | // if ((rx_vars[channel].rx_frame_buffer[i] < ' ') |
| JongYongPark | 18:2f7b820324c3 | 498 | // || (rx_vars[channel].rx_frame_buffer[i] > '~')) { |
| JongYongPark | 18:2f7b820324c3 | 499 | // valid_chars = false0; |
| JongYongPark | 18:2f7b820324c3 | 500 | // break; |
| JongYongPark | 18:2f7b820324c3 | 501 | // } else { |
| JongYongPark | 18:2f7b820324c3 | 502 | // } |
| JongYongPark | 18:2f7b820324c3 | 503 | // } |
| JongYongPark | 26:26474003e443 | 504 | valid_chars = true; |
| JongYongPark | 26:26474003e443 | 505 | #else |
| JongYongPark | 26:26474003e443 | 506 | // only valid when char is charactor |
| JongYongPark | 26:26474003e443 | 507 | for (int i = 1; i < (rx_vars[channel].rx_frame_size - 1); i++) { |
| JongYongPark | 26:26474003e443 | 508 | if ((rx_vars[channel].rx_frame_buffer[i] < ' ') |
| JongYongPark | 26:26474003e443 | 509 | || (rx_vars[channel].rx_frame_buffer[i] > '~')) { |
| JongYongPark | 26:26474003e443 | 510 | valid_chars = false; |
| JongYongPark | 26:26474003e443 | 511 | break; |
| JongYongPark | 26:26474003e443 | 512 | } else { |
| JongYongPark | 26:26474003e443 | 513 | } |
| JongYongPark | 26:26474003e443 | 514 | } |
| JongYongPark | 18:2f7b820324c3 | 515 | #endif |
| JongYongPark | 26:26474003e443 | 516 | // printf("\n============="); |
| JongYongPark | 26:26474003e443 | 517 | // print_frame_data(rx_vars[channel].rx_frame_buffer,rx_vars[channel].frame_length_save); |
| JongYongPark | 14:07669aafe0e4 | 518 | |
| JongYongPark | 26:26474003e443 | 519 | // memcpy(rx_vars[channel].rx_frame_buffer_save, rx_vars[channel].rx_frame_buffer, FRAME_BUFFER_SIZE); |
| JongYongPark | 26:26474003e443 | 520 | rx_vars[channel].is_received = true; |
| JongYongPark | 27:19ee6e15ba5e | 521 | printf("\n *** Channel[%d] Rx Finished !!! *** ", channel +1 ); |
| JongYongPark | 26:26474003e443 | 522 | if (valid_chars) { |
| JongYongPark | 0:488aa8153e15 | 523 | // //println(&(rx_frame_buffer[1])); |
| JongYongPark | 0:488aa8153e15 | 524 | // //stringReceive = string(&(rx_frame_buffer[1])); |
| JongYongPark | 0:488aa8153e15 | 525 | // //stringReceive = stringReceive.toUpperCase(); |
| JongYongPark | 0:488aa8153e15 | 526 | // //println(stringReceive); |
| JongYongPark | 0:488aa8153e15 | 527 | // printf("\nMSG(ch_%d)[%s]",channel, rx_vars[channel].rx_frame_buffer); |
| JongYongPark | 26:26474003e443 | 528 | rx_vars[channel].is_valid = true; |
| JongYongPark | 26:26474003e443 | 529 | } else { |
| JongYongPark | 0:488aa8153e15 | 530 | // printf("\nMSG_Invalid(ch_%d)[%s]",channel, rx_vars[channel].rx_frame_buffer); |
| JongYongPark | 26:26474003e443 | 531 | rx_vars[channel].is_valid = false; |
| JongYongPark | 26:26474003e443 | 532 | } |
| JongYongPark | 26:26474003e443 | 533 | // http://www.java2s.com/Tutorial/Cpp/0160__Structure/Usememcpytoduplicatestructures.htm |
| JongYongPark | 26:26474003e443 | 534 | //memcpy((void*) &rx_vars_received[channel], (void*) &rx_vars[channel], sizeof( struct RX_VARS)); |
| JongYongPark | 26:26474003e443 | 535 | //memcpy( &rx_vars_received[channel], &rx_vars[channel], sizeof( struct RX_VARS)); |
| JongYongPark | 26:26474003e443 | 536 | //memcpy((void*) & (rx_vars_received[channel]), (void*) &(rx_vars[channel]), sizeof(rx_vars[channel])); |
| JongYongPark | 26:26474003e443 | 537 | |
| JongYongPark | 26:26474003e443 | 538 | LifiRx_CopyData_FromReceivedFrame(channel); |
| JongYongPark | 26:26474003e443 | 539 | got_all_frame = true; |
| JongYongPark | 26:26474003e443 | 540 | } |
| JongYongPark | 26:26474003e443 | 541 | //if(frame_state != IDLE_STATE) println(received_data, HEX); |
| JongYongPark | 26:26474003e443 | 542 | } |
| JongYongPark | 26:26474003e443 | 543 | return got_all_frame; |
| JongYongPark | 0:488aa8153e15 | 544 | } |
| JongYongPark | 26:26474003e443 | 545 | |
| JongYongPark | 26:26474003e443 | 546 | |
| JongYongPark | 18:2f7b820324c3 | 547 | |
| JongYongPark | 18:2f7b820324c3 | 548 | void print_channel_data(int channel) |
| JongYongPark | 18:2f7b820324c3 | 549 | { |
| JongYongPark | 26:26474003e443 | 550 | #if RX_DEBUG_MAIN_LOOP |
| JongYongPark | 26:26474003e443 | 551 | printf("\nMSG(%d) valid=%d, [len:%d/%d/%d] Adc[Max=%d Min=%d Gap=%d]", |
| JongYongPark | 26:26474003e443 | 552 | channel, |
| JongYongPark | 26:26474003e443 | 553 | rx_vars[channel].is_valid, |
| JongYongPark | 26:26474003e443 | 554 | rx_vars[channel].pdu_length_count, //rx_vars[channel].pdu_length_count_save, |
| JongYongPark | 26:26474003e443 | 555 | rx_vars[channel].pdu_length, //rx_vars[channel].pdu_length_save, |
| JongYongPark | 26:26474003e443 | 556 | rx_vars[channel].frame_length, //rx_vars[channel].frame_length_save, |
| JongYongPark | 26:26474003e443 | 557 | rx_vars[channel].probe_adc_high, |
| JongYongPark | 26:26474003e443 | 558 | rx_vars[channel].probe_adc_low, |
| JongYongPark | 26:26474003e443 | 559 | rx_vars[channel].probe_adc_gap); |
| JongYongPark | 26:26474003e443 | 560 | //// print_frame_data(rx_vars[channel].rx_frame_buffer_save,rx_vars[channel].pdu_length); |
| JongYongPark | 26:26474003e443 | 561 | // print_pdu_data(rx_vars[channel].rx_frame_buffer_save + LIFI_RX_FRAME_DATA_OFFSET,rx_vars[channel].pdu_length_save); |
| JongYongPark | 26:26474003e443 | 562 | // print_frame_data(rx_vars[channel].rx_frame_buffer_save,rx_vars[channel].frame_length_save); |
| JongYongPark | 18:2f7b820324c3 | 563 | |
| JongYongPark | 26:26474003e443 | 564 | print_pdu_data(rx_vars[channel].rx_frame_buffer + LIFI_RX_FRAME_DATA_OFFSET,rx_vars[channel].pdu_length); |
| JongYongPark | 26:26474003e443 | 565 | print_frame_data(rx_vars[channel].rx_frame_buffer,rx_vars[channel].frame_length); |
| JongYongPark | 26:26474003e443 | 566 | #endif |
| JongYongPark | 18:2f7b820324c3 | 567 | } |
| JongYongPark | 0:488aa8153e15 | 568 | |
| JongYongPark | 26:26474003e443 | 569 | void print_channel_received_data(int channel) |
| JongYongPark | 26:26474003e443 | 570 | { |
| JongYongPark | 26:26474003e443 | 571 | #if RX_DEBUG_MAIN_LOOP |
| JongYongPark | 26:26474003e443 | 572 | printf("\nMSG(%d) valid=%d, [len:%d/%d/%d] Adc[Max=%d Min=%d Gap=%d]", |
| JongYongPark | 26:26474003e443 | 573 | channel, |
| JongYongPark | 26:26474003e443 | 574 | rx_vars_received[channel].is_valid, |
| JongYongPark | 26:26474003e443 | 575 | rx_vars_received[channel].pdu_length_count, |
| JongYongPark | 26:26474003e443 | 576 | rx_vars_received[channel].pdu_length, |
| JongYongPark | 26:26474003e443 | 577 | rx_vars_received[channel].frame_length, |
| JongYongPark | 26:26474003e443 | 578 | rx_vars_received[channel].probe_adc_high, |
| JongYongPark | 26:26474003e443 | 579 | rx_vars_received[channel].probe_adc_low, |
| JongYongPark | 26:26474003e443 | 580 | rx_vars_received[channel].probe_adc_gap); |
| JongYongPark | 26:26474003e443 | 581 | // print_frame_data(rx_vars[channel].rx_frame_buffer_save,rx_vars[channel].pdu_length); |
| JongYongPark | 26:26474003e443 | 582 | print_pdu_data(rx_vars_received[channel].rx_frame_buffer + LIFI_RX_FRAME_DATA_OFFSET,rx_vars_received[channel].pdu_length); |
| JongYongPark | 26:26474003e443 | 583 | print_frame_data(rx_vars_received[channel].rx_frame_buffer,rx_vars_received[channel].frame_length); |
| JongYongPark | 14:07669aafe0e4 | 584 | |
| JongYongPark | 14:07669aafe0e4 | 585 | #endif |
| JongYongPark | 0:488aa8153e15 | 586 | } |
| JongYongPark | 0:488aa8153e15 | 587 | |
| JongYongPark | 26:26474003e443 | 588 | void print_4ch_message() |
| JongYongPark | 26:26474003e443 | 589 | { |
| JongYongPark | 26:26474003e443 | 590 | // int channel = LIFI_CHANNEL_1; |
| JongYongPark | 26:26474003e443 | 591 | // for (; channel <= LIFI_ACTUAL_MAX_CHANNEL_NUM_INDEX; channel++) { |
| JongYongPark | 26:26474003e443 | 592 | // if (rx_vars[channel].is_received == false) |
| JongYongPark | 26:26474003e443 | 593 | // return; |
| JongYongPark | 26:26474003e443 | 594 | // } |
| JongYongPark | 26:26474003e443 | 595 | #if RX_DEBUG_MAIN_LOOP |
| JongYongPark | 26:26474003e443 | 596 | printf("\n----------------"); |
| JongYongPark | 26:26474003e443 | 597 | #endif |
| JongYongPark | 26:26474003e443 | 598 | print_channel_data(LIFI_CHANNEL_1); |
| JongYongPark | 26:26474003e443 | 599 | |
| JongYongPark | 26:26474003e443 | 600 | rx_vars[LIFI_CHANNEL_1].is_received = false; |
| JongYongPark | 26:26474003e443 | 601 | |
| JongYongPark | 26:26474003e443 | 602 | if (Lifi_IsChannelAvailable(LIFI_CHANNEL_2)) { |
| JongYongPark | 26:26474003e443 | 603 | print_channel_data(LIFI_CHANNEL_2); |
| JongYongPark | 26:26474003e443 | 604 | rx_vars[LIFI_CHANNEL_2].is_received = false; |
| JongYongPark | 26:26474003e443 | 605 | } |
| JongYongPark | 26:26474003e443 | 606 | if (Lifi_IsChannelAvailable(LIFI_CHANNEL_3)) { |
| JongYongPark | 26:26474003e443 | 607 | print_channel_data(LIFI_CHANNEL_3); |
| JongYongPark | 26:26474003e443 | 608 | rx_vars[LIFI_CHANNEL_3].is_received = false; |
| JongYongPark | 26:26474003e443 | 609 | } |
| JongYongPark | 26:26474003e443 | 610 | if (Lifi_IsChannelAvailable(LIFI_CHANNEL_4)) { |
| JongYongPark | 26:26474003e443 | 611 | print_channel_data(LIFI_CHANNEL_4); |
| JongYongPark | 26:26474003e443 | 612 | rx_vars[LIFI_CHANNEL_4].is_received = false; |
| JongYongPark | 26:26474003e443 | 613 | } |
| JongYongPark | 26:26474003e443 | 614 | } |
| JongYongPark | 26:26474003e443 | 615 | int LifixRx_FinishedChannlCount() |
| JongYongPark | 26:26474003e443 | 616 | { |
| JongYongPark | 26:26474003e443 | 617 | int channel = LIFI_CHANNEL_1; |
| JongYongPark | 26:26474003e443 | 618 | int got_frame_count = 0; |
| JongYongPark | 26:26474003e443 | 619 | for (; channel <= LIFI_ACTUAL_MAX_CHANNEL_NUM_INDEX; channel++) { |
| JongYongPark | 26:26474003e443 | 620 | if (rx_vars[channel].is_received == true) got_frame_count++; |
| JongYongPark | 26:26474003e443 | 621 | } |
| JongYongPark | 26:26474003e443 | 622 | return got_frame_count; |
| JongYongPark | 26:26474003e443 | 623 | } |
| JongYongPark | 26:26474003e443 | 624 | |
| JongYongPark | 26:26474003e443 | 625 | int LifixRx_PrintUnfinishedChannl() |
| JongYongPark | 26:26474003e443 | 626 | { |
| JongYongPark | 26:26474003e443 | 627 | int channel = LIFI_CHANNEL_1; |
| JongYongPark | 26:26474003e443 | 628 | int got_frame_count = 0; |
| JongYongPark | 26:26474003e443 | 629 | for (; channel <= LIFI_ACTUAL_MAX_CHANNEL_NUM_INDEX; channel++) { |
| JongYongPark | 26:26474003e443 | 630 | if (rx_vars[channel].is_received == true) ;//printf("CH[%d] Finished ooo", channel + 1); |
| JongYongPark | 26:26474003e443 | 631 | else printf("\n CH[%d]XXX", channel + 1); |
| JongYongPark | 26:26474003e443 | 632 | } |
| JongYongPark | 26:26474003e443 | 633 | return got_frame_count; |
| JongYongPark | 26:26474003e443 | 634 | } |
| JongYongPark | 26:26474003e443 | 635 | |
| JongYongPark | 26:26474003e443 | 636 | bool LifixRx_FinishedFromAllChannel() |
| JongYongPark | 26:26474003e443 | 637 | { |
| JongYongPark | 26:26474003e443 | 638 | int channel = LIFI_CHANNEL_1; |
| JongYongPark | 26:26474003e443 | 639 | for (; channel <= LIFI_ACTUAL_MAX_CHANNEL_NUM_INDEX; channel++) { |
| JongYongPark | 26:26474003e443 | 640 | if (rx_vars[channel].is_received == false) { |
| JongYongPark | 26:26474003e443 | 641 | //waiting_count_for_all_channel_finished++; |
| JongYongPark | 26:26474003e443 | 642 | return false; |
| JongYongPark | 26:26474003e443 | 643 | } |
| JongYongPark | 26:26474003e443 | 644 | } |
| JongYongPark | 26:26474003e443 | 645 | //waiting_count_for_all_channel_finished = 0; |
| JongYongPark | 26:26474003e443 | 646 | return true; |
| JongYongPark | 26:26474003e443 | 647 | } |
| JongYongPark | 0:488aa8153e15 | 648 | |
| JongYongPark | 26:26474003e443 | 649 | void LifiRx_LoopOOK() |
| JongYongPark | 26:26474003e443 | 650 | { |
| JongYongPark | 26:26474003e443 | 651 | static uint64_t loop_count = 0; |
| JongYongPark | 26:26474003e443 | 652 | int finished_channel = 0; |
| JongYongPark | 26:26474003e443 | 653 | //printf("!"); |
| JongYongPark | 26:26474003e443 | 654 | // for 1 channel, it works well. |
| JongYongPark | 26:26474003e443 | 655 | // data corrupted when open 2 channels |
| JongYongPark | 26:26474003e443 | 656 | // LIFI_RX_SYMBOL_PERIOD_SEC (0.01) = works well for 2 channels ********* |
| JongYongPark | 26:26474003e443 | 657 | rx_loop_ook_4ch(LIFI_CHANNEL_1); |
| JongYongPark | 26:26474003e443 | 658 | if (Lifi_IsChannelAvailable(LIFI_CHANNEL_2)) |
| JongYongPark | 26:26474003e443 | 659 | rx_loop_ook_4ch(LIFI_CHANNEL_2); |
| JongYongPark | 26:26474003e443 | 660 | if (Lifi_IsChannelAvailable(LIFI_CHANNEL_3)) |
| JongYongPark | 26:26474003e443 | 661 | rx_loop_ook_4ch(LIFI_CHANNEL_3); |
| JongYongPark | 26:26474003e443 | 662 | if (Lifi_IsChannelAvailable(LIFI_CHANNEL_4)) |
| JongYongPark | 26:26474003e443 | 663 | rx_loop_ook_4ch(LIFI_CHANNEL_4); |
| JongYongPark | 26:26474003e443 | 664 | |
| JongYongPark | 26:26474003e443 | 665 | |
| JongYongPark | 26:26474003e443 | 666 | // if(LifixRx_FinishedFromAllChannel()){ |
| JongYongPark | 26:26474003e443 | 667 | // print_4ch_message(); |
| JongYongPark | 26:26474003e443 | 668 | // loop_count = 0; |
| JongYongPark | 26:26474003e443 | 669 | // } |
| JongYongPark | 26:26474003e443 | 670 | // else { |
| JongYongPark | 26:26474003e443 | 671 | // loop_count++; |
| JongYongPark | 26:26474003e443 | 672 | // if(loop_count > 2 ) |
| JongYongPark | 26:26474003e443 | 673 | // { |
| JongYongPark | 26:26474003e443 | 674 | // LifixRx_PrintUnFinishedChannl(); |
| JongYongPark | 26:26474003e443 | 675 | // print_4ch_message(); |
| JongYongPark | 26:26474003e443 | 676 | // LifiRx_Init(); |
| JongYongPark | 26:26474003e443 | 677 | // loop_count = 0; |
| JongYongPark | 26:26474003e443 | 678 | // } |
| JongYongPark | 26:26474003e443 | 679 | // } |
| JongYongPark | 26:26474003e443 | 680 | |
| JongYongPark | 26:26474003e443 | 681 | finished_channel = LifixRx_FinishedChannlCount(); |
| JongYongPark | 26:26474003e443 | 682 | if( finished_channel == LIFI_ACTUAL_MAX_CHANNEL_NUM ) { |
| JongYongPark | 26:26474003e443 | 683 | print_4ch_message(); |
| JongYongPark | 26:26474003e443 | 684 | loop_count = 0; |
| JongYongPark | 26:26474003e443 | 685 | } |
| JongYongPark | 26:26474003e443 | 686 | // 4 channel 에서 하나의 유효한 channel 에서 데이타를 받으면 나머지는 어디서 문제가 발생했는지 알 수 있다. |
| JongYongPark | 26:26474003e443 | 687 | else if(finished_channel >= 1 ) { |
| JongYongPark | 26:26474003e443 | 688 | loop_count++; |
| JongYongPark | 26:26474003e443 | 689 | if(loop_count > 1000 ) { |
| JongYongPark | 26:26474003e443 | 690 | printf("\nHERE 1 Finished channel count (%d)",finished_channel); |
| JongYongPark | 26:26474003e443 | 691 | LifixRx_PrintUnfinishedChannl(); |
| JongYongPark | 26:26474003e443 | 692 | print_4ch_message(); |
| JongYongPark | 26:26474003e443 | 693 | LifiRx_Init(); |
| JongYongPark | 26:26474003e443 | 694 | loop_count = 0; |
| JongYongPark | 26:26474003e443 | 695 | } |
| JongYongPark | 26:26474003e443 | 696 | } |
| JongYongPark | 26:26474003e443 | 697 | // else |
| JongYongPark | 26:26474003e443 | 698 | // { |
| JongYongPark | 26:26474003e443 | 699 | // loop_count++; |
| JongYongPark | 26:26474003e443 | 700 | // if(loop_count > 10000000 ) |
| JongYongPark | 26:26474003e443 | 701 | // { |
| JongYongPark | 26:26474003e443 | 702 | // printf("\nHERE 2 Finished(%d)",finished_channel); |
| JongYongPark | 26:26474003e443 | 703 | // LifixRx_PrintUnfinishedChannl(); |
| JongYongPark | 26:26474003e443 | 704 | // print_4ch_message(); |
| JongYongPark | 26:26474003e443 | 705 | // LifiRx_Init(); |
| JongYongPark | 26:26474003e443 | 706 | // loop_count = 0; |
| JongYongPark | 26:26474003e443 | 707 | // } |
| JongYongPark | 26:26474003e443 | 708 | // } |
| JongYongPark | 0:488aa8153e15 | 709 | } |
| JongYongPark | 0:488aa8153e15 | 710 | |
| JongYongPark | 0:488aa8153e15 | 711 | // the loop routine runs over and over again forever: |
| JongYongPark | 0:488aa8153e15 | 712 | |
| JongYongPark | 26:26474003e443 | 713 | void LifiRx_SampleSignalEdge() |
| JongYongPark | 26:26474003e443 | 714 | { |
| JongYongPark | 26:26474003e443 | 715 | int sensorValue, sensorValue2, sensorValue3, sensorValue4; |
| JongYongPark | 0:488aa8153e15 | 716 | |
| JongYongPark | 26:26474003e443 | 717 | sensorValue = LifiRx_AdcRead(LIFI_CHANNEL_1); |
| JongYongPark | 26:26474003e443 | 718 | if (Lifi_IsChannelAvailable(LIFI_CHANNEL_2)) |
| JongYongPark | 26:26474003e443 | 719 | sensorValue2 = LifiRx_AdcRead(LIFI_CHANNEL_2); |
| JongYongPark | 26:26474003e443 | 720 | if (Lifi_IsChannelAvailable(LIFI_CHANNEL_3)) |
| JongYongPark | 26:26474003e443 | 721 | sensorValue3 = LifiRx_AdcRead(LIFI_CHANNEL_3); |
| JongYongPark | 26:26474003e443 | 722 | if (Lifi_IsChannelAvailable(LIFI_CHANNEL_4)) |
| JongYongPark | 26:26474003e443 | 723 | sensorValue4 = LifiRx_AdcRead(LIFI_CHANNEL_4); |
| JongYongPark | 0:488aa8153e15 | 724 | |
| JongYongPark | 26:26474003e443 | 725 | sample_signal_edge_4ch(LIFI_CHANNEL_1, sensorValue); |
| JongYongPark | 26:26474003e443 | 726 | if (Lifi_IsChannelAvailable(LIFI_CHANNEL_2)) |
| JongYongPark | 26:26474003e443 | 727 | sample_signal_edge_4ch(LIFI_CHANNEL_2, sensorValue2); |
| JongYongPark | 26:26474003e443 | 728 | if (Lifi_IsChannelAvailable(LIFI_CHANNEL_3)) |
| JongYongPark | 26:26474003e443 | 729 | sample_signal_edge_4ch(LIFI_CHANNEL_3, sensorValue3); |
| JongYongPark | 26:26474003e443 | 730 | if (Lifi_IsChannelAvailable(LIFI_CHANNEL_4)) |
| JongYongPark | 26:26474003e443 | 731 | sample_signal_edge_4ch(LIFI_CHANNEL_4, sensorValue4); |
| JongYongPark | 0:488aa8153e15 | 732 | } |
| JongYongPark | 0:488aa8153e15 | 733 | |
| JongYongPark | 26:26474003e443 | 734 | void LifiRx_Init() |
| JongYongPark | 26:26474003e443 | 735 | { |
| JongYongPark | 26:26474003e443 | 736 | rx_vars[LIFI_CHANNEL_1].rx_frame_index = -1; |
| JongYongPark | 26:26474003e443 | 737 | rx_vars[LIFI_CHANNEL_2].rx_frame_index = -1; |
| JongYongPark | 26:26474003e443 | 738 | rx_vars[LIFI_CHANNEL_3].rx_frame_index = -1; |
| JongYongPark | 26:26474003e443 | 739 | rx_vars[LIFI_CHANNEL_4].rx_frame_index = -1; |
| JongYongPark | 26:26474003e443 | 740 | rx_vars[LIFI_CHANNEL_1].rx_frame_size = -1; |
| JongYongPark | 26:26474003e443 | 741 | rx_vars[LIFI_CHANNEL_2].rx_frame_size = -1; |
| JongYongPark | 26:26474003e443 | 742 | rx_vars[LIFI_CHANNEL_3].rx_frame_size = -1; |
| JongYongPark | 26:26474003e443 | 743 | rx_vars[LIFI_CHANNEL_4].rx_frame_size = -1; |
| JongYongPark | 26:26474003e443 | 744 | rx_vars[LIFI_CHANNEL_1].frame_state = IDLE_STATE; |
| JongYongPark | 26:26474003e443 | 745 | rx_vars[LIFI_CHANNEL_2].frame_state = IDLE_STATE; |
| JongYongPark | 26:26474003e443 | 746 | rx_vars[LIFI_CHANNEL_3].frame_state = IDLE_STATE; |
| JongYongPark | 26:26474003e443 | 747 | rx_vars[LIFI_CHANNEL_4].frame_state = IDLE_STATE; |
| JongYongPark | 0:488aa8153e15 | 748 | |
| JongYongPark | 26:26474003e443 | 749 | rx_vars[LIFI_CHANNEL_1].is_received = false; |
| JongYongPark | 26:26474003e443 | 750 | rx_vars[LIFI_CHANNEL_2].is_received = false; |
| JongYongPark | 26:26474003e443 | 751 | rx_vars[LIFI_CHANNEL_3].is_received = false; |
| JongYongPark | 26:26474003e443 | 752 | rx_vars[LIFI_CHANNEL_4].is_received = false; |
| JongYongPark | 14:07669aafe0e4 | 753 | } |