| 1 | #include "DataPacker.h" |
|---|
| 2 | #include <stdio.h> |
|---|
| 3 | |
|---|
| 4 | unsigned char * DataPacker::msg; |
|---|
| 5 | |
|---|
| 6 | unsigned char * DataPacker::packData(STATION *station) { |
|---|
| 7 | int pos = 26; |
|---|
| 8 | DataPacker packer; |
|---|
| 9 | msg = packer.staticDataPack(station); |
|---|
| 10 | pos = packer.dynamicDataPack(station, 5, pos); |
|---|
| 11 | pos = packer.dynamicDataPack(station, 6, pos); |
|---|
| 12 | pos = packer.dynamicDataPack(station, 7, pos); |
|---|
| 13 | pos = packer.dynamicDataPack(station, 8, pos); |
|---|
| 14 | // Update data for BYTE 9, 16, 21, 22, 23, 24 |
|---|
| 15 | |
|---|
| 16 | // what is the current metering rate? |
|---|
| 17 | // check each LDS, if there is demand detector, the downstream node the |
|---|
| 18 | // ldsMap[i].dataPack[22-1] = ldsMap[i].dataPack[9-1] = ; |
|---|
| 19 | |
|---|
| 20 | // will need to check if queue override is enabled (Currently, no queue |
|---|
| 21 | // ldsMap[i].dataPack[16-1] = ; |
|---|
| 22 | |
|---|
| 23 | // byte 23: MAINLINE total volume |
|---|
| 24 | msg[23 - 1] = station->MlTotVol; |
|---|
| 25 | |
|---|
| 26 | // byte 24: opposite total volume |
|---|
| 27 | msg[24 - 1] = station->OppTotVol; |
|---|
| 28 | |
|---|
| 29 | // last BYTE: checksum |
|---|
| 30 | msg[station->length - 1] = |
|---|
| 31 | packer.chksum(msg, station->length - 1 - 1); |
|---|
| 32 | |
|---|
| 33 | for (int j = 0; j < station->length; j++) { |
|---|
| 34 | printf("%02X", msg[j]); |
|---|
| 35 | } |
|---|
| 36 | printf("\n"); |
|---|
| 37 | |
|---|
| 38 | return msg; |
|---|
| 39 | } |
|---|
| 40 | |
|---|
| 41 | int DataPacker::dynamicDataPack(STATION *station, int packNo, int pos) { |
|---|
| 42 | int i, j, vol, occ, haveData; |
|---|
| 43 | //used for data byte 23 and 24 |
|---|
| 44 | station->MlTotVol = 0; |
|---|
| 45 | station->OppTotVol = 0; |
|---|
| 46 | |
|---|
| 47 | for (j = 1; j <= 8; j++) { |
|---|
| 48 | |
|---|
| 49 | if (DataAvail(msg[packNo - 1], j)) { |
|---|
| 50 | // loop at bit j has data |
|---|
| 51 | for (int lane = 0; lane < station->loops.size(); lane++) { |
|---|
| 52 | // what's the corresponding loop of bit j |
|---|
| 53 | char * currLoopLoc = station->loops.at(lane)->loop_loc; |
|---|
| 54 | if (packNo == 5) |
|---|
| 55 | haveData = strcmp(currLoopLoc, dp5[j - 1]); |
|---|
| 56 | else if (packNo == 6) |
|---|
| 57 | haveData = strcmp(currLoopLoc, dp6[j - 1]); |
|---|
| 58 | else if (packNo == 7) |
|---|
| 59 | haveData = strcmp(currLoopLoc, dp7[j - 1]); |
|---|
| 60 | else if (packNo == 8) |
|---|
| 61 | haveData = strcmp(currLoopLoc, dp8[j - 1]); |
|---|
| 62 | else |
|---|
| 63 | return -1; |
|---|
| 64 | |
|---|
| 65 | // if we have data (strcmp returns 0 if a string match) |
|---|
| 66 | if (haveData == 0) { |
|---|
| 67 | LOOP *currLoop = station->loops.at(lane); |
|---|
| 68 | vol = currLoop->vol; |
|---|
| 69 | occ = (int) (currLoop->occ * 900 + 0.5); |
|---|
| 70 | cout << "Volume: " << vol << endl; |
|---|
| 71 | cout << "OCC : " << occ << endl; |
|---|
| 72 | VOLOCC packedVOLOCC = packVOLOCC(vol, occ); |
|---|
| 73 | pos++; |
|---|
| 74 | msg[pos - 1] = packedVOLOCC.high; |
|---|
| 75 | pos++; |
|---|
| 76 | msg[pos - 1] = packedVOLOCC.low; |
|---|
| 77 | |
|---|
| 78 | if (packNo == 5) { |
|---|
| 79 | station->MlTotVol += vol; |
|---|
| 80 | } else if (packNo == 6) { |
|---|
| 81 | station->OppTotVol += vol; |
|---|
| 82 | } |
|---|
| 83 | } |
|---|
| 84 | } |
|---|
| 85 | } |
|---|
| 86 | } |
|---|
| 87 | return pos; |
|---|
| 88 | } |
|---|
| 89 | |
|---|
| 90 | unsigned char * DataPacker::staticDataPack(STATION *station) { |
|---|
| 91 | int j; |
|---|
| 92 | // Allocate memory for dataPack |
|---|
| 93 | unsigned char *dataPack = (unsigned char *) calloc(sizeof(unsigned char), station->length); |
|---|
| 94 | |
|---|
| 95 | // dataPack 5-8: lane config |
|---|
| 96 | char d5 = 0, d6 = 0, d7 = 0, d8 = 0; |
|---|
| 97 | for (j = 0; j < station->loops.size(); j++) { |
|---|
| 98 | for (int k = 0; k < 8; k++) { |
|---|
| 99 | char * currLoopLoc = station->loops.at(j)->loop_loc; |
|---|
| 100 | if (strcmp(currLoopLoc, dp5[k]) == 0) |
|---|
| 101 | d5 += pow(2, k); |
|---|
| 102 | if (strcmp(currLoopLoc, dp6[k]) == 0) |
|---|
| 103 | d6 += pow(2, k); |
|---|
| 104 | if (strcmp(currLoopLoc, dp7[k]) == 0) |
|---|
| 105 | d7 += pow(2, k); |
|---|
| 106 | if (strcmp(currLoopLoc, dp8[k]) == 0) |
|---|
| 107 | d8 += pow(2, k); |
|---|
| 108 | } |
|---|
| 109 | } |
|---|
| 110 | dataPack[5 - 1] = d5; |
|---|
| 111 | dataPack[6 - 1] = d6; |
|---|
| 112 | dataPack[7 - 1] = d7; |
|---|
| 113 | dataPack[8 - 1] = d8; |
|---|
| 114 | |
|---|
| 115 | // dataPack 1: Drop number, i.e. station address |
|---|
| 116 | dataPack[1 - 1] = station->drop; |
|---|
| 117 | // dataPack2 (2 bytes per loop) |
|---|
| 118 | dataPack[2 - 1] = station->loops.size() * 2 + Fixed_Byte_To_Checksum; |
|---|
| 119 | |
|---|
| 120 | // dataPacket 3 (lowbyte: # of mainline loops, highbyte: # of opposite loops) |
|---|
| 121 | int low = 0, high = 0; |
|---|
| 122 | for (j = 1; j <= 6; j++) { |
|---|
| 123 | low += DataAvail(dataPack[5 - 1], j); |
|---|
| 124 | high += DataAvail(dataPack[6 - 1], j); |
|---|
| 125 | } |
|---|
| 126 | high = high << 4; |
|---|
| 127 | dataPack[3 - 1] = high | low; |
|---|
| 128 | |
|---|
| 129 | // dataPack4 (Miscl. flags: samples are: 80, A0, E0, 00) |
|---|
| 130 | dataPack[4 - 1] = 0xA0; |
|---|
| 131 | |
|---|
| 132 | // dataPack 9: initialized as 00 (meaning no metering); need to be updated every 30 sec |
|---|
| 133 | dataPack[9 - 1] = 0; |
|---|
| 134 | |
|---|
| 135 | // datadataPack 10-13: lane malfunction? Assuming all functional |
|---|
| 136 | dataPack[10 - 1] = 0; |
|---|
| 137 | dataPack[11 - 1] = 0; |
|---|
| 138 | dataPack[12 - 1] = 0; |
|---|
| 139 | dataPack[13 - 1] = 0; |
|---|
| 140 | |
|---|
| 141 | // dataPack 14-22: ramp metering data |
|---|
| 142 | // BYTE 16 and 22 need to be updated every 30 sec |
|---|
| 143 | bool found = false; |
|---|
| 144 | for (j = 0; j < station->loops.size(); j++) { |
|---|
| 145 | if (strcmp(station->loops.at(j)->loop_loc, "DEMAND") == 0) { |
|---|
| 146 | found = true; |
|---|
| 147 | break; |
|---|
| 148 | } |
|---|
| 149 | } |
|---|
| 150 | if (found) { |
|---|
| 151 | // BYTE 14: mostly 07, some are 05, 03, 00 |
|---|
| 152 | dataPack[14 - 1] = 0x07; |
|---|
| 153 | // mostly 06(TOD table 1); some are 0B (No metering) or 05(traffic responsive) |
|---|
| 154 | dataPack[15 - 1] = 0x06; |
|---|
| 155 | // most 00, some are 01 (queue override) or 80(Meter ON sign) |
|---|
| 156 | dataPack[16 - 1] = 0x00; |
|---|
| 157 | // Field Manual Rate |
|---|
| 158 | dataPack[17 - 1] = 0xFF; |
|---|
| 159 | // TOC Manual Rate |
|---|
| 160 | dataPack[18 - 1] = 0xFF; |
|---|
| 161 | // PSO Manual Rate |
|---|
| 162 | dataPack[19 - 1] = 0xFF; |
|---|
| 163 | // CORM Rate |
|---|
| 164 | dataPack[20 - 1] = 0xFF; |
|---|
| 165 | // Local Responsive Rate. DON'T UNDERSTAND YET |
|---|
| 166 | dataPack[21 - 1] = 0x00; |
|---|
| 167 | // TOD Rate: need to query RAMP plugin! |
|---|
| 168 | dataPack[22 - 1] = 0x00; |
|---|
| 169 | }// LDS: NO Metering |
|---|
| 170 | else { |
|---|
| 171 | dataPack[14 - 1] = 0x00; |
|---|
| 172 | dataPack[15 - 1] = 0x0B; |
|---|
| 173 | dataPack[16 - 1] = 0x00; |
|---|
| 174 | dataPack[17 - 1] = 0xFF; |
|---|
| 175 | dataPack[18 - 1] = 0xFF; |
|---|
| 176 | dataPack[19 - 1] = 0xFF; |
|---|
| 177 | dataPack[20 - 1] = 0xFF; |
|---|
| 178 | dataPack[21 - 1] = 0x00; |
|---|
| 179 | dataPack[22 - 1] = 0x00; |
|---|
| 180 | } |
|---|
| 181 | |
|---|
| 182 | // dataPack 23-24: sum of mainline/Opp traffic data; need to be updated every 30 sec |
|---|
| 183 | station->MlTotVol = 0; |
|---|
| 184 | station->OppTotVol = 0; |
|---|
| 185 | dataPack[23 - 1] = station->MlTotVol; |
|---|
| 186 | dataPack[24 - 1] = station->OppTotVol; |
|---|
| 187 | |
|---|
| 188 | // dataPack 25-26: BYTE 25 is fixed, i.e. 03; BYTE 26 is either 0xA2 or 0x84 |
|---|
| 189 | dataPack[25 - 1] = 0x03; |
|---|
| 190 | dataPack[26 - 1] = 0x84; |
|---|
| 191 | |
|---|
| 192 | return dataPack; |
|---|
| 193 | } |
|---|
| 194 | |
|---|
| 195 | bool DataPacker::DataAvail(char flag, int num) { |
|---|
| 196 | int mag, fel; |
|---|
| 197 | |
|---|
| 198 | // find mask value |
|---|
| 199 | if (num == 1) |
|---|
| 200 | mag = 0x01; |
|---|
| 201 | else if (num == 2) |
|---|
| 202 | mag = 0x02; |
|---|
| 203 | else if (num == 3) |
|---|
| 204 | mag = 0x04; |
|---|
| 205 | else if (num == 4) |
|---|
| 206 | mag = 0x08; |
|---|
| 207 | else if (num == 5) |
|---|
| 208 | mag = 0x10; |
|---|
| 209 | else if (num == 6) |
|---|
| 210 | mag = 0x20; |
|---|
| 211 | else if (num == 7) |
|---|
| 212 | mag = 0x40; |
|---|
| 213 | else if (num == 8) |
|---|
| 214 | mag = 0x80; |
|---|
| 215 | |
|---|
| 216 | fel = flag & mag; |
|---|
| 217 | fel = fel >> (num - 1); |
|---|
| 218 | |
|---|
| 219 | if (fel == 1) |
|---|
| 220 | return true; |
|---|
| 221 | else |
|---|
| 222 | return false; |
|---|
| 223 | } |
|---|
| 224 | |
|---|
| 225 | // checksum based on data from byte 1 (after 0DOA) to the second last byte (the |
|---|
| 226 | char DataPacker::chksum(unsigned char *dataptr, int len) { |
|---|
| 227 | int i; |
|---|
| 228 | unsigned char checksum = 0; |
|---|
| 229 | |
|---|
| 230 | for (i = 0; i < len; i++) |
|---|
| 231 | checksum += dataptr[i]; |
|---|
| 232 | |
|---|
| 233 | return checksum; |
|---|
| 234 | } |
|---|
| 235 | |
|---|
| 236 | // convert vol and occ data to a two-byte data packet |
|---|
| 237 | VOLOCC DataPacker::packVOLOCC(int vol, int occ) |
|---|
| 238 | { |
|---|
| 239 | int bit, i; |
|---|
| 240 | int high, low; |
|---|
| 241 | int high_high = 0, high_low = 0; |
|---|
| 242 | VOLOCC com; |
|---|
| 243 | |
|---|
| 244 | // occ data: 10 bits |
|---|
| 245 | low = 0; |
|---|
| 246 | for (i=9; i>=0; i--) |
|---|
| 247 | { |
|---|
| 248 | if (i >= 8) |
|---|
| 249 | { |
|---|
| 250 | bit = ((occ >> i) & 1); |
|---|
| 251 | high_low += pow(2, (i - 8)) * bit; |
|---|
| 252 | } |
|---|
| 253 | // lower byte |
|---|
| 254 | else |
|---|
| 255 | { |
|---|
| 256 | bit = ((occ >> i) & 1); |
|---|
| 257 | low += pow(2, i) * bit; |
|---|
| 258 | } |
|---|
| 259 | } |
|---|
| 260 | |
|---|
| 261 | // vol: 6 bits (1. vol, shift to the left for two times; 2. combine data) |
|---|
| 262 | high_high = vol << 2; |
|---|
| 263 | high = high_high | high_low; |
|---|
| 264 | |
|---|
| 265 | com.high = high; |
|---|
| 266 | com.low = low; |
|---|
| 267 | |
|---|
| 268 | return com; |
|---|
| 269 | } |
|---|