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.
5 You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>.
12 #include "libs/Kernel.h"
14 #include "ConfigValue.h"
15 #include "ConfigSource.h"
16 #include "ConfigCache.h"
17 #include "libs/nuts_bolts.h"
18 #include "libs/utils.h"
19 #include "libs/SerialMessage.h"
20 #include "libs/ConfigSources/FileConfigSource.h"
21 #include "libs/ConfigSources/FirmConfigSource.h"
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
26 this->config_cache_loaded
= false;
28 // Config source for firm config found in src/config.default
29 this->config_sources
.push_back( new FirmConfigSource() );
31 // Config source for */config files
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
);
38 this->config_sources
.push_back( fcs
);
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
);
46 this->config_sources
.push_back( fcs
);
48 // Pre-load the config cache
49 this->config_cache_load();
53 void Config::on_module_loaded(){}
55 void Config::on_console_line_received( void* argument
){}
57 // Set a value in the config cache, but not in any config source
58 void Config::set_string( string setting
, string value
){
59 ConfigValue
* cv
= new ConfigValue
;
61 get_checksums(cv
->check_sums
, setting
);
64 this->config_cache
.replace_or_push_back(cv
);
66 THEKERNEL
->call_event(ON_CONFIG_RELOAD
);
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
70 void Config::get_module_list(vector
<uint16_t>* list
, uint16_t family
){
71 for( unsigned int i
=1; i
<this->config_cache
.size(); i
++){
72 ConfigValue
* value
= this->config_cache
.at(i
);
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
){
75 // We found a module enable for this family, add it's number
76 list
->push_back(value
->check_sums
[1]);
82 // Command to load config cache into buffer for multiple reads during init
83 void Config::config_cache_load(){
85 // First clear the cache
86 this->config_cache_clear();
88 // First element is a special empty ConfigValue for values not found
89 ConfigValue
* result
= new ConfigValue
;
90 this->config_cache
.push_back(result
);
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
);
98 this->config_cache_loaded
= true;
101 // Command to clear the config cache after init
102 void Config::config_cache_clear(){
103 while( ! this->config_cache
.empty() ){
104 delete this->config_cache
.back();
105 this->config_cache
.pop_back();
107 this->config_cache_loaded
= false;
110 // Three ways to read a value from the config, depending on adress length
111 ConfigValue
* Config::value(uint16_t check_sum_a
, uint16_t check_sum_b
, uint16_t check_sum_c
){
112 uint16_t check_sums
[3];
113 check_sums
[0] = check_sum_a
;
114 check_sums
[1] = check_sum_b
;
115 check_sums
[2] = check_sum_c
;
116 return this->value(check_sums
);
119 ConfigValue
* Config::value(uint16_t check_sum_a
, uint16_t check_sum_b
){
120 uint16_t check_sums
[3];
121 check_sums
[0] = check_sum_a
;
122 check_sums
[1] = check_sum_b
;
123 check_sums
[2] = 0x0000;
124 return this->value(check_sums
);
127 ConfigValue
* Config::value(uint16_t check_sum
){
128 uint16_t check_sums
[3];
129 check_sums
[0] = check_sum
;
130 check_sums
[1] = 0x0000;
131 check_sums
[2] = 0x0000;
132 return this->value(check_sums
);
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
138 ConfigValue
* Config::value(uint16_t check_sums
[]){
139 ConfigValue
* result
= this->config_cache
[0];
140 bool cache_preloaded
= this->config_cache_loaded
;
141 if( !cache_preloaded
){ this->config_cache_load(); }
143 for( unsigned int i
=1; i
<this->config_cache
.size(); i
++){
144 // If this line matches the checksum
146 unsigned int counter
= 0;
147 while(check_sums
[counter
] != 0x0000 && counter
<= 2 ){
148 if(this->config_cache
[i
]->check_sums
[counter
] != check_sums
[counter
] ){
154 if( match
== false ){
157 result
= this->config_cache
[i
];
161 if( !cache_preloaded
){
162 this->config_cache_clear();