auto-sync
This commit is contained in:
parent
49fe7a8239
commit
80db0ae56d
|
@ -3,6 +3,10 @@
|
||||||
*
|
*
|
||||||
* FORD_ESCORT_GT = 14
|
* FORD_ESCORT_GT = 14
|
||||||
*
|
*
|
||||||
|
* MIATA_1990 = 19
|
||||||
|
* MIATA_1994 = 20
|
||||||
|
* MIATA_1996 = 21
|
||||||
|
*
|
||||||
* @date Apr 11, 2014
|
* @date Apr 11, 2014
|
||||||
* @author Andrey Belomutskiy, (c) 2012-2014
|
* @author Andrey Belomutskiy, (c) 2012-2014
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -244,7 +244,13 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration, board_
|
||||||
// engineConfiguration->idleMode = IM_AUTO;
|
// engineConfiguration->idleMode = IM_AUTO;
|
||||||
engineConfiguration->idleMode = IM_MANUAL;
|
engineConfiguration->idleMode = IM_MANUAL;
|
||||||
|
|
||||||
|
#if EFI_PROD_CODE
|
||||||
engineConfiguration->digitalChartSize = 300;
|
engineConfiguration->digitalChartSize = 300;
|
||||||
|
#else
|
||||||
|
// need more events for automated test
|
||||||
|
engineConfiguration->digitalChartSize = 400;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
engineConfiguration->isInjectionEnabled = true;
|
engineConfiguration->isInjectionEnabled = true;
|
||||||
engineConfiguration->isIgnitionEnabled = true;
|
engineConfiguration->isIgnitionEnabled = true;
|
||||||
|
|
|
@ -24,11 +24,12 @@
|
||||||
* If not, see <http://www.gnu.org/licenses/>.
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "wave_chart.h"
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
#include "wave_chart.h"
|
||||||
|
|
||||||
#if EFI_WAVE_CHART
|
#if EFI_WAVE_CHART
|
||||||
|
|
||||||
|
#include "engine_configuration.h"
|
||||||
#include "eficonsole.h"
|
#include "eficonsole.h"
|
||||||
#include "status_loop.h"
|
#include "status_loop.h"
|
||||||
|
|
||||||
|
@ -40,17 +41,15 @@
|
||||||
static histogram_s waveChartHisto;
|
static histogram_s waveChartHisto;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern engine_configuration_s *engineConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the number of events in the digital chart which would be displayed
|
* This is the number of events in the digital chart which would be displayed
|
||||||
* on the 'digital sniffer' pane
|
* on the 'digital sniffer' pane
|
||||||
*/
|
*/
|
||||||
#if EFI_PROD_CODE
|
#if EFI_PROD_CODE
|
||||||
// todo: does it really need to be a variable? maybe a constant should be enough?
|
|
||||||
static volatile int chartSize = 300;
|
|
||||||
#define WAVE_LOGGING_SIZE 5000
|
#define WAVE_LOGGING_SIZE 5000
|
||||||
#else
|
#else
|
||||||
// need more events for automated test
|
|
||||||
static volatile int chartSize = 400;
|
|
||||||
#define WAVE_LOGGING_SIZE 35000
|
#define WAVE_LOGGING_SIZE 35000
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -80,12 +79,12 @@ static char WAVE_LOGGING_BUFFER[WAVE_LOGGING_SIZE] CCM_OPTIONAL
|
||||||
;
|
;
|
||||||
|
|
||||||
static int isWaveChartFull(WaveChart *chart) {
|
static int isWaveChartFull(WaveChart *chart) {
|
||||||
return chart->counter >= chartSize;
|
return chart->counter >= engineConfiguration->digitalChartSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void printStatus(void) {
|
static void printStatus(void) {
|
||||||
scheduleIntValue(&logger, "chart", isChartActive);
|
scheduleIntValue(&logger, "chart", isChartActive);
|
||||||
scheduleIntValue(&logger, "chartsize", chartSize);
|
scheduleIntValue(&logger, "chartsize", engineConfiguration->digitalChartSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setChartActive(int value) {
|
static void setChartActive(int value) {
|
||||||
|
@ -94,10 +93,10 @@ static void setChartActive(int value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void setChartSize(int newSize) {
|
void setChartSize(int newSize) {
|
||||||
if (newSize < 5) {
|
if (newSize < 5) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
chartSize = newSize;
|
engineConfiguration->digitalChartSize = newSize;
|
||||||
printStatus();
|
printStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,10 +114,10 @@ void publishChart(WaveChart *chart) {
|
||||||
Logging *l = &chart->logging;
|
Logging *l = &chart->logging;
|
||||||
scheduleSimpleMsg(&debugLogging, "IT'S TIME", strlen(l->buffer));
|
scheduleSimpleMsg(&debugLogging, "IT'S TIME", strlen(l->buffer));
|
||||||
#endif
|
#endif
|
||||||
bool isFullLog = getFullLog();
|
bool isFullLog = getFullLog();
|
||||||
if (isChartActive && isFullLog) {
|
if (isChartActive && isFullLog) {
|
||||||
scheduleLogging(&chart->logging);
|
scheduleLogging(&chart->logging);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static char timeBuffer[10];
|
static char timeBuffer[10];
|
||||||
|
@ -133,20 +132,19 @@ void addWaveChartEvent3(WaveChart *chart, const char *name, const char * msg, co
|
||||||
#endif
|
#endif
|
||||||
if (isWaveChartFull(chart)) {
|
if (isWaveChartFull(chart)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if EFI_HISTOGRAMS && EFI_PROD_CODE
|
#if EFI_HISTOGRAMS && EFI_PROD_CODE
|
||||||
int beforeCallback = hal_lld_get_counter_value();
|
int beforeCallback = hal_lld_get_counter_value();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
int time100 = getTimeNowUs() / 10;
|
int time100 = getTimeNowUs() / 10;
|
||||||
|
|
||||||
bool alreadyLocked = lockOutputBuffer(); // we have multiple threads writing to the same output buffer
|
bool alreadyLocked = lockOutputBuffer(); // we have multiple threads writing to the same output buffer
|
||||||
|
|
||||||
if (chart->counter == 0) {
|
if (chart->counter == 0) {
|
||||||
chart->startTime = time100;
|
chart->startTime = time100;
|
||||||
}
|
}
|
||||||
chart->counter++;
|
chart->counter++;
|
||||||
if (remainingSize(&chart->logging) > 30) {
|
if (remainingSize(&chart->logging) > 30) {
|
||||||
/**
|
/**
|
||||||
|
@ -168,13 +166,13 @@ void addWaveChartEvent3(WaveChart *chart, const char *name, const char * msg, co
|
||||||
}
|
}
|
||||||
if (!alreadyLocked) {
|
if (!alreadyLocked) {
|
||||||
unlockOutputBuffer();
|
unlockOutputBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if EFI_HISTOGRAMS && EFI_PROD_CODE
|
#if EFI_HISTOGRAMS && EFI_PROD_CODE
|
||||||
int64_t diff = hal_lld_get_counter_value() - beforeCallback;
|
int64_t diff = hal_lld_get_counter_value() - beforeCallback;
|
||||||
if (diff > 0) {
|
if (diff > 0) {
|
||||||
hsAdd(&waveChartHisto, diff);
|
hsAdd(&waveChartHisto, diff);
|
||||||
}
|
}
|
||||||
#endif /* EFI_HISTOGRAMS */
|
#endif /* EFI_HISTOGRAMS */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -190,7 +188,7 @@ void initWaveChart(WaveChart *chart) {
|
||||||
|
|
||||||
if (!isChartActive) {
|
if (!isChartActive) {
|
||||||
printMsg(&logger, "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! chart disabled");
|
printMsg(&logger, "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! chart disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
printStatus();
|
printStatus();
|
||||||
|
|
||||||
|
|
|
@ -110,25 +110,6 @@ const char* getConfigurationName(engine_configuration_s *engineConfiguration) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char * pinModeToString(pin_output_mode_e mode) {
|
|
||||||
switch (mode) {
|
|
||||||
case OM_DEFAULT:
|
|
||||||
return "default";
|
|
||||||
case OM_INVERTED:
|
|
||||||
return "inverted";
|
|
||||||
case OM_OPENDRAIN:
|
|
||||||
return "open drain";
|
|
||||||
case OM_OPENDRAIN_INVERTED:
|
|
||||||
return "open drain inverted";
|
|
||||||
default:
|
|
||||||
return "unexpected";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char * boolToString(bool value) {
|
|
||||||
return value ? "Yes" : "No";
|
|
||||||
}
|
|
||||||
|
|
||||||
extern board_configuration_s *boardConfiguration;
|
extern board_configuration_s *boardConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -190,8 +171,6 @@ void printConfiguration(engine_configuration_s *engineConfiguration, engine_conf
|
||||||
pinModeToString(boardConfiguration->malfunctionIndicatorPinMode));
|
pinModeToString(boardConfiguration->malfunctionIndicatorPinMode));
|
||||||
scheduleMsg(&logger, "analogInputDividerCoefficient: %f", engineConfiguration->analogInputDividerCoefficient);
|
scheduleMsg(&logger, "analogInputDividerCoefficient: %f", engineConfiguration->analogInputDividerCoefficient);
|
||||||
|
|
||||||
scheduleMsg(&logger, "needSecondTriggerInput: %s", boolToString(engineConfiguration->needSecondTriggerInput));
|
|
||||||
|
|
||||||
#if EFI_PROD_CODE
|
#if EFI_PROD_CODE
|
||||||
scheduleMsg(&logger, "idleValvePin: %s", hwPortname(boardConfiguration->idleValvePin));
|
scheduleMsg(&logger, "idleValvePin: %s", hwPortname(boardConfiguration->idleValvePin));
|
||||||
scheduleMsg(&logger, "fuelPumpPin: mode %s @ %s", pinModeToString(boardConfiguration->fuelPumpPinMode),
|
scheduleMsg(&logger, "fuelPumpPin: mode %s @ %s", pinModeToString(boardConfiguration->fuelPumpPinMode),
|
||||||
|
@ -211,18 +190,6 @@ void printConfiguration(engine_configuration_s *engineConfiguration, engine_conf
|
||||||
scheduleMsg(&logger, "ignition %d @ %s", i, hwPortname(brainPin));
|
scheduleMsg(&logger, "ignition %d @ %s", i, hwPortname(brainPin));
|
||||||
}
|
}
|
||||||
|
|
||||||
scheduleMsg(&logger, "primary trigger simulator: %s %s", hwPortname(boardConfiguration->triggerSimulatorPins[0]),
|
|
||||||
pinModeToString(boardConfiguration->triggerSimulatorPinModes[0]));
|
|
||||||
scheduleMsg(&logger, "secondary trigger simulator: %s %s", hwPortname(boardConfiguration->triggerSimulatorPins[1]),
|
|
||||||
pinModeToString(boardConfiguration->triggerSimulatorPinModes[1]));
|
|
||||||
scheduleMsg(&logger, "3rd trigger simulator: %s %s", hwPortname(boardConfiguration->triggerSimulatorPins[2]),
|
|
||||||
pinModeToString(boardConfiguration->triggerSimulatorPinModes[2]));
|
|
||||||
|
|
||||||
scheduleMsg(&logger, "primary trigger input: %s", hwPortname(boardConfiguration->triggerInputPins[0]));
|
|
||||||
scheduleMsg(&logger, "secondary trigger input: %s", hwPortname(boardConfiguration->triggerInputPins[1]));
|
|
||||||
scheduleMsg(&logger, "primary logic input: %s", hwPortname(boardConfiguration->logicAnalyzerPins[0]));
|
|
||||||
scheduleMsg(&logger, "secondary logic input: %s", hwPortname(boardConfiguration->logicAnalyzerPins[1]));
|
|
||||||
|
|
||||||
scheduleMsg(&logger, "boardTestModeJumperPin: %s", hwPortname(boardConfiguration->boardTestModeJumperPin));
|
scheduleMsg(&logger, "boardTestModeJumperPin: %s", hwPortname(boardConfiguration->boardTestModeJumperPin));
|
||||||
|
|
||||||
scheduleMsg(&logger, "digitalPotentiometerSpiDevice %d", boardConfiguration->digitalPotentiometerSpiDevice);
|
scheduleMsg(&logger, "digitalPotentiometerSpiDevice %d", boardConfiguration->digitalPotentiometerSpiDevice);
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "engine_configuration.h"
|
#include "engine_configuration.h"
|
||||||
#include "listener_array.h"
|
#include "listener_array.h"
|
||||||
#include "data_buffer.h"
|
#include "data_buffer.h"
|
||||||
|
#include "pin_repository.h"
|
||||||
#include "histogram.h"
|
#include "histogram.h"
|
||||||
#if EFI_PROD_CODE
|
#if EFI_PROD_CODE
|
||||||
#include "rfiutil.h"
|
#include "rfiutil.h"
|
||||||
|
@ -24,7 +25,7 @@ static volatile uint64_t previousShaftEventTime = (efitimems_t) -10 * US_PER_SEC
|
||||||
|
|
||||||
TriggerCentral triggerCentral;
|
TriggerCentral triggerCentral;
|
||||||
|
|
||||||
static Logging logging;
|
static Logging logger;
|
||||||
|
|
||||||
uint64_t getCrankEventCounter() {
|
uint64_t getCrankEventCounter() {
|
||||||
return triggerCentral.triggerState.getTotalEventCounter();
|
return triggerCentral.triggerState.getTotalEventCounter();
|
||||||
|
@ -106,7 +107,7 @@ void TriggerCentral::handleShaftSignal(configuration_s *configuration, trigger_e
|
||||||
#if EFI_PROD_CODE
|
#if EFI_PROD_CODE
|
||||||
// this temporary code is about trigger noise debugging
|
// this temporary code is about trigger noise debugging
|
||||||
for (int i = 0; i < HW_EVENT_TYPES; i++) {
|
for (int i = 0; i < HW_EVENT_TYPES; i++) {
|
||||||
scheduleMsg(&logging, "event type: %d count=%d", i, hwEventCounters[i]);
|
scheduleMsg(&logger, "event type: %d count=%d", i, hwEventCounters[i]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -141,7 +142,7 @@ void TriggerCentral::handleShaftSignal(configuration_s *configuration, trigger_e
|
||||||
|
|
||||||
void printAllCallbacksHistogram(void) {
|
void printAllCallbacksHistogram(void) {
|
||||||
#if EFI_PROD_CODE
|
#if EFI_PROD_CODE
|
||||||
printHistogram(&logging, &triggerCallback);
|
printHistogram(&logger, &triggerCallback);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,18 +150,41 @@ void printAllCallbacksHistogram(void) {
|
||||||
// todo: eliminate this extern which is needed by 'triggerInfo'
|
// todo: eliminate this extern which is needed by 'triggerInfo'
|
||||||
extern engine_configuration_s *engineConfiguration;
|
extern engine_configuration_s *engineConfiguration;
|
||||||
extern engine_configuration2_s * engineConfiguration2;
|
extern engine_configuration2_s * engineConfiguration2;
|
||||||
|
extern board_configuration_s *boardConfiguration;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void triggerInfo() {
|
static void triggerInfo() {
|
||||||
#if EFI_PROD_CODE || EFI_SIMULATOR
|
#if EFI_PROD_CODE || EFI_SIMULATOR
|
||||||
scheduleMsg(&logging, "trigger event counters %d/%d/%d/%d", triggerCentral.getHwEventCounter(0),
|
scheduleMsg(&logger, "Template %s/%d trigger %d", getConfigurationName(engineConfiguration),
|
||||||
|
engineConfiguration->engineType, engineConfiguration->triggerConfig.triggerType);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
scheduleMsg(&logger, "trigger event counters %d/%d/%d/%d", triggerCentral.getHwEventCounter(0),
|
||||||
triggerCentral.getHwEventCounter(1), triggerCentral.getHwEventCounter(2),
|
triggerCentral.getHwEventCounter(1), triggerCentral.getHwEventCounter(2),
|
||||||
triggerCentral.getHwEventCounter(3));
|
triggerCentral.getHwEventCounter(3));
|
||||||
scheduleMsg(&logging, "trigger type=%d/need2ndChannel=%d",
|
scheduleMsg(&logger, "expected cycle events %d/%d/%d",
|
||||||
|
engineConfiguration2->triggerShape.expectedEventCount[0],
|
||||||
|
engineConfiguration2->triggerShape.expectedEventCount[1],
|
||||||
|
engineConfiguration2->triggerShape.expectedEventCount[2]);
|
||||||
|
|
||||||
|
scheduleMsg(&logger, "trigger type=%d/need2ndChannel=%s",
|
||||||
engineConfiguration->triggerConfig.triggerType,
|
engineConfiguration->triggerConfig.triggerType,
|
||||||
engineConfiguration->needSecondTriggerInput);
|
boolToString(engineConfiguration->needSecondTriggerInput));
|
||||||
scheduleMsg(&logging, "expected duty #0=%f/#1=%f", engineConfiguration2->triggerShape.dutyCycle[0],
|
scheduleMsg(&logger, "expected duty #0=%f/#1=%f", engineConfiguration2->triggerShape.dutyCycle[0],
|
||||||
engineConfiguration2->triggerShape.dutyCycle[1]);
|
engineConfiguration2->triggerShape.dutyCycle[1]);
|
||||||
|
|
||||||
|
scheduleMsg(&logger, "primary trigger simulator: %s %s", hwPortname(boardConfiguration->triggerSimulatorPins[0]),
|
||||||
|
pinModeToString(boardConfiguration->triggerSimulatorPinModes[0]));
|
||||||
|
scheduleMsg(&logger, "secondary trigger simulator: %s %s", hwPortname(boardConfiguration->triggerSimulatorPins[1]),
|
||||||
|
pinModeToString(boardConfiguration->triggerSimulatorPinModes[1]));
|
||||||
|
scheduleMsg(&logger, "3rd trigger simulator: %s %s", hwPortname(boardConfiguration->triggerSimulatorPins[2]),
|
||||||
|
pinModeToString(boardConfiguration->triggerSimulatorPinModes[2]));
|
||||||
|
|
||||||
|
scheduleMsg(&logger, "primary trigger input: %s", hwPortname(boardConfiguration->triggerInputPins[0]));
|
||||||
|
scheduleMsg(&logger, "secondary trigger input: %s", hwPortname(boardConfiguration->triggerInputPins[1]));
|
||||||
|
scheduleMsg(&logger, "primary logic input: %s", hwPortname(boardConfiguration->logicAnalyzerPins[0]));
|
||||||
|
scheduleMsg(&logger, "secondary logic input: %s", hwPortname(boardConfiguration->logicAnalyzerPins[1]));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,7 +194,7 @@ float getTriggerDutyCycle(int index) {
|
||||||
|
|
||||||
void initTriggerCentral(void) {
|
void initTriggerCentral(void) {
|
||||||
#if EFI_PROD_CODE || EFI_SIMULATOR
|
#if EFI_PROD_CODE || EFI_SIMULATOR
|
||||||
initLogging(&logging, "ShaftPosition");
|
initLogging(&logger, "ShaftPosition");
|
||||||
addConsoleAction("triggerinfo", triggerInfo);
|
addConsoleAction("triggerinfo", triggerInfo);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -102,6 +102,21 @@ brain_pin_e parseBrainPin(const char *str) {
|
||||||
return basePin + pin;
|
return basePin + pin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char * pinModeToString(pin_output_mode_e mode) {
|
||||||
|
switch (mode) {
|
||||||
|
case OM_DEFAULT:
|
||||||
|
return "default";
|
||||||
|
case OM_INVERTED:
|
||||||
|
return "inverted";
|
||||||
|
case OM_OPENDRAIN:
|
||||||
|
return "open drain";
|
||||||
|
case OM_OPENDRAIN_INVERTED:
|
||||||
|
return "open drain inverted";
|
||||||
|
default:
|
||||||
|
return "unexpected";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
char *hwPortname(brain_pin_e brainPin) {
|
char *hwPortname(brain_pin_e brainPin) {
|
||||||
if (brainPin == GPIO_INVALID) {
|
if (brainPin == GPIO_INVALID) {
|
||||||
return "INVALID";
|
return "INVALID";
|
||||||
|
|
|
@ -24,6 +24,7 @@ extern "C"
|
||||||
|
|
||||||
void initPinRepository(void);
|
void initPinRepository(void);
|
||||||
char *hwPortname(brain_pin_e brainPin);
|
char *hwPortname(brain_pin_e brainPin);
|
||||||
|
const char * pinModeToString(pin_output_mode_e mode);
|
||||||
brain_pin_e parseBrainPin(const char *str);
|
brain_pin_e parseBrainPin(const char *str);
|
||||||
void mySetPadMode(const char *msg, ioportid_t port, ioportmask_t pin, iomode_t mode);
|
void mySetPadMode(const char *msg, ioportid_t port, ioportmask_t pin, iomode_t mode);
|
||||||
char *portname(GPIO_TypeDef* GPIOx);
|
char *portname(GPIO_TypeDef* GPIOx);
|
||||||
|
|
|
@ -20,6 +20,10 @@ bool cisnan(float f) {
|
||||||
return *(((int*) (&f))) == 0x7FC00000;
|
return *(((int*) (&f))) == 0x7FC00000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char * boolToString(bool value) {
|
||||||
|
return value ? "Yes" : "No";
|
||||||
|
}
|
||||||
|
|
||||||
int minI(int i1, int i2) {
|
int minI(int i1, int i2) {
|
||||||
return i1 < i2 ? i1 : i2;
|
return i1 < i2 ? i1 : i2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,8 @@ extern "C"
|
||||||
|
|
||||||
#define ERROR_CODE -11223344
|
#define ERROR_CODE -11223344
|
||||||
|
|
||||||
|
const char * boolToString(bool value);
|
||||||
|
|
||||||
int indexOf(const char *string, char ch);
|
int indexOf(const char *string, char ch);
|
||||||
float atoff(const char *string);
|
float atoff(const char *string);
|
||||||
int atoi(const char *string);
|
int atoi(const char *string);
|
||||||
|
|
Loading…
Reference in New Issue