Tomonori Kuroki / MuWatchdog

Fork of Watchdog by David Smart

Committer:
mutech
Date:
Sat May 25 09:03:50 2019 +0000
Revision:
27:b16166a526a2
Parent:
26:f7ccf62c4dd0
Child:
29:d84c025e8c8e
This provides a basic Watchdog service, and includes a startup detection to determine if the reset was caused by the WD.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mutech 27:b16166a526a2 1 /// @file Watchdog.cpp provides the interface to the Watchdog module
WiredHome 2:2873f068f325 2 ///
WiredHome 2:2873f068f325 3 /// This provides basic Watchdog service for the mbed. You can configure
WiredHome 2:2873f068f325 4 /// various timeout intervals that meet your system needs. Additionally,
WiredHome 2:2873f068f325 5 /// it is possible to identify if the Watchdog was the cause of any
WiredHome 2:2873f068f325 6 /// system restart.
WiredHome 2:2873f068f325 7 ///
WiredHome 2:2873f068f325 8 /// Adapted from Simon's Watchdog code from http://mbed.org/forum/mbed/topic/508/
WiredHome 2:2873f068f325 9 ///
WiredHome 2:2873f068f325 10 /// @note Copyright © 2011 by Smartware Computing, all rights reserved.
WiredHome 2:2873f068f325 11 /// This software may be used to derive new software, as long as
WiredHome 2:2873f068f325 12 /// this copyright statement remains in the source file.
WiredHome 2:2873f068f325 13 /// @author David Smart
WiredHome 2:2873f068f325 14 ///
mutech 7:3814d72b8166 15 /// \li v2.10 - 20160914: Changed TARGET_STM by mutech, t.kuroki
mutech 7:3814d72b8166 16
WiredHome 0:7a316f14da9c 17 #include "Watchdog.h"
WiredHome 0:7a316f14da9c 18
mutech 27:b16166a526a2 19 //-----------------------------------------------------------------------------
WiredHome 5:2dad2a78ffbd 20 #if defined( TARGET_LPC1768 )
WiredHome 0:7a316f14da9c 21 /// Watchdog gets instantiated at the module level
mutech 27:b16166a526a2 22 Watchdog::Watchdog()
mutech 27:b16166a526a2 23 {
mutech 15:e0e4c2268558 24 _wdreset = (LPC_WDT->WDMOD >> 2) & 1; // capture the cause of the previous reset
WiredHome 0:7a316f14da9c 25 }
WiredHome 0:7a316f14da9c 26
WiredHome 0:7a316f14da9c 27 /// Load timeout value in watchdog timer and enable
mutech 27:b16166a526a2 28 void Watchdog::begin(float sec)
mutech 27:b16166a526a2 29 {
WiredHome 0:7a316f14da9c 30 LPC_WDT->WDCLKSEL = 0x1; // Set CLK src to PCLK
WiredHome 0:7a316f14da9c 31 uint32_t clk = SystemCoreClock / 16; // WD has a fixed /4 prescaler, PCLK default is /4
mutech 27:b16166a526a2 32 LPC_WDT->WDTC = (uint32_t)(sec * (float)clk);
WiredHome 0:7a316f14da9c 33 LPC_WDT->WDMOD = 0x3; // Enabled and Reset
mutech 27:b16166a526a2 34 clear();
WiredHome 0:7a316f14da9c 35 }
WiredHome 0:7a316f14da9c 36
mutech 27:b16166a526a2 37 void Watchdog::begin(int ms)
mutech 27:b16166a526a2 38 {
mutech 7:3814d72b8166 39 LPC_WDT->WDCLKSEL = 0x1; // Set CLK src to PCLK
mutech 7:3814d72b8166 40 uint32_t clk = SystemCoreClock / 1000; //
mutech 7:3814d72b8166 41 LPC_WDT->WDTC = (ms * clk) / 16; // WD has a fixed /4 prescaler, PCLK default is /4
mutech 7:3814d72b8166 42 LPC_WDT->WDMOD = 0x3; // Enabled and Reset
mutech 27:b16166a526a2 43 clear();
mutech 7:3814d72b8166 44 }
mutech 7:3814d72b8166 45
WiredHome 0:7a316f14da9c 46 /// "Service", "kick" or "feed" the dog - reset the watchdog timer
WiredHome 0:7a316f14da9c 47 /// by writing this required bit pattern
mutech 27:b16166a526a2 48 void Watchdog::clear()
mutech 27:b16166a526a2 49 {
WiredHome 0:7a316f14da9c 50 LPC_WDT->WDFEED = 0xAA;
WiredHome 0:7a316f14da9c 51 LPC_WDT->WDFEED = 0x55;
WiredHome 0:7a316f14da9c 52 }
WiredHome 0:7a316f14da9c 53
WiredHome 0:7a316f14da9c 54 /// get the flag to indicate if the watchdog causes the reset
mutech 27:b16166a526a2 55 bool Watchdog::WatchdogCausedReset()
mutech 27:b16166a526a2 56 {
mutech 15:e0e4c2268558 57 return _wdreset;
WiredHome 0:7a316f14da9c 58 }
mutech 27:b16166a526a2 59
mutech 27:b16166a526a2 60 //-----------------------------------------------------------------------------
WiredHome 5:2dad2a78ffbd 61 #elif defined( TARGET_LPC4088 )
WiredHome 5:2dad2a78ffbd 62 // from Gesotec Gesotec
WiredHome 5:2dad2a78ffbd 63 /// Watchdog gets instantiated at the module level
mutech 27:b16166a526a2 64 Watchdog::Watchdog()
mutech 27:b16166a526a2 65 {
mutech 15:e0e4c2268558 66 _wdreset = (LPC_WDT->MOD >> 2) & 1; // capture the cause of the previous reset
WiredHome 5:2dad2a78ffbd 67 }
WiredHome 5:2dad2a78ffbd 68
WiredHome 5:2dad2a78ffbd 69 /// Load timeout value in watchdog timer and enable
mutech 27:b16166a526a2 70 void Watchdog::begin(float sec)
mutech 27:b16166a526a2 71 {
WiredHome 5:2dad2a78ffbd 72 //LPC_WDT->CLKSEL = 0x1; // Set CLK src to PCLK
WiredHome 5:2dad2a78ffbd 73 uint32_t clk = 500000 / 4; // WD has a fixed /4 prescaler, and a 500khz oscillator
mutech 27:b16166a526a2 74 LPC_WDT->TC = (uint32_t)(sec * (float)clk);
WiredHome 5:2dad2a78ffbd 75 LPC_WDT->MOD = 0x3; // Enabled and Reset
mutech 27:b16166a526a2 76 clear();
WiredHome 5:2dad2a78ffbd 77 }
mutech 7:3814d72b8166 78
mutech 27:b16166a526a2 79 void Watchdog::begin(int ms)
mutech 27:b16166a526a2 80 {
mutech 7:3814d72b8166 81 //LPC_WDT->CLKSEL = 0x1; // Set CLK src to PCLK
mutech 7:3814d72b8166 82 uint32_t clk = 500000 / 4; // WD has a fixed /4 prescaler, and a 500khz oscillator
mutech 7:3814d72b8166 83 LPC_WDT->TC = (ms * clk) / 1000;
mutech 7:3814d72b8166 84 LPC_WDT->MOD = 0x3; // Enabled and Reset
mutech 27:b16166a526a2 85 clear();
mutech 7:3814d72b8166 86 }
mutech 7:3814d72b8166 87
WiredHome 5:2dad2a78ffbd 88 /// "Service", "kick" or "feed" the dog - reset the watchdog timer
WiredHome 5:2dad2a78ffbd 89 /// by writing this required bit pattern
mutech 27:b16166a526a2 90 void Watchdog::clear()
mutech 27:b16166a526a2 91 {
WiredHome 5:2dad2a78ffbd 92 LPC_WDT->FEED = 0xAA;
WiredHome 5:2dad2a78ffbd 93 LPC_WDT->FEED = 0x55;
WiredHome 5:2dad2a78ffbd 94 }
WiredHome 5:2dad2a78ffbd 95
WiredHome 5:2dad2a78ffbd 96 /// get the flag to indicate if the watchdog causes the reset
mutech 27:b16166a526a2 97 bool Watchdog::WatchdogCausedReset()
mutech 27:b16166a526a2 98 {
mutech 15:e0e4c2268558 99 return _wdreset;
WiredHome 5:2dad2a78ffbd 100 }
mutech 17:ccd155378a9b 101
mutech 27:b16166a526a2 102 //-----------------------------------------------------------------------------
mutech 17:ccd155378a9b 103 #elif defined(TARGET_LPC81X) || defined(TARGET_LPC82X)
mutech 18:edfbf294c9e2 104
mutech 17:ccd155378a9b 105 // from Gesotec Gesotec
mutech 17:ccd155378a9b 106 /// Watchdog gets instantiated at the module level
mutech 17:ccd155378a9b 107 Watchdog::Watchdog()
mutech 17:ccd155378a9b 108 {
mutech 17:ccd155378a9b 109 _wdreset = (LPC_WWDT->MOD >> 2) & 1; // capture the cause of the previous reset
mutech 17:ccd155378a9b 110 }
mutech 17:ccd155378a9b 111
mutech 17:ccd155378a9b 112 /// Load timeout value in watchdog timer and enable
mutech 27:b16166a526a2 113 void Watchdog::begin(float sec)
mutech 17:ccd155378a9b 114 {
mutech 27:b16166a526a2 115 begin((int)(s * 1000));
mutech 17:ccd155378a9b 116 }
mutech 17:ccd155378a9b 117
mutech 19:3b172e42d8ee 118 #define WDTOSCCTRL_Val(clk, div) ((((uint32_t)(clk)) << 5) | (((div) >> 1) - 1))
mutech 19:3b172e42d8ee 119
mutech 27:b16166a526a2 120 void Watchdog::begin(int ms)
mutech 17:ccd155378a9b 121 {
mutech 18:edfbf294c9e2 122 #if 0
mutech 18:edfbf294c9e2 123 uint32_t clk = get_wdtclock() / 4; // WD has a fixed /4 prescaler, and a 500khz oscillator
mutech 18:edfbf294c9e2 124 LPC_WWDT->TC = (ms * clk) / 1000;
mutech 18:edfbf294c9e2 125 #else
mutech 19:3b172e42d8ee 126 LPC_SYSCON->WDTOSCCTRL = WDTOSCCTRL_Val(10, 2); // wdt_osc_clk = Fclkana/2, Fclkana = 3.5MHz
mutech 18:edfbf294c9e2 127 LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 17); // Enable Clock WWDT
mutech 18:edfbf294c9e2 128 LPC_SYSCON->PDRUNCFG &= ~(1 << 6); // Enable Power WDTOSC_PD
mutech 18:edfbf294c9e2 129 uint32_t clk = ((3500000/2)/4); // COUNT = wdt_osc_clk/4
mutech 18:edfbf294c9e2 130 LPC_WWDT->TC = (ms * clk) / 1000;
mutech 18:edfbf294c9e2 131 #endif
mutech 18:edfbf294c9e2 132 LPC_WWDT->MOD = 0x3; // Enabled and Reset
mutech 27:b16166a526a2 133 clear();
mutech 18:edfbf294c9e2 134 }
mutech 18:edfbf294c9e2 135
mutech 18:edfbf294c9e2 136 uint32_t Watchdog::get_wdtclock()
mutech 18:edfbf294c9e2 137 {
mutech 22:3c7ea2ad3a85 138 #if 0
mutech 17:ccd155378a9b 139 uint32_t wdt_osc = 0;
mutech 18:edfbf294c9e2 140
mutech 17:ccd155378a9b 141 /* Determine clock frequency according to clock register values */
mutech 17:ccd155378a9b 142 switch ((LPC_SYSCON->WDTOSCCTRL >> 5) & 0x0F)
mutech 17:ccd155378a9b 143 {
mutech 17:ccd155378a9b 144 case 0: wdt_osc = 0; break;
mutech 18:edfbf294c9e2 145 case 1: wdt_osc = 600000; break;
mutech 18:edfbf294c9e2 146 case 2: wdt_osc = 1050000; break;
mutech 18:edfbf294c9e2 147 case 3: wdt_osc = 1400000; break;
mutech 18:edfbf294c9e2 148 case 4: wdt_osc = 1750000; break;
mutech 18:edfbf294c9e2 149 case 5: wdt_osc = 2100000; break;
mutech 18:edfbf294c9e2 150 case 6: wdt_osc = 2400000; break;
mutech 18:edfbf294c9e2 151 case 7: wdt_osc = 2700000; break;
mutech 18:edfbf294c9e2 152 case 8: wdt_osc = 3000000; break;
mutech 18:edfbf294c9e2 153 case 9: wdt_osc = 3250000; break;
mutech 18:edfbf294c9e2 154 case 10: wdt_osc = 3500000; break;
mutech 18:edfbf294c9e2 155 case 11: wdt_osc = 3750000; break;
mutech 18:edfbf294c9e2 156 case 12: wdt_osc = 4000000; break;
mutech 18:edfbf294c9e2 157 case 13: wdt_osc = 4200000; break;
mutech 18:edfbf294c9e2 158 case 14: wdt_osc = 4400000; break;
mutech 18:edfbf294c9e2 159 case 15: wdt_osc = 4600000; break;
mutech 17:ccd155378a9b 160 }
mutech 22:3c7ea2ad3a85 161 #else
mutech 22:3c7ea2ad3a85 162 const uint32_t osctab[16] =
mutech 22:3c7ea2ad3a85 163 {
mutech 22:3c7ea2ad3a85 164 0, // 0
mutech 22:3c7ea2ad3a85 165 600000, // 1
mutech 22:3c7ea2ad3a85 166 1050000, // 2
mutech 22:3c7ea2ad3a85 167 1400000, // 3
mutech 22:3c7ea2ad3a85 168 1750000, // 4
mutech 22:3c7ea2ad3a85 169 2100000, // 5
mutech 22:3c7ea2ad3a85 170 2400000, // 6
mutech 22:3c7ea2ad3a85 171 2700000, // 7
mutech 22:3c7ea2ad3a85 172 3000000, // 8
mutech 22:3c7ea2ad3a85 173 3250000, // 9
mutech 22:3c7ea2ad3a85 174 3500000, // 10
mutech 22:3c7ea2ad3a85 175 3750000, // 11
mutech 22:3c7ea2ad3a85 176 4000000, // 12
mutech 22:3c7ea2ad3a85 177 4200000, // 13
mutech 22:3c7ea2ad3a85 178 4400000, // 14
mutech 22:3c7ea2ad3a85 179 4600000 // 15
mutech 22:3c7ea2ad3a85 180 };
mutech 22:3c7ea2ad3a85 181 #endif
mutech 22:3c7ea2ad3a85 182 uint32_t wdt_osc = osctab[(LPC_SYSCON->WDTOSCCTRL >> 5) & 0x0F];
mutech 22:3c7ea2ad3a85 183
mutech 18:edfbf294c9e2 184 // wdt_osc /= ((LPC_SYSCON->WDTOSCCTRL & 0x1F) << 1) + 2;
mutech 18:edfbf294c9e2 185 return wdt_osc;
mutech 17:ccd155378a9b 186 }
mutech 17:ccd155378a9b 187
mutech 17:ccd155378a9b 188 /// "Service", "kick" or "feed" the dog - reset the watchdog timer
mutech 17:ccd155378a9b 189 /// by writing this required bit pattern
mutech 27:b16166a526a2 190 void Watchdog::clear()
mutech 17:ccd155378a9b 191 {
mutech 17:ccd155378a9b 192 LPC_WWDT->FEED = 0xAA;
mutech 17:ccd155378a9b 193 LPC_WWDT->FEED = 0x55;
mutech 17:ccd155378a9b 194 }
mutech 17:ccd155378a9b 195
mutech 17:ccd155378a9b 196 /// get the flag to indicate if the watchdog causes the reset
mutech 17:ccd155378a9b 197 bool Watchdog::WatchdogCausedReset()
mutech 17:ccd155378a9b 198 {
mutech 17:ccd155378a9b 199 return _wdreset;
mutech 17:ccd155378a9b 200 }
mutech 17:ccd155378a9b 201
mutech 27:b16166a526a2 202 //-----------------------------------------------------------------------------
mutech 7:3814d72b8166 203 #elif defined(TARGET_STM)
WiredHome 0:7a316f14da9c 204
mutech 11:a1611543c454 205 // 整数Xを含む最小のべき乗指数
mutech 27:b16166a526a2 206 static int calcExponent16bit(uint16_t v)
mutech 11:a1611543c454 207 {
mutech 11:a1611543c454 208 // return (v == 0) ? 0 : MSB16bit(v - 1) + 1;
mutech 11:a1611543c454 209 if (!v)
mutech 11:a1611543c454 210 return 0;
mutech 11:a1611543c454 211 --v;
mutech 7:3814d72b8166 212 // 最大有効ビット数(MSB:Most Significant Bit)
mutech 7:3814d72b8166 213 v |= (v >> 1);
mutech 7:3814d72b8166 214 v |= (v >> 2);
mutech 7:3814d72b8166 215 v |= (v >> 4);
mutech 7:3814d72b8166 216 v |= (v >> 8);
mutech 7:3814d72b8166 217 // return count16bit(v) - 1;
mutech 7:3814d72b8166 218 // 立っているビットの数を数える
mutech 7:3814d72b8166 219 v = (v & 0x5555) + ((v >> 1) & 0x5555);
mutech 7:3814d72b8166 220 v = (v & 0x3333) + ((v >> 2) & 0x3333);
mutech 7:3814d72b8166 221 v = (v & 0x0f0f) + ((v >> 4) & 0x0f0f);
mutech 11:a1611543c454 222 return (v & 0x00ff) + ((v >> 8) & 0x00ff);
mutech 7:3814d72b8166 223 }
mutech 7:3814d72b8166 224
mutech 27:b16166a526a2 225 Watchdog::Watchdog()
mutech 27:b16166a526a2 226 {
mutech 27:b16166a526a2 227 _rcc_csr = RCC->CSR;
mutech 27:b16166a526a2 228 RCC->CSR |= RCC_CSR_RMVF; // clear reset flag
mutech 27:b16166a526a2 229 }
mutech 27:b16166a526a2 230
mutech 24:bb99754d8098 231 #if defined(TARGET_STM32F0) || defined(TARGET_STM32F1) || defined(TARGET_STM32F3)
mutech 14:30665d9afe68 232 #define WDT_CLOCK 40000U // 40 kHz
mutech 14:30665d9afe68 233 #else
mutech 24:bb99754d8098 234 // TARGET_STM32L0/STM32L1/STM32L4/STM32F4/STM32F7
mutech 14:30665d9afe68 235 #define WDT_CLOCK 32768U // 32.768 kHz
mutech 14:30665d9afe68 236 #endif
mutech 7:3814d72b8166 237
WiredHome 5:2dad2a78ffbd 238 /// Load timeout value in watchdog timer and enable
mutech 27:b16166a526a2 239 void Watchdog::begin(float sec)
mutech 7:3814d72b8166 240 {
WiredHome 5:2dad2a78ffbd 241 // http://www.st.com/web/en/resource/technical/document/reference_manual/CD00171190.pdf
mutech 7:3814d72b8166 242
mutech 11:a1611543c454 243 // Newer Nucleo boards have 32.768 kHz crystal. Without it, the internal
mutech 7:3814d72b8166 244 // RC clock would have an average frequency of 40 kHz (variable between 30 and 60 kHz)
mutech 27:b16166a526a2 245 uint32_t tick = (uint32_t)(sec * WDT_CLOCK + 0.5f);
mutech 11:a1611543c454 246 // The RLR register is 12 bits and beyond that a prescaler should be used
mutech 11:a1611543c454 247 int scale = calcExponent16bit((tick + 4095) >> 12);
mutech 7:3814d72b8166 248 if (scale < 2)
mutech 7:3814d72b8166 249 scale = 2;
mutech 10:673dff2b0ee6 250 else if (scale > 8) // STM32 allows a maximum time of around 26.2 seconds for the Watchdog timer
mutech 7:3814d72b8166 251 scale = 8;
mutech 11:a1611543c454 252
mutech 11:a1611543c454 253 int residual = tick / (1 << scale); // The value for the RLR register
mutech 11:a1611543c454 254 if (residual < 1)
mutech 11:a1611543c454 255 residual = 1;
mutech 11:a1611543c454 256 else if (residual > 4096)
mutech 7:3814d72b8166 257 residual = 4096;
mutech 7:3814d72b8166 258
WiredHome 5:2dad2a78ffbd 259 IWDG->KR = 0x5555; // enable write to PR, RLR
mutech 7:3814d72b8166 260 IWDG->PR = scale - 2; // Prescaler has values of multiples of 4 (i.e. 2 ^2), page 486 Reference Manual
mutech 7:3814d72b8166 261 IWDG->RLR = residual - 1; // Init RLR
mutech 7:3814d72b8166 262 IWDG->KR = 0xAAAA; // Reload the watchdog
mutech 7:3814d72b8166 263 IWDG->KR = 0xCCCC; // Starts the WD
mutech 7:3814d72b8166 264 }
mutech 7:3814d72b8166 265
mutech 26:f7ccf62c4dd0 266 void Watchdog::begin(int ms)
mutech 7:3814d72b8166 267 {
mutech 7:3814d72b8166 268 // http://www.st.com/web/en/resource/technical/document/reference_manual/CD00171190.pdf
mutech 7:3814d72b8166 269
mutech 11:a1611543c454 270 // Newer Nucleo boards have 32.768 kHz crystal. Without it, the internal
mutech 11:a1611543c454 271 // RC clock would have an average frequency of 40 kHz (variable between 30 and 60 kHz)
mutech 11:a1611543c454 272 // tick = (ms / (1/WDT_CLOCK))/1000;
mutech 11:a1611543c454 273 uint32_t tick = ((uint32_t)ms * WDT_CLOCK + 500U) / 1000U;
mutech 11:a1611543c454 274 // The RLR register is 12 bits and beyond that a prescaler should be used
mutech 11:a1611543c454 275 int scale = calcExponent16bit((tick + 4095) >> 12);
mutech 11:a1611543c454 276 if (scale < 2)
mutech 11:a1611543c454 277 scale = 2;
mutech 11:a1611543c454 278 else if (scale > 8) // STM32 allows a maximum time of around 26.2 seconds for the Watchdog timer
mutech 11:a1611543c454 279 scale = 8;
mutech 10:673dff2b0ee6 280
mutech 11:a1611543c454 281 int residual = tick / (1 << scale); // The value for the RLR register
mutech 11:a1611543c454 282 if (residual < 1)
mutech 7:3814d72b8166 283 residual = 1;
mutech 11:a1611543c454 284 else if (residual > 4096)
mutech 7:3814d72b8166 285 residual = 4096;
mutech 7:3814d72b8166 286
mutech 7:3814d72b8166 287 IWDG->KR = 0x5555; // enable write to PR, RLR
mutech 7:3814d72b8166 288 IWDG->PR = scale - 2; // Prescaler has values of multiples of 4 (i.e. 2 ^2), page 486 Reference Manual
mutech 7:3814d72b8166 289 IWDG->RLR = residual - 1; // Init RLR
WiredHome 5:2dad2a78ffbd 290 IWDG->KR = 0xAAAA; // Reload the watchdog
WiredHome 5:2dad2a78ffbd 291 IWDG->KR = 0xCCCC; // Starts the WD
WiredHome 5:2dad2a78ffbd 292 }
WiredHome 0:7a316f14da9c 293
WiredHome 5:2dad2a78ffbd 294 /// "Service", "kick" or "feed" the dog - reset the watchdog timer
mutech 27:b16166a526a2 295 void Watchdog::clear()
mutech 7:3814d72b8166 296 {
WiredHome 5:2dad2a78ffbd 297 IWDG->KR = 0xAAAA;
WiredHome 5:2dad2a78ffbd 298 }
WiredHome 5:2dad2a78ffbd 299
WiredHome 5:2dad2a78ffbd 300 /// get the flag to indicate if the watchdog causes the reset
mutech 7:3814d72b8166 301 bool Watchdog::WatchdogCausedReset()
mutech 7:3814d72b8166 302 {
mutech 25:4eecd15f0c38 303 #if defined(RCC_CSR_IWDGRSTF)
mutech 15:e0e4c2268558 304 return (_rcc_csr & (RCC_CSR_IWDGRSTF | RCC_CSR_WWDGRSTF)) != 0; // read the IWDGRSTF (Independent WD, not the windows WD)
mutech 25:4eecd15f0c38 305 #else
mutech 25:4eecd15f0c38 306 // for old library
mutech 25:4eecd15f0c38 307 return (_rcc_csr & (RCC_CSR_WDGRSTF | RCC_CSR_WWDGRSTF)) != 0; // read the IWDGRSTF (Independent WD, not the windows WD)
mutech 25:4eecd15f0c38 308 #endif
WiredHome 5:2dad2a78ffbd 309 }
mutech 27:b16166a526a2 310
mutech 27:b16166a526a2 311 //-----------------------------------------------------------------------------
WiredHome 5:2dad2a78ffbd 312 #endif
mutech 27:b16166a526a2 313