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