add keyboard interrupt handling to fast-stream.py
[clinton/Smoothieware.git] / src / libs / Config.cpp
1 /*
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/>.
6 */
7
8 using namespace std;
9 #include <vector>
10 #include <string>
11
12 #include "libs/Kernel.h"
13 #include "Config.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"
22 #include "StreamOutputPool.h"
23
24 // Add various config sources. Config can be fetched from several places.
25 // All values are read into a cache, that is then used by modules to read their configuration
26 Config::Config()
27 {
28 this->config_cache = NULL;
29
30 // Config source for firm config found in src/config.default
31 this->config_sources.push_back( new FirmConfigSource("firm") );
32
33 // Config source for */config files
34 FileConfigSource *fcs = NULL;
35 if( file_exists("/local/config") )
36 fcs = new FileConfigSource("/local/config", "local");
37 else if( file_exists("/local/config.txt") )
38 fcs = new FileConfigSource("/local/config.txt", "local");
39 if( fcs != NULL ) {
40 this->config_sources.push_back( fcs );
41 fcs = NULL;
42 }
43 if( file_exists("/sd/config") )
44 fcs = new FileConfigSource("/sd/config", "sd");
45 else if( file_exists("/sd/config.txt") )
46 fcs = new FileConfigSource("/sd/config.txt", "sd");
47 if( fcs != NULL )
48 this->config_sources.push_back( fcs );
49 }
50
51 Config::Config(ConfigSource *cs)
52 {
53 this->config_cache = NULL;
54 this->config_sources.push_back( cs );
55 }
56
57 Config::~Config()
58 {
59 config_cache_clear();
60 for(auto i : this->config_sources) {
61 delete i;
62 }
63 }
64
65 // 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
66 void Config::get_module_list(vector<uint16_t> *list, uint16_t family)
67 {
68 this->config_cache->collect(family, CHECKSUM("enable"), list);
69 }
70
71 // Command to load config cache into buffer for multiple reads during init
72 void Config::config_cache_load(bool parse)
73 {
74 // First clear the cache
75 this->config_cache_clear();
76
77 this->config_cache= new ConfigCache;
78 if(parse) {
79 // For each ConfigSource in our stack
80 for( ConfigSource *source : this->config_sources ) {
81 source->transfer_values_to_cache(this->config_cache);
82 }
83 }
84 }
85
86 // Command to clear the config cache after init
87 void Config::config_cache_clear()
88 {
89 delete this->config_cache;
90 this->config_cache= NULL;
91 }
92
93 // Three ways to read a value from the config, depending on adress length
94 ConfigValue *Config::value(uint16_t check_sum_a, uint16_t check_sum_b, uint16_t check_sum_c )
95 {
96 uint16_t check_sums[3];
97 check_sums[0] = check_sum_a;
98 check_sums[1] = check_sum_b;
99 check_sums[2] = check_sum_c;
100 return this->value(check_sums);
101 }
102
103 static ConfigValue dummyValue;
104
105 // Get a value from the configuration as a string
106 // 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
107 // See get_checksum
108 ConfigValue *Config::value(uint16_t check_sums[])
109 {
110 if( !is_config_cache_loaded() ) {
111 THEKERNEL->streams->printf("ERROR: calling value after config cache has been cleared\n");
112 // note this will cause whatever called it to blow up!
113 return NULL;
114 }
115
116 ConfigValue *result = this->config_cache->lookup(check_sums);
117
118 if(result == NULL) {
119 // create a dummy value for this to play with, each call requires it's own value not a shared one
120 // result= new ConfigValue(check_sums);
121 // config_cache->add(result);
122 dummyValue.clear();
123 result = &dummyValue;
124 }
125
126 return result;
127 }
128
129
130