bool AP_Param::configured_in_defaults_file(void) { uint32_t group_element = 0; const struct GroupInfo *ginfo; uint8_t idx; const struct AP_Param::Info *info = find_var_info(&group_element, &ginfo, &idx); if (info == NULL) { // we don't have any info on how to load it return false; } const float* def_value_ptr; if (ginfo != NULL) { def_value_ptr = &ginfo->def_value; } else { def_value_ptr = &info->def_value; } for (uint16_t i=0; i<num_param_overrides; i++) { if (def_value_ptr == param_overrides[i].def_value_ptr) { return true; } } return false; }
// Copy the variable's whole name to the supplied buffer. // // If the variable is a group member, prepend the group name. // void AP_Param::copy_name(char *buffer, size_t buffer_size, bool force_scalar) { uint32_t group_element; const struct GroupInfo *ginfo; uint8_t idx; const struct AP_Param::Info *info = find_var_info(&group_element, &ginfo, &idx); if (info == NULL) { *buffer = 0; serialDebug("no info found"); return; } strncpy_P(buffer, info->name, buffer_size); if (ginfo != NULL) { uint8_t len = strnlen(buffer, buffer_size); if (len < buffer_size) { strncpy_P(&buffer[len], ginfo->name, buffer_size-len); } if ((force_scalar || idx != 0) && AP_PARAM_VECTOR3F == PGM_UINT8(&ginfo->type)) { // the caller wants a specific element in a Vector3f add_vector3f_suffix(buffer, buffer_size, idx); } } else if ((force_scalar || idx != 0) && AP_PARAM_VECTOR3F == PGM_UINT8(&info->type)) { add_vector3f_suffix(buffer, buffer_size, idx); } }
bool AP_Param::configured_in_storage(void) { uint32_t group_element = 0; const struct GroupInfo *ginfo; uint8_t idx; const struct AP_Param::Info *info = find_var_info(&group_element, &ginfo, &idx); if (info == NULL) { // we don't have any info on how to load it return false; } struct Param_header phdr; // create the header we will use to match the variable if (ginfo != NULL) { phdr.type = PGM_UINT8(&ginfo->type); } else { phdr.type = PGM_UINT8(&info->type); } phdr.key = PGM_UINT8(&info->key); phdr.group_element = group_element; // scan EEPROM to find the right location uint16_t ofs; // only vector3f can have non-zero idx for now return scan(&phdr, &ofs) && (phdr.type == AP_PARAM_VECTOR3F || idx == 0); }
bool AS_Param::load(void) { uint8_t idx; const struct AS_Param::Info *info = find_var_info(); if (info == NULL) { // we don't have any info on how to load it return false; } struct Param_header phdr; phdr.type = info->type; phdr.key = info->key; // scan EEPROM to find the right location uint16_t ofs; if (!scan(&phdr, &ofs)) { set_value((enum as_var_type)phdr.type, (void*) info->ptr, info->value); return false; } AS_Param *ap; ap = this; if (idx != 0) { ap = (AS_Param *)((uintptr_t)ap) - (idx*sizeof(float)); } // found it eeprom_read_block(ap,(void*)(ofs+sizeof(phdr)), type_size((enum as_var_type)phdr.type)); return true; }
void AS_Param::copy_name_token( char *buffer, uint8_t buffer_size) const { const struct AS_Param::Info * info = find_var_info(); if (info == 0) { *buffer = 0; return; } strncpy(buffer, info->param_name, buffer_size); }
// Load the variable from EEPROM, if supported // bool AP_Param::load(void) { uint32_t group_element = 0; const struct GroupInfo *ginfo; uint8_t idx; const struct AP_Param::Info *info = find_var_info(&group_element, &ginfo, &idx); if (info == NULL) { // we don't have any info on how to load it return false; } struct Param_header phdr; // create the header we will use to match the variable if (ginfo != NULL) { phdr.type = PGM_UINT8(&ginfo->type); } else { phdr.type = PGM_UINT8(&info->type); } phdr.key = PGM_UINT8(&info->key); phdr.group_element = group_element; // scan EEPROM to find the right location uint16_t ofs; if (!scan(&phdr, &ofs)) { // if the value isn't stored in EEPROM then set the default value if (ginfo != NULL) { uintptr_t base = PGM_POINTER(&info->ptr); set_value((enum ap_var_type)phdr.type, (void*)(base + PGM_UINT16(&ginfo->offset)), get_default_value(&ginfo->def_value)); } else { set_value((enum ap_var_type)phdr.type, (void*)PGM_POINTER(&info->ptr), get_default_value(&info->def_value)); } return false; } if (phdr.type != AP_PARAM_VECTOR3F && idx != 0) { // only vector3f can have non-zero idx for now return false; } AP_Param *ap; ap = this; if (idx != 0) { ap = (AP_Param *)((uintptr_t)ap) - (idx*sizeof(float)); } // found it _storage.read_block(ap, ofs+sizeof(phdr), type_size((enum ap_var_type)phdr.type)); return true; }
// Save the variable to EEPROM, if supported // bool AP_Param::save(void) { uint8_t group_element = 0; const struct GroupInfo *ginfo; uint8_t idx; const struct AP_Param::Info *info = find_var_info(&group_element, &ginfo, &idx); const AP_Param *ap; if (info == NULL) { // we don't have any info on how to store it return false; } struct Param_header phdr; // create the header we will use to store the variable if (ginfo != NULL) { phdr.type = PGM_UINT8(&ginfo->type); } else { phdr.type = PGM_UINT8(&info->type); } phdr.key = PGM_UINT8(&info->key); phdr.group_element = group_element; ap = this; if (phdr.type != AP_PARAM_VECTOR3F && idx != 0) { // only vector3f can have non-zero idx for now return false; } if (idx != 0) { ap = (const AP_Param *)((uintptr_t)ap) - (idx*sizeof(float)); } // scan EEPROM to find the right location uint16_t ofs; if (scan(&phdr, &ofs)) { // found an existing copy of the variable eeprom_write_check(ap, ofs+sizeof(phdr), type_size((enum ap_var_type)phdr.type)); return true; } if (ofs == (uint16_t)~0) { return false; } // write a new sentinal, then the data, then the header write_sentinal(ofs + sizeof(phdr) + type_size((enum ap_var_type)phdr.type)); eeprom_write_check(ap, ofs+sizeof(phdr), type_size((enum ap_var_type)phdr.type)); eeprom_write_check(&phdr, ofs, sizeof(phdr)); return true; }
// notify GCS of current value of parameter void AP_Param::notify() const { uint32_t group_element = 0; const struct GroupInfo *ginfo; uint8_t idx; const struct AP_Param::Info *info = find_var_info(&group_element, &ginfo, &idx); if (info == NULL) { // this is probably very bad return; } char name[AP_MAX_NAME_SIZE+1]; copy_name_info(info, ginfo, idx, name, sizeof(name), true); uint32_t param_header_type; if (ginfo != NULL) { param_header_type = PGM_UINT8(&ginfo->type); } else { param_header_type = PGM_UINT8(&info->type); } send_parameter(name, (enum ap_var_type)param_header_type); }
// Save the variable to EEPROM, if supported // bool AP_Param::save(void) { uint32_t group_element = 0; const struct GroupInfo *ginfo; uint8_t idx; const struct AP_Param::Info *info = find_var_info(&group_element, &ginfo, &idx); const AP_Param *ap; if (info == NULL) { // we don't have any info on how to store it return false; } struct Param_header phdr; // create the header we will use to store the variable if (ginfo != NULL) { phdr.type = PGM_UINT8(&ginfo->type); } else { phdr.type = PGM_UINT8(&info->type); } phdr.key = PGM_UINT8(&info->key); phdr.group_element = group_element; ap = this; if (phdr.type != AP_PARAM_VECTOR3F && idx != 0) { // only vector3f can have non-zero idx for now return false; } if (idx != 0) { ap = (const AP_Param *)((uintptr_t)ap) - (idx*sizeof(float)); } // scan EEPROM to find the right location uint16_t ofs; if (scan(&phdr, &ofs)) { // found an existing copy of the variable eeprom_write_check(ap, ofs+sizeof(phdr), type_size((enum ap_var_type)phdr.type)); return true; } if (ofs == (uint16_t) ~0) { return false; } // if the value is the default value then don't save if (phdr.type <= AP_PARAM_FLOAT) { float v1 = cast_to_float((enum ap_var_type)phdr.type); float v2; if (ginfo != NULL) { v2 = PGM_FLOAT(&ginfo->def_value); } else { v2 = PGM_FLOAT(&info->def_value); } if (v1 == v2) { return true; } if (phdr.type != AP_PARAM_INT32 && (fabsf(v1-v2) < 0.0001f*fabsf(v1))) { // for other than 32 bit integers, we accept values within // 0.01 percent of the current value as being the same return true; } } if (ofs+type_size((enum ap_var_type)phdr.type)+2*sizeof(phdr) >= _eeprom_size) { // we are out of room for saving variables return false; } // write a new sentinal, then the data, then the header write_sentinal(ofs + sizeof(phdr) + type_size((enum ap_var_type)phdr.type)); eeprom_write_check(ap, ofs+sizeof(phdr), type_size((enum ap_var_type)phdr.type)); eeprom_write_check(&phdr, ofs, sizeof(phdr)); return true; }
bool AS_Param::save(bool force_save) { uint8_t idx; const struct AS_Param::Info *info = find_var_info(); const AS_Param *ap; if (info == NULL) { // we don't have any info on how to store it return false; } struct Param_header phdr; phdr.type = info->type; phdr.key = info->key; ap = this; if (idx != 0) { ap = (const AS_Param *)((uintptr_t)ap) - (idx*sizeof(float)); } // scan EEPROM to find the right location uint16_t ofs; if (scan(&phdr, &ofs)) { // found an existing copy of the variable eeprom_write_check(ap, ofs+sizeof(phdr), type_size((enum as_var_type)phdr.type)); return true; } if (ofs == (uint16_t) ~0) { return false; } float v1 = cast_to_float((enum as_var_type)phdr.type); float v2; v2 = info->value; if (v1 == v2 && !force_save) { return true; } if (phdr.type != AS_PTYPE_INT32 && (fabs(v1-v2) < 0.0001f*fabs(v1))) { // for other than 32 bit integers, we accept values within // 0.01 percent of the current value as being the same return true; } if (ofs+type_size((enum as_var_type)phdr.type)+2*sizeof(phdr) >= _eeprom_size) { // we are out of room for saving variables Serial.print("EEPROM full"); return false; } // write a new sentinal, then the data, then the header write_sentinal(ofs + sizeof(phdr) + type_size((enum as_var_type)phdr.type)); eeprom_write_check(ap, ofs+sizeof(phdr), type_size((enum as_var_type)phdr.type)); eeprom_write_check(&phdr, ofs, sizeof(phdr)); Serial.print("Write param done\n"); return true; }