#include #include #include #include #include "../inc/sserial.h" #include "../shared/defines.h" memory_t memory; uint8_t *heap_ptr; uint32_t timeout; pd_table_t pd_table; uint16_t add_pd(char *name_string, char *unit_string, uint8_t data_size_in_bits, uint8_t data_type, uint8_t data_dir, float param_min, float param_max) { process_data_descriptor_t pdr; pdr.record_type = RECORD_TYPE_PROCESS_DATA_RECORD; pdr.data_size = data_size_in_bits; pdr.data_type = data_type; pdr.data_direction = data_dir; pdr.param_min = param_min; pdr.param_max = param_max; pdr.data_addr = MEMPTR(*heap_ptr); heap_ptr += NUM_BYTES(data_size_in_bits); // this aligns the heap pointer to 32bit. Not doing this causes the floats in the pd to be misaligned, which crashes the arm. if((uint32_t)heap_ptr % 4) { heap_ptr += 4 - (uint32_t)heap_ptr % 4; } memcpy(heap_ptr, &pdr, sizeof(process_data_descriptor_t)); // note that we don't store the names in the struct anymore. The fixed-length struct is copied into memory, and then the nmaes go in directly behind it, so they'll read out properly uint16_t pd_ptr = MEMPTR(*heap_ptr); // save off the ptr to return, before we modify the heap ptr heap_ptr = (uint8_t *)&(((process_data_descriptor_t *)heap_ptr)->names); // copy the strings in after the pd strcpy((char *)heap_ptr, unit_string); heap_ptr += strlen(unit_string) + 1; strcpy((char *)heap_ptr, name_string); heap_ptr += strlen(name_string) + 1; // moved this up to before the pd record /* // this aligns the heap pointer to 32bit. Not doing this causes the floats in the pd to be misaligned, which crashes the arm. if((uint32_t)heap_ptr % 4){ heap_ptr += 4 - (uint32_t)heap_ptr % 4; } */ return pd_ptr; } uint16_t add_mode(char *name_string, uint8_t index, uint8_t type) { mode_descriptor_t mdr; mdr.record_type = RECORD_TYPE_MODE_DATA_RECORD; mdr.index = index; mdr.type = type; //hw = 0, sw = 1 mdr.unused = 0x00; memcpy(heap_ptr, &mdr, sizeof(mode_descriptor_t)); uint16_t md_ptr = MEMPTR(*heap_ptr); heap_ptr = (uint8_t *)&(((mode_descriptor_t *)heap_ptr)->names); strcpy((char *)heap_ptr, name_string); heap_ptr += strlen(name_string) + 1; return md_ptr; } void metadata(pd_metadata_t *pdm, process_data_descriptor_t *ptr) { pdm->ptr = ptr; pdm->range = ptr->data_type == DATA_TYPE_SIGNED ? MAX(ABS(ptr->param_min), ABS(ptr->param_max)) * 2 : ptr->param_max; pdm->bitmax = (1 << ptr->data_size) - 1; } void print_pd(process_data_descriptor_t *pd) { int strl = strlen(&pd->names); char *unit = &pd->names; char *name = &pd->names + strl + 1; switch(pd->data_type) { case DATA_TYPE_PAD: printf("uint32_t padding : %u;\n", pd->data_size); break; case DATA_TYPE_BITS: for(int i = 0; i < pd->data_size; i++) { printf("uint32_t %s_%i : 1;\n", name, i); } break; case DATA_TYPE_UNSIGNED: if(pd->data_size == 8) { printf("uint8_t %s;\n", name); } else { printf("warning: unsupported int size!\n"); } break; case DATA_TYPE_SIGNED: if(pd->data_size == 8) { printf("int8_t %s;\n", name); } else { printf("warning: unsupported int size!\n"); } break; case DATA_TYPE_FLOAT: //TODO: check size if(pd->data_size != 32) { printf("warning: unsupported float size!"); } printf("float %s;\n", name); break; case DATA_TYPE_BOOLEAN: printf("uint32_t %s : %u;\n", name, pd->data_size); break; case DATA_TYPE_NONVOL_UNSIGNED: case DATA_TYPE_NONVOL_SIGNED: case DATA_TYPE_STREAM: case DATA_TYPE_ENCODER: case DATA_TYPE_ENCODER_H: case DATA_TYPE_ENCODER_L: default: printf("unsupported data type: 0x%02X\n", pd->data_type); } } int main() { heap_ptr = memory.heap; uint16_t input_bits = 8; // this starts at 8 bits = 1 byte for the fault byte uint16_t output_bits = 0; // these are temp toc arrays that the macros will write pointers into. the tocs get copied to main memory after everything else is written in uint16_t ptoc[32]; uint16_t gtoc[32]; uint16_t *ptocp = ptoc; uint16_t *gtocp = gtoc; process_data_descriptor_t *last_pd; ADD_PROCESS_VAR(("pos_cmd", "rad", 32, DATA_TYPE_FLOAT, DATA_DIRECTION_OUTPUT, -INFINITY, INFINITY)); metadata(&(pd_table.pos_cmd), last_pd); ADD_PROCESS_VAR(("vel_cmd", "rad", 32, DATA_TYPE_FLOAT, DATA_DIRECTION_OUTPUT, -INFINITY, INFINITY)); metadata(&(pd_table.vel_cmd), last_pd); ADD_PROCESS_VAR(("out", "none", 4, DATA_TYPE_BITS, DATA_DIRECTION_OUTPUT, 0, 1)); metadata(&(pd_table.output_pins), last_pd); ADD_PROCESS_VAR(("enable", "none", 1, DATA_TYPE_BOOLEAN, DATA_DIRECTION_OUTPUT, 0, 1)); metadata(&(pd_table.enable), last_pd); ADD_PROCESS_VAR(("pos_fb", "rad", 32, DATA_TYPE_FLOAT, DATA_DIRECTION_INPUT, -INFINITY, INFINITY)); metadata(&(pd_table.pos_fb), last_pd); ADD_PROCESS_VAR(("vel_fb", "rad", 32, DATA_TYPE_FLOAT, DATA_DIRECTION_INPUT, -INFINITY, INFINITY)); metadata(&(pd_table.vel_fb), last_pd); ADD_PROCESS_VAR(("current", "A", 8, DATA_TYPE_SIGNED, DATA_DIRECTION_INPUT, -30, 30)); metadata(&(pd_table.current), last_pd); ADD_PROCESS_VAR(("in", "none", 4, DATA_TYPE_BITS, DATA_DIRECTION_INPUT, -100, 100)); metadata(&(pd_table.input_pins), last_pd); ADD_PROCESS_VAR(("fault", "none", 1, DATA_TYPE_BOOLEAN, DATA_DIRECTION_INPUT, 0, 1)); metadata(&(pd_table.fault), last_pd); ADD_PROCESS_VAR(("index_enable", "none", 1, DATA_TYPE_BOOLEAN, DATA_DIRECTION_BI_DIRECTIONAL, 0, 1)); metadata(&(pd_table.index_enable), last_pd); ADD_GLOBAL_VAR(("scale", "none", 32, DATA_TYPE_FLOAT, DATA_DIRECTION_OUTPUT, -INFINITY, INFINITY)); ADD_MODE(("Position mode", 0, 1)); // automatically create padding pds based on the mod remainder of input/output bits if(input_bits % 8) ADD_PROCESS_VAR(("padding", "", 8 - (input_bits % 8), DATA_TYPE_PAD, DATA_DIRECTION_INPUT, 0, 0)); if(output_bits % 8) ADD_PROCESS_VAR(("padding", "", 8 - (output_bits % 8), DATA_TYPE_PAD, DATA_DIRECTION_OUTPUT, 0, 0)); // now that all the toc entries have been added, write out the tocs to memory and set up the toc pointers //calculate bytes from bits memory.discovery.input = input_bits >> 3; memory.discovery.output = output_bits >> 3; memory.discovery.ptocp = MEMPTR(*heap_ptr); for(uint8_t i = 0; i < ptocp - ptoc; i++) { *heap_ptr++ = ptoc[i] & 0x00FF; *heap_ptr++ = (ptoc[i] & 0xFF00) >> 8; } // this is the ptoc end marker *heap_ptr++ = 0x00; *heap_ptr++ = 0x00; memory.discovery.gtocp = MEMPTR(*heap_ptr); for(uint8_t i = 0; i < gtocp - gtoc; i++) { *heap_ptr++ = gtoc[i] & 0x00FF; *heap_ptr++ = (gtoc[i] & 0xFF00) >> 8; } // this is the gtoc end marker *heap_ptr++ = 0x00; *heap_ptr++ = 0x00; // printf("gtoc:%u\n",memory.discovery.gtocp); // printf("ptoc:%u\n",memory.discovery.ptocp); // printf("%i\n",sizeof(memory_t)); //printf("%u\n",MEMPTR(*heap_ptr)); int nl = 0; printf("uint8_t sserial_slave[] = {\n"); for(int i = 0; i < MEMPTR(*heap_ptr); i++) { //printf("%u %c\n",memory.bytes[i],memory.bytes[i]); printf("0x%02X,", memory.bytes[i]); nl++; if(nl > 7) { nl = 0; printf("// %i..%i\n", i - 7, i); } } printf("\n};\n\n"); printf("const discovery_rpc_t discovery = {\n"); printf(" .ptocp = 0x%04X,\n", memory.discovery.ptocp); printf(" .gtocp = 0x%04X,\n", memory.discovery.gtocp); printf(" .input = %u,\n", memory.discovery.input); printf(" .output = %u,\n", memory.discovery.output); printf("};\n\n"); printf("typedef struct {\n"); ptocp = (uint16_t *)(memory.bytes + memory.discovery.ptocp); gtocp = (uint16_t *)(memory.bytes + memory.discovery.gtocp); while(*ptocp != 0x0000) { process_data_descriptor_t *pd = (process_data_descriptor_t *)(memory.bytes + *ptocp++); //printf("0x%02X\n",pd->data_direction); if((pd->data_direction == DATA_DIRECTION_OUTPUT || pd->data_direction == DATA_DIRECTION_BI_DIRECTIONAL) && pd->record_type == RECORD_TYPE_PROCESS_DATA_RECORD) { print_pd(pd); } // printf("pd has data at %x with value %x\n", pd->data_addr, MEMU16(pd->data_addr)); } printf("} sserial_out_process_data_t; //size:%u bytes\n", memory.discovery.output); printf("_Static_assert(sizeof(sserial_out_process_data_t) == %u, \"sserial_out_process_data_t size error!\");\n", memory.discovery.output); printf("\n"); printf("typedef struct {\n"); ptocp = (uint16_t *)(memory.bytes + memory.discovery.ptocp); while(*ptocp != 0x0000) { process_data_descriptor_t *pd = (process_data_descriptor_t *)(memory.bytes + *ptocp++); //printf("0x%02X\n",pd->data_direction); if((pd->data_direction == DATA_DIRECTION_INPUT || pd->data_direction == DATA_DIRECTION_BI_DIRECTIONAL) && pd->record_type == RECORD_TYPE_PROCESS_DATA_RECORD) { print_pd(pd); } // printf("pd has data at %x with value %x\n", pd->data_addr, MEMU16(pd->data_addr)); } printf("} sserial_in_process_data_t; //size:%u bytes\n", memory.discovery.input - 1); printf("_Static_assert(sizeof(sserial_in_process_data_t) == %u, \"sserial_in_process_data_t size error!\");\n", memory.discovery.input - 1); gtocp = (uint16_t *)(memory.bytes + memory.discovery.gtocp); while(*gtocp != 0x0000) { process_data_descriptor_t *pd = (process_data_descriptor_t *)(memory.bytes + *gtocp++); if(pd->record_type == RECORD_TYPE_PROCESS_DATA_RECORD) { int strl = strlen(&pd->names); char *unit = &pd->names; char *name = &pd->names + strl + 1; printf("//global name:%s addr:0x%x size:%i dir:0x%x\n", name, pd->data_addr, pd->data_size, pd->data_direction); printf("#define %s_address %i\n", name, pd->data_addr); } } }