enabled specifying numeric config values using all strtof capabilities
[clinton/Smoothieware.git] / src / libs / Config.cpp
CommitLineData
df27a6a3 1/*
4cff3ded
AW
2 This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
3 Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
4 Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
df27a6a3 5 You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>.
4cff3ded
AW
6*/
7
3c132bd0
AW
8using namespace std;
9#include <vector>
4cff3ded 10#include <string>
3c132bd0 11
4cff3ded
AW
12#include "libs/Kernel.h"
13#include "Config.h"
c295905f
AW
14#include "ConfigValue.h"
15#include "ConfigSource.h"
16#include "ConfigCache.h"
4eb9c745
AW
17#include "libs/nuts_bolts.h"
18#include "libs/utils.h"
6268c527 19#include "libs/SerialMessage.h"
c295905f 20#include "libs/ConfigSources/FileConfigSource.h"
33110301 21#include "libs/ConfigSources/FirmConfigSource.h"
4cff3ded 22
93694d6b
AW
23// Add various config sources. Config can be fetched from several places.
24// All values are read into a cache, that is then used by modules to read their configuration
4cff3ded 25Config::Config(){
d272dd3c 26 this->config_cache_loaded = false;
fc82a1ee 27
33110301
L
28 // Config source for firm config found in src/config.default
29 this->config_sources.push_back( new FirmConfigSource() );
30
c295905f 31 // Config source for */config files
40a7c6c0
L
32 FileConfigSource* fcs = NULL;
33 if( file_exists("/local/config") )
34 fcs = new FileConfigSource("/local/config", LOCAL_CONFIGSOURCE_CHECKSUM);
35 else if( file_exists("/local/config.txt") )
36 fcs = new FileConfigSource("/local/config.txt", LOCAL_CONFIGSOURCE_CHECKSUM);
247f7afd 37 if( fcs != NULL ){
40a7c6c0 38 this->config_sources.push_back( fcs );
247f7afd
L
39 fcs = NULL;
40 }
40a7c6c0
L
41 if( file_exists("/sd/config") )
42 fcs = new FileConfigSource("/sd/config", SD_CONFIGSOURCE_CHECKSUM );
43 else if( file_exists("/sd/config.txt") )
44 fcs = new FileConfigSource("/sd/config.txt", SD_CONFIGSOURCE_CHECKSUM );
45 if( fcs != NULL )
46 this->config_sources.push_back( fcs );
4cff3ded 47
c295905f
AW
48 // Pre-load the config cache
49 this->config_cache_load();
cebe90b6 50
cebe90b6
AW
51}
52
c295905f 53void Config::on_module_loaded(){}
26806df9 54
c295905f 55void Config::on_console_line_received( void* argument ){}
ced5fce8 56
93694d6b 57// Set a value in the config cache, but not in any config source
ced5fce8
L
58void Config::set_string( string setting, string value ){
59 ConfigValue* cv = new ConfigValue;
60 cv->found = true;
4464301d 61 get_checksums(cv->check_sums, setting);
ced5fce8
L
62 cv->value = value;
63
64 this->config_cache.replace_or_push_back(cv);
65
314ab8f7 66 THEKERNEL->call_event(ON_CONFIG_RELOAD);
ced5fce8
L
67}
68
93694d6b 69// Get a list of modules, used by module "pools" that look for the "enable" keyboard to find things like "moduletype.modulename.enable" as the marker of a new instance of a module
df27a6a3 70void Config::get_module_list(vector<uint16_t>* list, uint16_t family){
f01a01e8 71 for( unsigned int i=1; i<this->config_cache.size(); i++){
df27a6a3 72 ConfigValue* value = this->config_cache.at(i);
d4f93cf4
AG
73 //if( value->check_sums.size() == 3 && value->check_sums.at(2) == CHECKSUM("enable") && value->check_sums.at(0) == family ){
74 if( value->check_sums[2] == CHECKSUM("enable") && value->check_sums[0] == family ){
df27a6a3 75 // We found a module enable for this family, add it's number
4464301d 76 list->push_back(value->check_sums[1]);
df27a6a3 77 }
26c569a2
AW
78 }
79}
26806df9 80
d272dd3c
L
81
82// Command to load config cache into buffer for multiple reads during init
83void Config::config_cache_load(){
c295905f 84
93694d6b 85 // First clear the cache
d272dd3c 86 this->config_cache_clear();
c295905f
AW
87
88 // First element is a special empty ConfigValue for values not found
d272dd3c 89 ConfigValue* result = new ConfigValue;
fc82a1ee 90 this->config_cache.push_back(result);
2b56b363 91
c295905f
AW
92 // For each ConfigSource in our stack
93 for( unsigned int i = 0; i < this->config_sources.size(); i++ ){
94 ConfigSource* source = this->config_sources[i];
95 source->transfer_values_to_cache(&this->config_cache);
96 }
2b56b363 97
d272dd3c
L
98 this->config_cache_loaded = true;
99}
100
101// Command to clear the config cache after init
102void Config::config_cache_clear(){
fc82a1ee 103 while( ! this->config_cache.empty() ){
d272dd3c
L
104 delete this->config_cache.back();
105 this->config_cache.pop_back();
106 }
d272dd3c 107 this->config_cache_loaded = false;
da24d6ae
AW
108}
109
93694d6b 110// Three ways to read a value from the config, depending on adress length
3c132bd0 111ConfigValue* Config::value(uint16_t check_sum_a, uint16_t check_sum_b, uint16_t check_sum_c ){
df27a6a3
MM
112 uint16_t check_sums[3];
113 check_sums[0] = check_sum_a;
4464301d
AW
114 check_sums[1] = check_sum_b;
115 check_sums[2] = check_sum_c;
3c132bd0 116 return this->value(check_sums);
df27a6a3 117}
3c132bd0
AW
118
119ConfigValue* Config::value(uint16_t check_sum_a, uint16_t check_sum_b){
df27a6a3
MM
120 uint16_t check_sums[3];
121 check_sums[0] = check_sum_a;
4464301d
AW
122 check_sums[1] = check_sum_b;
123 check_sums[2] = 0x0000;
3c132bd0 124 return this->value(check_sums);
df27a6a3 125}
3c132bd0
AW
126
127ConfigValue* Config::value(uint16_t check_sum){
df27a6a3
MM
128 uint16_t check_sums[3];
129 check_sums[0] = check_sum;
4464301d
AW
130 check_sums[1] = 0x0000;
131 check_sums[2] = 0x0000;
3c132bd0 132 return this->value(check_sums);
df27a6a3 133}
2b56b363 134
4cff3ded
AW
135// Get a value from the configuration as a string
136// Because we don't like to waste space in Flash with lengthy config parameter names, we take a checksum instead so that the name does not have to be stored
137// See get_checksum
4464301d 138ConfigValue* Config::value(uint16_t check_sums[]){
fc82a1ee 139 ConfigValue* result = this->config_cache[0];
d272dd3c 140 bool cache_preloaded = this->config_cache_loaded;
c295905f 141 if( !cache_preloaded ){ this->config_cache_load(); }
2b56b363 142
f01a01e8 143 for( unsigned int i=1; i<this->config_cache.size(); i++){
df27a6a3 144 // If this line matches the checksum
d272dd3c 145 bool match = true;
87b6a8d5 146 unsigned int counter = 0;
4464301d
AW
147 while(check_sums[counter] != 0x0000 && counter <= 2 ){
148 if(this->config_cache[i]->check_sums[counter] != check_sums[counter] ){
d272dd3c 149 match = false;
df27a6a3 150 break;
d272dd3c 151 }
4464301d 152 counter++;
df27a6a3
MM
153 }
154 if( match == false ){
155 continue;
4cff3ded 156 }
fc82a1ee 157 result = this->config_cache[i];
d272dd3c
L
158 break;
159 }
2b56b363 160
d272dd3c
L
161 if( !cache_preloaded ){
162 this->config_cache_clear();
163 }
b66fb830 164 return result;
4cff3ded
AW
165}
166
3c132bd0 167
4cff3ded 168