├── LICENSE ├── README.md ├── kserial.c ├── kserial.h ├── kserial_conf.h └── kstatus.h /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 KitSprout 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### kSerial Packet Format 2 | 3 | 4 | 5 | | byte 1 | byte 2 | byte 3 | byte 4 | byte 5 | byte 6 | byte 7 | ...   | byte L + 8 | 6 | | :----: | :----: | :----: | :----: | :----: | :----: | :----: | :----: | :--------: | 7 | |   HK   |   HS   |   TP   |   LN   |   P1   |   P2   |   CK   |   DN   |   ER | 8 | 9 | | name | information | 10 | | :--: | ------------------------------ | 11 | | HK | header 'K' (75) | 12 | | HS | header 'S' (83) | 13 | | TP | data type (4-bit) | 14 | | LN | data length (12-bit, 0~4095) | 15 | | P1 | parameter 1 | 16 | | P2 | parameter 2 | 17 | | CK | checksum | 18 | | ... | ... | 19 | | DN | data | 20 | | ER | finish '\r' (13) | 21 | 22 | | type | binrary | 23 | | :------: | ------------ | 24 | | uint8 | 0x0, 4'b0000 | 25 | | uint16  | 0x1, 4'b0001 | 26 | | uint32 | 0x2, 4'b0010 | 27 | | uint64 | 0x3, 4'b0011 | 28 | | int8 | 0x4, 4'b0100 | 29 | | int16   | 0x5, 4'b0101 | 30 | | int32 | 0x6, 4'b0110 | 31 | | int64 | 0x7, 4'b0111 | 32 | | half   | 0x9, 4'b1001 | 33 | | float | 0xA, 4'b1010 | 34 | | double | 0xB, 4'b1011 | 35 | | R0 | 0x8, 4'b1000 | 36 | | R1 | 0xC, 4'b1100 | 37 | | R2 | 0xD, 4'b1101 | 38 | | R3 | 0xE, 4'b1110 | 39 | | R4 | 0xF, 4'b1111 | 40 | 41 | more information 42 | 43 | 44 | ### Library 45 | 46 | [kSerial_Python](https://github.com/KitSprout/kSerial_Python) 47 | [kSerial_Matlab](https://github.com/KitSprout/kSerial_Matlab) 48 | [kSerialApp](https://github.com/KitSprout/kSerialApp) 49 | 50 | ### Youtube DEMO Video 51 | 52 | 53 | -------------------------------------------------------------------------------- /kserial.c: -------------------------------------------------------------------------------- 1 | /** 2 | * __ ____ 3 | * / /__ _ __ / __/ __ 4 | * / //_/(_)/ /_ / / ___ ____ ___ __ __ / /_ 5 | * / ,< / // __/_\ \ / _ \ / __// _ \/ // // __/ 6 | * /_/|_|/_/ \__//___// .__//_/ \___/\_,_/ \__/ 7 | * /_/ github.com/KitSprout 8 | * 9 | * @file kserial.c 10 | * @author KitSprout 11 | * @brief kserial packet format : 12 | * byte 1 : header 'K' (75) [HK] 13 | * byte 2 : header 'S' (83) [HS] 14 | * byte 3 : data type (4-bit) [TP] 15 | * byte 4 : data bytes (12-bit) [LN] 16 | * byte 5 : parameter 1 [P1] 17 | * byte 6 : parameter 2 [P2] 18 | * byte 7 : checksum [CK] 19 | * ... 20 | * byte L-1 : data [DN] 21 | * byte L : finish '\r' (13) [ER] 22 | */ 23 | 24 | /* Includes --------------------------------------------------------------------------------*/ 25 | #include 26 | #include 27 | #include "kserial.h" 28 | 29 | /* Define ----------------------------------------------------------------------------------*/ 30 | /* Macro -----------------------------------------------------------------------------------*/ 31 | /* Typedef ---------------------------------------------------------------------------------*/ 32 | /* Variables -------------------------------------------------------------------------------*/ 33 | 34 | const char KSERIAL_VERSION[] = KSERIAL_VERSION_DEFINE; 35 | 36 | #if KSERIAL_SEND_ENABLE 37 | static uint8_t sbuffer[KS_MAX_SEND_BUFFER_SIZE] = {0}; 38 | #endif 39 | #if KSERIAL_RECV_ENABLE 40 | static uint8_t rbuffer[KS_MAX_RECV_BUFFER_SIZE] = {0}; 41 | #endif 42 | 43 | #if KSERIAL_RECV_TREAD_ENABLE 44 | static uint8_t pkbuffer[KSERIAL_RECV_PACKET_BUFFER_LENS] = {0}; 45 | static kserial_packet_t kspacket[KSERIAL_MAX_PACKET_LENS] = {0}; 46 | kserial_t ks = 47 | { 48 | .size = KSERIAL_RECV_PACKET_BUFFER_LENS, 49 | .count = 0, 50 | .buffer = pkbuffer, 51 | .packet = kspacket 52 | }; 53 | #endif 54 | 55 | const uint32_t KS_TYPE_SIZE[KSERIAL_TYPE_LENS] = 56 | { 57 | 1, 2, 4, 8, 58 | 1, 2, 4, 8, 59 | 0, 2, 4, 8, 60 | 0, 0, 0, 0 61 | }; 62 | 63 | const char KS_TYPE_STRING[KSERIAL_TYPE_LENS][4] = 64 | { 65 | "U8", "U16", "U32", "U64", 66 | "I8", "I16", "I32", "I64", 67 | "R0", "F16", "F32", "F64", 68 | "R1", "R2", "R3", "R4", 69 | }; 70 | 71 | const char KS_TYPE_FORMATE[KSERIAL_TYPE_LENS][8] = 72 | { 73 | "%4d", "%6d", "%11d", "%20d", 74 | "%4d", "%6d", "%11d", "%20d", 75 | "", "%.6f", "%.6f", "%.6f", 76 | "", "", "", "" 77 | }; 78 | 79 | /* Prototypes ------------------------------------------------------------------------------*/ 80 | /* Functions -------------------------------------------------------------------------------*/ 81 | 82 | /** 83 | * @brief kserial_get_typesize 84 | */ 85 | #if 1 86 | #define kserial_get_typesize(__TYPE) KS_TYPE_SIZE[__TYPE] 87 | #else 88 | uint32_t kserial_get_typesize(uint32_t type) 89 | { 90 | type &= 0x0F; 91 | if ((type > KS_F64) || (type == KS_R0)) 92 | { 93 | return (0); 94 | } 95 | else 96 | { 97 | return (1 << (type & 0x03)); 98 | } 99 | } 100 | #endif 101 | 102 | /** 103 | * @brief kserial_check_header 104 | */ 105 | uint32_t kserial_check_header(const uint8_t *packet, void *param, uint32_t *type, uint32_t *nbyte) 106 | { 107 | uint32_t checksum = 0; 108 | 109 | if ((packet[0] == 'K') && (packet[1] == 'S')) 110 | { 111 | *type = packet[2] >> 4; 112 | *nbyte = (((uint16_t)packet[2] << 8) | packet[3]) & 0x0FFF; 113 | for (uint32_t i = 2; i < 6; i++) 114 | { 115 | checksum += packet[i]; 116 | } 117 | checksum &= 0xFF; 118 | if (packet[6] == checksum) 119 | { 120 | ((uint8_t*)param)[0] = packet[4]; 121 | ((uint8_t*)param)[1] = packet[5]; 122 | return KS_OK; 123 | } 124 | } 125 | 126 | return KS_ERROR; 127 | } 128 | 129 | /** 130 | * @brief kserial_check_end 131 | */ 132 | uint32_t kserial_check_end(const uint8_t *packet, uint32_t nbyte) 133 | { 134 | if (packet[nbyte + 8 - 1] == '\r') 135 | { 136 | return KS_OK; 137 | } 138 | 139 | return KS_ERROR; 140 | } 141 | 142 | /** 143 | * @brief kserial_check 144 | */ 145 | uint32_t kserial_check(const uint8_t *packet, void *param, uint32_t *type, uint32_t *nbyte) 146 | { 147 | uint32_t checksum = 0; 148 | 149 | if ((packet[0] == 'K') && (packet[1] == 'S')) 150 | { 151 | *type = packet[2] >> 4; 152 | *nbyte = (((uint16_t)packet[2] << 8) | packet[3]) & 0x0FFF; 153 | for (uint32_t i = 2; i < 6; i++) 154 | { 155 | checksum += packet[i]; 156 | } 157 | checksum &= 0xFF; 158 | if ((packet[6] == checksum) && (packet[*nbyte + 8 - 1] == '\r')) 159 | { 160 | ((uint8_t*)param)[0] = packet[4]; 161 | ((uint8_t*)param)[1] = packet[5]; 162 | return KS_OK; 163 | } 164 | } 165 | 166 | return KS_ERROR; 167 | } 168 | 169 | /** 170 | * @brief kserial_get_bytesdata 171 | */ 172 | void kserial_get_bytesdata(const uint8_t *packet, void *pdata, uint32_t nbyte) 173 | { 174 | for (uint32_t i = 0; i < nbyte; i++) 175 | { 176 | ((uint8_t*)pdata)[i] = packet[7 + i]; 177 | } 178 | } 179 | 180 | /** 181 | * @brief kserial_pack 182 | */ 183 | uint32_t kserial_pack(uint8_t *packet, const void *param, uint32_t type, uint32_t lens, const void *pdata) 184 | { 185 | uint32_t databytes; // in bytes 186 | uint32_t checksum = 0; 187 | uint32_t typesize = kserial_get_typesize(type); 188 | 189 | databytes = (typesize > 1) ? (lens * typesize) : (lens); 190 | 191 | packet[0] = 'K'; // header 'K' 192 | packet[1] = 'S'; // header 'S' 193 | packet[2] = (type << 4) | (databytes >> 8); // data type (4bit) 194 | packet[3] = databytes; // data bytes (12bit) 195 | 196 | if (param != NULL) 197 | { 198 | packet[4] = ((uint8_t*)param)[0]; // parameter 1 199 | packet[5] = ((uint8_t*)param)[1]; // parameter 2 200 | } 201 | else 202 | { 203 | packet[4] = 0; 204 | packet[5] = 0; 205 | } 206 | for (uint32_t i = 2; i < 6; i++) 207 | { 208 | checksum += packet[i]; 209 | } 210 | packet[6] = checksum; // checksum 211 | 212 | if (pdata != NULL) 213 | { 214 | for (uint32_t i = 0; i < databytes; i++) 215 | { 216 | packet[7 + i] = ((uint8_t*)pdata)[i]; // data ... 217 | } 218 | } 219 | packet[7 + databytes] = '\r'; // finish '\r' 220 | 221 | return (databytes + 8); 222 | } 223 | 224 | /** 225 | * @brief kserial_unpack 226 | */ 227 | uint32_t kserial_unpack(const uint8_t *packet, void *param, uint32_t *type, uint32_t *nbyte, void *pdata) 228 | { 229 | uint32_t status; 230 | 231 | status = kserial_check(packet, param, type, nbyte); 232 | if ((status == KS_OK) && (pdata != NULL)) 233 | { 234 | for (uint32_t i = 0; i < *nbyte; i++) 235 | { 236 | ((uint8_t*)pdata)[i] = packet[7 + i]; 237 | } 238 | } 239 | 240 | return status; 241 | } 242 | 243 | /** 244 | * @brief kserial_unpack_buffer 245 | */ 246 | uint32_t kserial_unpack_buffer(const uint8_t *buffer, uint32_t buffersize, kserial_packet_t *ksp, uint32_t *count) 247 | { 248 | uint32_t status; 249 | uint32_t offset = 0; 250 | uint32_t newindex = 0; 251 | uint32_t typesize; 252 | 253 | *count = 0; 254 | 255 | while ((buffersize - offset) > 7) // min packet bytes = 8 256 | { 257 | status = kserial_check(&buffer[offset], ksp[*count].param, &ksp[*count].type, &ksp[*count].nbyte); 258 | if (status == KS_OK) 259 | { 260 | if ((offset + ksp[*count].nbyte + 8) > buffersize) 261 | { 262 | break; 263 | } 264 | ksp[*count].data = (void *)malloc(ksp[*count].nbyte * sizeof(uint8_t)); 265 | kserial_get_bytesdata(&buffer[offset], ksp[*count].data, ksp[*count].nbyte); 266 | typesize = kserial_get_typesize(ksp[*count].type); 267 | if (typesize > 1) 268 | { 269 | ksp[*count].lens = ksp[*count].nbyte / typesize; 270 | } 271 | offset += ksp[*count].nbyte + 8; 272 | newindex = offset - 1; 273 | (*count)++; 274 | } 275 | else 276 | { 277 | offset++; 278 | } 279 | } 280 | // TODO: fix return 281 | return (newindex + 1); 282 | } 283 | 284 | /** 285 | * @brief kserial_send_packet 286 | */ 287 | uint32_t kserial_send_packet(void *param, void *pdata, uint32_t lens, uint32_t type) 288 | { 289 | #if KSERIAL_SEND_ENABLE 290 | uint32_t nbytes; 291 | nbytes = kserial_pack(sbuffer, param, type, lens, pdata); 292 | kserial_send(sbuffer, nbytes); 293 | // TODO: fix return 294 | return nbytes; 295 | #else 296 | return KS_ERROR; 297 | #endif 298 | } 299 | 300 | /** 301 | * @brief kserial_recv_packet 302 | */ 303 | uint32_t kserial_recv_packet(uint8_t input, void *param, void *pdata, uint32_t *lens, uint32_t *type) 304 | { 305 | #if KSERIAL_RECV_ENABLE 306 | static uint32_t index = 0; 307 | static uint32_t bytes = 0; 308 | static uint32_t point = 0; 309 | 310 | uint32_t state; 311 | uint32_t typesize; 312 | 313 | rbuffer[point] = input; 314 | if (point > 6) 315 | { 316 | if ((rbuffer[point - 7] == 'K') && (rbuffer[point - 6] == 'S')) 317 | { 318 | index = point - 7; 319 | bytes = (((rbuffer[index + 2] << 8) | rbuffer[index + 3]) & 0x0FFF) + 8; 320 | } 321 | if ((point - index + 1) == bytes) 322 | { 323 | state = kserial_unpack(&rbuffer[index], param, type, lens, pdata); 324 | if (state == KS_OK) 325 | { 326 | point = 0; 327 | index = 0; 328 | bytes = 0; 329 | typesize = kserial_get_typesize(*type); 330 | if (typesize > 1) 331 | { 332 | *lens /= typesize; 333 | } 334 | return KS_OK; 335 | } 336 | } 337 | } 338 | if (++point >= KS_MAX_RECV_BUFFER_SIZE) 339 | { 340 | point = 0; 341 | } 342 | return KS_ERROR; 343 | #else 344 | return KS_ERROR; 345 | #endif 346 | } 347 | 348 | /** 349 | * @brief kserial_read 350 | */ 351 | uint32_t kserial_read(kserial_t *ks) 352 | { 353 | #if KSERIAL_RECV_ENABLE 354 | uint32_t available = 0; 355 | uint32_t nbyte; 356 | uint32_t newindex; 357 | 358 | do 359 | { // add rx data to packet buffer 360 | nbyte = kserial_recv(&ks->buffer[ks->count], ks->size - ks->count); 361 | if (nbyte) 362 | { 363 | available = 1; 364 | ks->count += nbyte; 365 | } 366 | } 367 | while (nbyte); 368 | 369 | ks->pkcnt = 0; 370 | if (available) 371 | { 372 | newindex = kserial_unpack_buffer(ks->buffer, ks->count, ks->packet, &ks->pkcnt); 373 | if (ks->pkcnt) 374 | { 375 | // update packet buffer 376 | ks->count -= newindex; 377 | memcpy(ks->buffer, &ks->buffer[newindex], ks->count); 378 | memset(&ks->buffer[ks->count], 0, ks->size - ks->count); 379 | } 380 | } 381 | // TODO: fix return 382 | return ks->pkcnt; 383 | #else 384 | return KS_ERROR; 385 | #endif 386 | } 387 | 388 | /** 389 | * @brief kserial_flush_read 390 | */ 391 | void kserial_flush_read(kserial_t *ks) 392 | { 393 | #if KSERIAL_RECV_ENABLE 394 | kserial_flush_recv(); 395 | memset(ks->buffer, 0, ks->size); 396 | ks->count = 0; 397 | #endif 398 | } 399 | 400 | /** 401 | * @brief kserial_get_frequence 402 | */ 403 | // float kserial_get_frequence(uint32_t lens, uint32_t time, uint32_t count) 404 | // { 405 | // // static uint64_t kslensLast = 0; 406 | // // static uint64_t ksTimeLast = 0; 407 | // static float frequence = 0; 408 | // // if ((time - ksTimeLast) >= count) 409 | // // { 410 | // // frequence = ((float)lens - kslensLast) / (time - ksTimeLast) * 1000.0f; 411 | // // kslensLast = lens; 412 | // // ksTimeLast = time; 413 | // // } 414 | // return frequence; 415 | // } 416 | 417 | /** 418 | * @brief kserial_get_packetdata 419 | */ 420 | void kserial_get_packetdata(kserial_packet_t *ksp, void *pdata, uint32_t index) 421 | { 422 | if (pdata != NULL) 423 | { 424 | memcpy(pdata, ksp[index].data, ksp[index].nbyte); 425 | } 426 | free(ksp[index].data); 427 | } 428 | 429 | /** 430 | * @brief kserial_read_continuous 431 | */ 432 | uint32_t kserial_read_continuous(kserial_packet_t *ksp, uint32_t *index, uint32_t *count, uint32_t *total) 433 | { 434 | #if KSERIAL_RECV_TREAD_ENABLE 435 | if ((*count == 0) || (*index >= *count)) 436 | { 437 | *count = kserial_read(&ks); 438 | if (*count == 0) 439 | { 440 | return KS_ERROR; 441 | } 442 | *index = 0; 443 | } 444 | kserial_get_packetdata(ks.packet, ksp->data, *index); 445 | ksp->param[0] = ks.packet[*index].param[0]; 446 | ksp->param[1] = ks.packet[*index].param[1]; 447 | ksp->type = ks.packet[*index].type; 448 | ksp->lens = ks.packet[*index].lens; 449 | ksp->nbyte = ks.packet[*index].nbyte; 450 | (*total)++; 451 | (*index)++; 452 | return KS_OK; 453 | #else 454 | return KS_ERROR; 455 | #endif 456 | } 457 | 458 | /** 459 | * @brief kscmd_send_command 460 | * Send packet ['K', 'S', type, 0, param1, param2, ck, '\r'] 461 | * Recv packet ['K', 'S', type, 0, param1, param2, ck, '\r'] 462 | */ 463 | uint32_t kscmd_send_command(uint32_t type, uint32_t param1, uint32_t param2, kserial_ack_t *ack) 464 | { 465 | #if KSERIAL_SEND_ENABLE 466 | uint8_t param[2] = {param1, param2}; 467 | uint32_t nbytes; 468 | uint32_t status = KS_OK; 469 | 470 | #if KSERIAL_RECV_ENABLE 471 | if (ack != NULL) 472 | { 473 | kserial_flush_recv(); 474 | } 475 | #endif 476 | nbytes = kserial_pack(sbuffer, param, type, 0, NULL); 477 | kserial_send(sbuffer, nbytes); 478 | #if KSERIAL_RECV_ENABLE 479 | if (ack != NULL) 480 | { 481 | #if 0 482 | nbytes = 0; 483 | while (nbytes == 0) 484 | { 485 | kserial_delay(50); 486 | nbytes = kserial_recv(rbuffer, KS_MAX_RECV_BUFFER_SIZE); 487 | } 488 | #else 489 | kserial_delay(50); 490 | nbytes = kserial_recv(rbuffer, KS_MAX_RECV_BUFFER_SIZE); 491 | #endif 492 | status = kserial_unpack(rbuffer, ack->param, &ack->type, &ack->nbyte, ack->data); 493 | } 494 | #endif 495 | return status; 496 | #else 497 | return KS_ERROR; 498 | #endif 499 | } 500 | 501 | /** 502 | * @brief kscmd_check_device 503 | * Send packet ['K', 'S', R0, 0, 0xD0, 0, ck, '\r'] 504 | * Recv packet ['K', 'S', R0, 0, IDL, IDH, ck, '\r'] 505 | */ 506 | uint32_t kscmd_check_device(uint32_t *id) 507 | { 508 | #if KSERIAL_CMD_ENABLE 509 | kserial_ack_t ack = {0}; 510 | if (kscmd_send_command(KS_R0, KSCMD_R0_DEVICE_ID, 0x00, &ack) != KS_OK) 511 | { 512 | return KS_ERROR; 513 | } 514 | if (ack.type != KS_R0) 515 | { 516 | return KS_ERROR; 517 | } 518 | if (id != NULL) 519 | { 520 | *id = (uint32_t)*(uint16_t*)ack.param; 521 | } 522 | return KS_OK; 523 | #else 524 | return KS_ERROR; 525 | #endif 526 | } 527 | 528 | /** 529 | * @brief kscmd_set_baudrate 530 | * Send packet ['K', 'S', R0, 4, 0xD1, 4, ck, BAUD[0:7], BAUD[8:15], BAUD[16:23], BAUD[24:31], '\r'] 531 | */ 532 | uint32_t kscmd_set_baudrate(int32_t baudrate) 533 | { 534 | if (baudrate < 0) 535 | { 536 | return KS_ERROR; 537 | } 538 | uint8_t param[2] = {KSCMD_R0_DEVICE_BAUDRATE, 4}; 539 | return kserial_send_packet(param, &baudrate, param[1], KS_R0); 540 | } 541 | 542 | /** 543 | * @brief kscmd_set_updaterate 544 | * Send packet ['K', 'S', R0, 4, 0xD2, 4, ck, FREQ[0:7], FREQ[8:15], FREQ[16:23], FREQ[24:31], '\r'] 545 | */ 546 | uint32_t kscmd_set_updaterate(int32_t updaterate) 547 | { 548 | if (updaterate < 0) 549 | { 550 | return KS_ERROR; 551 | } 552 | uint8_t param[2] = {KSCMD_R0_DEVICE_RATE, 4}; 553 | return kserial_send_packet(param, &updaterate, param[1], KS_R0); 554 | } 555 | 556 | /** 557 | * @brief kscmd_set_mode 558 | * Send packet ['K', 'S', R0, 4, 0xD3, 4, ck, MODE[0:7], MODE[8:15], MODE[16:23], MODE[24:31], '\r'] 559 | */ 560 | uint32_t kscmd_set_mode(int32_t mode) 561 | { 562 | if (mode < 0) 563 | { 564 | return KS_ERROR; 565 | } 566 | return kscmd_send_command(KS_R0, KSCMD_R0_DEVICE_MDOE, mode, NULL); 567 | } 568 | 569 | /** 570 | * @brief kscmd_get_value 571 | * Send packet ['K', 'S', R0, 0, 0xE3, ITEM, ck, '\r'] 572 | * Recv packet ['K', 'S', R0, 0, 0xE3, ITEM, ck, VAL[0:7], VAL[8:15], VAL[16:23], VAL[24:31], '\r'] 573 | */ 574 | uint32_t kscmd_get_value(uint32_t item, int32_t *value) 575 | { 576 | kserial_ack_t ack = {0}; 577 | if (kscmd_send_command(KS_R0, KSCMD_R0_DEVICE_GET, item, &ack) != KS_OK) 578 | { 579 | *value = 0; 580 | return KS_ERROR; 581 | } 582 | *value = *(uint32_t*)ack.data; 583 | return KS_OK; 584 | } 585 | 586 | /** 587 | * @brief kscmd_twi_writereg 588 | * Send packet ['K', 'S', R1, 1, slaveAddress(8-bit), regAddress, ck, regData, '\r'] 589 | */ 590 | uint32_t kscmd_twi_writereg(uint8_t slaveaddr, uint8_t regaddr, uint8_t regdata) 591 | { 592 | #if KSERIAL_CMD_ENABLE 593 | uint8_t param[2] = {slaveaddr << 1, regaddr}; 594 | uint32_t type = KS_R1; 595 | uint32_t nbytes; 596 | 597 | kserial_flush_recv(); 598 | 599 | nbytes = kserial_pack(sbuffer, param, type, 1, ®data); 600 | kserial_send(sbuffer, nbytes); 601 | #if 0 602 | klogd("[W] param = %02X, %02X, type = %d, bytes = %d, data = %02X\n", param[0], param[1], type, nbytes, wdata); 603 | #endif 604 | return nbytes; 605 | #else 606 | return KS_ERROR; 607 | #endif 608 | } 609 | 610 | /** 611 | * @brief kscmd_twi_readregs 612 | * Send packet ['K', 'S', R1, 1, slaveAddress(8-bit)+1, regAddress, ck, lens, '\r'] 613 | * Recv packet ['K', 'S', R1, lens, slaveAddress(8-bit)+1, regAddress, ck, regData ..., '\r'] 614 | */ 615 | uint32_t kscmd_twi_readregs(uint8_t slaveaddr, uint8_t regaddr, uint8_t *regdata, uint8_t lens) 616 | { 617 | #if KSERIAL_CMD_ENABLE 618 | uint8_t param[2] = {(slaveaddr << 1) + 1, regaddr}; 619 | uint32_t type = KS_R1; 620 | uint32_t nbytes; 621 | uint32_t status; 622 | 623 | kserial_flush_recv(); 624 | 625 | nbytes = kserial_pack(sbuffer, param, type, 1, &lens); 626 | kserial_send(sbuffer, nbytes); 627 | 628 | nbytes = 0; 629 | while (nbytes == 0) 630 | { 631 | kserial_delay(100); 632 | nbytes = kserial_recv(rbuffer, KS_MAX_RECV_BUFFER_SIZE); 633 | } 634 | 635 | // TODO: check i2cbuff first 'KS' 636 | status = kserial_unpack(rbuffer, param, &type, &nbytes, sbuffer); 637 | if (status == KS_OK) 638 | { 639 | for (uint32_t i = 0; i < nbytes; i++) 640 | { 641 | regdata[i] = sbuffer[i]; 642 | } 643 | #if 0 644 | klogd("[R] param = %02X, %02X, type = %d, bytes = %d, data =", param[0], param[1], type, nbytes + 8); 645 | for (uint32_t i = 0; i < nbytes; i++) 646 | { 647 | klogd(" %02X", i2cbuff[1][i]); 648 | } 649 | klogd("\n"); 650 | #endif 651 | } 652 | return status; 653 | #else 654 | return KS_ERROR; 655 | #endif 656 | } 657 | 658 | /** 659 | * @brief kscmd_twi_writeregs 660 | * Send packet ['K', 'S', R1, lens, slaveAddress(8-bit), regAddress, ck, regData ... , '\r'] 661 | */ 662 | uint32_t kscmd_twi_writeregs(uint8_t slaveaddr, uint8_t regaddr, uint8_t *regdata, uint8_t lens) 663 | { 664 | #if KSERIAL_CMD_ENABLE 665 | uint8_t param[2] = {slaveaddr << 1, regaddr}; 666 | uint32_t type = KS_R1; 667 | uint32_t nbytes; 668 | 669 | kserial_flush_recv(); 670 | 671 | nbytes = kserial_pack(sbuffer, param, type, lens, regdata); 672 | kserial_send(sbuffer, nbytes); 673 | #if 0 674 | klogd("[W] param = %02X, %02X, type = %d, bytes = %d, data = %02X\n", param[0], param[1], type, nbytes, wdata); 675 | #endif 676 | return nbytes; 677 | #else 678 | return KS_ERROR; 679 | #endif 680 | } 681 | 682 | /** 683 | * @brief kscmd_twi_scandevice 684 | * Send packet ['K', 'S', R2, 0, 0xA1, 0, ck, '\r'] 685 | * Recv packet ['K', 'S', R2, lens, 0xA1, 0, ck, address ..., '\r'] 686 | */ 687 | uint32_t kscmd_twi_scandevice(uint8_t *slaveaddr) 688 | { 689 | #if KSERIAL_CMD_ENABLE 690 | uint8_t param[2] = {KSCMD_R2_TWI_SCAN_DEVICE, 0}; 691 | uint32_t type = KS_R2; 692 | uint32_t nbytes; 693 | uint32_t status; 694 | uint32_t count; 695 | 696 | kserial_flush_recv(); 697 | 698 | nbytes = kserial_pack(sbuffer, param, type, 0, NULL); 699 | kserial_send(sbuffer, nbytes); 700 | 701 | kserial_delay(100); 702 | nbytes = kserial_recv(rbuffer, KS_MAX_RECV_BUFFER_SIZE); 703 | 704 | // TODO: check i2cbuff first 'KS' 705 | status = kserial_unpack(rbuffer, param, &type, &count, sbuffer); 706 | if (status == KS_OK) 707 | { 708 | for (uint32_t i = 0; i < count; i++) 709 | { 710 | slaveaddr[i] = sbuffer[i]; 711 | } 712 | #if 0 713 | klogd(" >> i2c device list (found %d device)\n\n", count); 714 | klogd(" "); 715 | for (uint32_t i = 0; i < count; i++) 716 | { 717 | klogd(" %02X", slaveaddr[i]); 718 | } 719 | klogd("\n\n"); 720 | #endif 721 | } 722 | else 723 | { 724 | return 0xFF; 725 | } 726 | return count; 727 | #else 728 | return KS_ERROR; 729 | #endif 730 | } 731 | 732 | /** 733 | * @brief kscmd_twi_scanregister 734 | * Send packet ['K', 'S', R2, 0, 0xA2, slaveAddress, ck, '\r'] 735 | * Recv packet ['K', 'S', R2, 256, 0xA2, slaveAddress, ck, address ..., '\r'] 736 | */ 737 | uint32_t kscmd_twi_scanregister(uint8_t slaveaddr, uint8_t reg[256]) 738 | { 739 | #if KSERIAL_CMD_ENABLE 740 | uint8_t param[2] = {KSCMD_R2_TWI_SCAN_REGISTER, slaveaddr << 1}; 741 | uint32_t type = KS_R2; 742 | uint32_t nbytes; 743 | uint32_t status; 744 | 745 | kserial_flush_recv(); 746 | 747 | nbytes = kserial_pack(sbuffer, param, type, 0, NULL); 748 | kserial_send(sbuffer, nbytes); 749 | 750 | kserial_delay(100); 751 | nbytes = kserial_recv(rbuffer, KS_MAX_RECV_BUFFER_SIZE); 752 | 753 | // TODO: check i2cbuff first 'KS' 754 | status = kserial_unpack(rbuffer, param, &type, &nbytes, sbuffer); 755 | if (status == KS_OK) 756 | { 757 | for (uint32_t i = 0; i < 256; i++) 758 | { 759 | reg[i] = sbuffer[i]; 760 | } 761 | #if 0 762 | klogd("\n"); 763 | klogd(" >> i2c device register (address 0x%02X)\n\n", slaveaddr); 764 | prklogdintf(" 0 1 2 3 4 5 6 7 8 9 A B C D E F\n"); 765 | for (uint32_t i = 0; i < 256; i += 16) 766 | { 767 | klogd(" %02X: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", 768 | i, 769 | reg[i + 0], reg[i + 1], reg[i + 2], reg[i + 3], 770 | reg[i + 4], reg[i + 5], reg[i + 6], reg[i + 7], 771 | reg[i + 8], reg[i + 9], reg[i + 10], reg[i + 11], 772 | reg[i + 12], reg[i + 13], reg[i + 14], reg[i + 15] 773 | ); 774 | } 775 | klogd("\n\n"); 776 | #endif 777 | } 778 | return status; 779 | #else 780 | return KS_ERROR; 781 | #endif 782 | } 783 | 784 | /*************************************** END OF FILE ****************************************/ 785 | -------------------------------------------------------------------------------- /kserial.h: -------------------------------------------------------------------------------- 1 | /** 2 | * __ ____ 3 | * / /__ _ __ / __/ __ 4 | * / //_/(_)/ /_ / / ___ ____ ___ __ __ / /_ 5 | * / ,< / // __/_\ \ / _ \ / __// _ \/ // // __/ 6 | * /_/|_|/_/ \__//___// .__//_/ \___/\_,_/ \__/ 7 | * /_/ github.com/KitSprout 8 | * 9 | * @file kserial.h 10 | * @author KitSprout 11 | * @brief 12 | * 13 | */ 14 | 15 | /* Define to prevent recursive inclusion ---------------------------------------------------*/ 16 | #ifndef __KSERIAL_H 17 | #define __KSERIAL_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /* Includes --------------------------------------------------------------------------------*/ 24 | #include 25 | #include "kstatus.h" 26 | #ifndef KSERIAL_RECONFIG 27 | #include "kserial_conf.h" 28 | #else 29 | #include "kserial_reconf.h" 30 | #endif 31 | 32 | /* Define ----------------------------------------------------------------------------------*/ 33 | 34 | #ifndef KSERIAL_VERSION_DEFINE 35 | #define KSERIAL_VERSION_DEFINE "1.1.2" 36 | #endif 37 | 38 | /* Macro -----------------------------------------------------------------------------------*/ 39 | /* Typedef ---------------------------------------------------------------------------------*/ 40 | 41 | typedef struct 42 | { 43 | uint8_t param[2]; 44 | uint32_t type; 45 | uint32_t lens; 46 | uint32_t nbyte; 47 | void *data; 48 | 49 | } kserial_packet_t; 50 | 51 | typedef struct 52 | { 53 | uint32_t size; 54 | uint32_t count; 55 | uint8_t *buffer; 56 | 57 | uint32_t pkcnt; 58 | kserial_packet_t *packet; 59 | 60 | } kserial_t; 61 | 62 | typedef struct 63 | { 64 | uint32_t type; 65 | uint32_t nbyte; 66 | uint8_t param[2]; 67 | uint8_t data[8]; 68 | 69 | } kserial_ack_t; 70 | 71 | typedef enum 72 | { 73 | KSCMD_R0_NULL = 0x00, 74 | KSCMD_R0_DEVICE_ID = 0xD0, 75 | KSCMD_R0_DEVICE_BAUDRATE = 0xD1, 76 | KSCMD_R0_DEVICE_RATE = 0xD2, 77 | KSCMD_R0_DEVICE_MDOE = 0xD3, 78 | KSCMD_R0_DEVICE_GET = 0xE3 79 | 80 | } kserial_r0_command_t; 81 | 82 | typedef enum 83 | { 84 | KSCMD_R2_TWI_SCAN_DEVICE = 0xA1, 85 | KSCMD_R2_TWI_SCAN_REGISTER = 0xA2 86 | 87 | } kserial_r2_command_t; 88 | 89 | typedef void (*pkserial_callback_t)(kserial_packet_t *pk, uint8_t *data, uint32_t count, uint32_t total); 90 | 91 | /* Extern ----------------------------------------------------------------------------------*/ 92 | 93 | extern const uint32_t KS_TYPE_SIZE[KSERIAL_TYPE_LENS]; 94 | extern const char KS_TYPE_STRING[KSERIAL_TYPE_LENS][4]; 95 | extern const char KS_TYPE_FORMATE[KSERIAL_TYPE_LENS][8]; 96 | 97 | /* Functions -------------------------------------------------------------------------------*/ 98 | 99 | uint32_t kserial_get_typesize(uint32_t type); 100 | 101 | uint32_t kserial_check_header(const uint8_t *packet, void *param, uint32_t *type, uint32_t *nbyte); 102 | uint32_t kserial_check_end(const uint8_t *packet, uint32_t nbyte); 103 | uint32_t kserial_check(const uint8_t *packet, void *param, uint32_t *type, uint32_t *nbyte); 104 | void kserial_get_bytesdata(const uint8_t *packet, void *pdata, uint32_t nbyte); 105 | 106 | uint32_t kserial_pack(uint8_t *packet, const void *param, uint32_t type, uint32_t lens, const void *pdata); 107 | uint32_t kserial_unpack(const uint8_t *packet, void *param, uint32_t *type, uint32_t *nbyte, void *pdata); 108 | uint32_t kserial_unpack_buffer(const uint8_t *buffer, uint32_t buffersize, kserial_packet_t *ksp, uint32_t *count); 109 | 110 | uint32_t kserial_send_packet(void *param, void *pdata, uint32_t lens, uint32_t type); 111 | uint32_t kserial_recv_packet(uint8_t input, void *param, void *pdata, uint32_t *lens, uint32_t *type); 112 | 113 | uint32_t kserial_read(kserial_t *ks ); 114 | void kserial_flush_read(kserial_t *ks ); 115 | void kserial_get_packetdata(kserial_packet_t *ksp, void *pdata, uint32_t index); 116 | uint32_t kserial_read_continuous(kserial_packet_t *ksp, uint32_t *index, uint32_t *count, uint32_t *total); 117 | 118 | uint32_t kscmd_send_command(uint32_t type, uint32_t param1, uint32_t param2, kserial_ack_t *ack); 119 | uint32_t kscmd_check_device(uint32_t *id); 120 | 121 | uint32_t kscmd_set_baudrate(int32_t baudrate); 122 | uint32_t kscmd_set_updaterate(int32_t updaterate); 123 | uint32_t kscmd_set_mode(int32_t mode); 124 | uint32_t kscmd_get_value(uint32_t item, int32_t *value); 125 | 126 | uint32_t kscmd_twi_readregs(uint8_t slaveaddr, uint8_t regaddr, uint8_t *regdata, uint8_t lens); 127 | uint32_t kscmd_twi_writeregs(uint8_t slaveaddr, uint8_t regaddr, uint8_t *regdata, uint8_t lens); 128 | uint32_t kscmd_twi_scandevice( uint8_t *slaveaddr); 129 | uint32_t kscmd_twi_scanregister(uint8_t slaveaddr, uint8_t reg[256]); 130 | 131 | #ifdef __cplusplus 132 | } 133 | #endif 134 | 135 | #endif 136 | 137 | /*************************************** END OF FILE ****************************************/ 138 | -------------------------------------------------------------------------------- /kserial_conf.h: -------------------------------------------------------------------------------- 1 | /** 2 | * __ ____ 3 | * / /__ _ __ / __/ __ 4 | * / //_/(_)/ /_ / / ___ ____ ___ __ __ / /_ 5 | * / ,< / // __/_\ \ / _ \ / __// _ \/ // // __/ 6 | * /_/|_|/_/ \__//___// .__//_/ \___/\_,_/ \__/ 7 | * /_/ github.com/KitSprout 8 | * 9 | * @file kserial_conf.h 10 | * @author KitSprout 11 | * @brief 12 | * 13 | */ 14 | 15 | /* Define to prevent recursive inclusion ---------------------------------------------------*/ 16 | #ifndef __KSERIAL_CONF_H 17 | #define __KSERIAL_CONF_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /* Define ----------------------------------------------------------------------------------*/ 24 | 25 | #ifndef KSERIAL_SEND_ENABLE 26 | #define KSERIAL_SEND_ENABLE (1U) 27 | #ifndef KS_MAX_SEND_BUFFER_SIZE 28 | #define KS_MAX_SEND_BUFFER_SIZE (4096 + 32) 29 | #endif 30 | #endif 31 | 32 | #ifndef KSERIAL_RECV_ENABLE 33 | #define KSERIAL_RECV_ENABLE (1U) 34 | #ifndef KS_MAX_RECV_BUFFER_SIZE 35 | #define KS_MAX_RECV_BUFFER_SIZE (4096 + 1024 + 32) 36 | #endif 37 | #endif 38 | 39 | #ifndef KSERIAL_RECV_TREAD_ENABLE 40 | #define KSERIAL_RECV_TREAD_ENABLE (1U) 41 | #define KSERIAL_MAX_PACKET_LENS (4096) 42 | #define KSERIAL_RECV_PACKET_BUFFER_LENS (64 * 1024) 43 | #endif 44 | 45 | #ifndef KSERIAL_CMD_ENABLE 46 | #define KSERIAL_CMD_ENABLE (1U) 47 | #endif 48 | 49 | #if KSERIAL_RECV_TREAD_ENABLE 50 | #if !(KSERIAL_RECV_ENABLE) 51 | #error "Need to enable recv" 52 | #endif 53 | #endif 54 | #if KSERIAL_CMD_ENABLE 55 | #if !(KSERIAL_SEND_ENABLE && KSERIAL_RECV_ENABLE) 56 | #error "Need to enable send and recv" 57 | #endif 58 | #endif 59 | 60 | #define KSERIAL_TYPE_LENS (16) 61 | 62 | /* Includes --------------------------------------------------------------------------------*/ 63 | 64 | #if (KSERIAL_SEND_ENABLE || KSERIAL_RECV_ENABLE) 65 | #include "serial.h" 66 | #endif 67 | 68 | /* Macro -----------------------------------------------------------------------------------*/ 69 | 70 | #if KSERIAL_SEND_ENABLE 71 | #ifndef kserial_send 72 | #define kserial_send(__DATA, __LENS) serial_send_data(&s, __DATA, __LENS) 73 | #define kserial_sendbyte(__DATA) serial_send_byte(&s, __DATA) 74 | #endif 75 | #endif 76 | #if KSERIAL_RECV_ENABLE 77 | #define kserial_recv(__DATA, __LENS) serial_recv_data(&s, __DATA, __LENS) 78 | #define kserial_recvbyte() serial_recv_byte(&s) 79 | #define kserial_flush_recv() serial_flush(&s) 80 | #endif 81 | #if (KSERIAL_SEND_ENABLE || KSERIAL_RECV_ENABLE) 82 | #define kserial_delay(__MS) serial_delay(__MS) 83 | #endif 84 | 85 | #ifdef __cplusplus 86 | } 87 | #endif 88 | 89 | #endif 90 | 91 | /*************************************** END OF FILE ****************************************/ 92 | -------------------------------------------------------------------------------- /kstatus.h: -------------------------------------------------------------------------------- 1 | /** 2 | * __ ____ 3 | * / /__ _ __ / __/ __ 4 | * / //_/(_)/ /_ / / ___ ____ ___ __ __ / /_ 5 | * / ,< / // __/_\ \ / _ \ / __// _ \/ // // __/ 6 | * /_/|_|/_/ \__//___// .__//_/ \___/\_,_/ \__/ 7 | * /_/ github.com/KitSprout 8 | * 9 | * @file kstatus.h 10 | * @author KitSprout 11 | * @brief 12 | * 13 | */ 14 | 15 | /* Define to prevent recursive inclusion ---------------------------------------------------*/ 16 | #ifndef __KSTATUS_H 17 | #define __KSTATUS_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /* Includes --------------------------------------------------------------------------------*/ 24 | /* Define ----------------------------------------------------------------------------------*/ 25 | 26 | #ifndef NULL 27 | #ifdef __cplusplus 28 | #define NULL 0 29 | #else 30 | #define NULL ((void *)0) 31 | #endif 32 | #endif 33 | 34 | #ifndef KSSTATUS 35 | #define KSSTATUS 36 | #define KS_OK (0U) 37 | #define KS_ERROR (1U) 38 | #define KS_BUSY (2U) 39 | #define KS_TIMEOUT (3U) 40 | 41 | #define KS_CLOSE (0U) 42 | #define KS_OPEN (1U) 43 | 44 | #define KS_DISABLE (0U) 45 | #define KS_ENABLE (1U) 46 | 47 | #define KS_NULL (0U) 48 | #define KS_FALSE (0U) 49 | #define KS_TRUE (1U) 50 | #endif 51 | 52 | #ifndef KSUNIT 53 | #define KSUNIT 54 | #define KS_U8 (0x0) /* 4'b 0000 */ 55 | #define KS_U16 (0x1) /* 4'b 0001 */ 56 | #define KS_U32 (0x2) /* 4'b 0010 */ 57 | #define KS_U64 (0x3) /* 4'b 0011 */ 58 | #define KS_I8 (0x4) /* 4'b 0100 */ 59 | #define KS_I16 (0x5) /* 4'b 0101 */ 60 | #define KS_I32 (0x6) /* 4'b 0110 */ 61 | #define KS_I64 (0x7) /* 4'b 0111 */ 62 | #define KS_F16 (0x9) /* 4'b 1001 */ 63 | #define KS_F32 (0xA) /* 4'b 1010 */ 64 | #define KS_F64 (0xB) /* 4'b 1011 */ 65 | #define KS_R0 (0x8) /* 4'b 1000 */ 66 | #define KS_R1 (0xC) /* 4'b 1100 */ 67 | #define KS_R2 (0xD) /* 4'b 1101 */ 68 | #define KS_R3 (0xE) /* 4'b 1110 */ 69 | #define KS_R4 (0xF) /* 4'b 1111 */ 70 | #endif 71 | 72 | /* Macro -----------------------------------------------------------------------------------*/ 73 | /* Typedef ---------------------------------------------------------------------------------*/ 74 | /* Extern ----------------------------------------------------------------------------------*/ 75 | /* Functions -------------------------------------------------------------------------------*/ 76 | 77 | #ifdef __cplusplus 78 | } 79 | #endif 80 | 81 | #endif 82 | 83 | /*************************************** END OF FILE ****************************************/ 84 | --------------------------------------------------------------------------------