Time your pocket computers with good precision

Talk in English

Modérateur : Politburo

Répondre
Avatar du membre
Jamel
Fonctionne à 1200 bauds
Fonctionne à 1200 bauds
Messages : 348
Enregistré le : 16 févr. 2006 16:07
Localisation : Orégon - USA
Contact :

Time your pocket computers with good precision

Message par Jamel »

Hi friends,

Some of you may know/remember that I am working on a book dedicated to C language programmable pocket computers. Since it is Christmas (vacation, yeah! :D), I took the time to work on a tool required to collect performance data. I have to start somewhere :wink:. Indeed, none of the pockets have precise timing functions, and manual timing is not really an option. After thinking about the problem for a while, I came up with a simple external solution (rather than trying to find some – hidden – internals). This also allows for a fair comparison of time data between different classes of devices of various brands (SHARP & CASIO in my case). Last but not least, I am sharing this information right now so others may find this information useful for their own work – and also because I am far from being done with my book, so if you had to wait for its completion... :oops:.
OK. So, what is the solution? It is pretty simple in fact. I am using a micro-controller to time any code section running on the pocket computer. A section of code is defined between a START and a STOP command received by the micro-controller. Commands are simple bit patterns sent through any built-in language specific IO command. An IO port Is of course required on the System Under Test (SUT). I do prefer serial IOes vs. expansion buses for ease of implementation and for ubiquity.
A simple C code runs on the micro-controller. It samples well-selected IO pins (SUT dependent, check the user guide) connected to the micro-controller ADC. It then looks for START and STOP commands. On START, time is measured (using the micro-controller high precision timer). On STOP, elapsed time is measured. Data is then sent to any device using a serial communication (data is sent in CSV format for easy import into spreadsheet programs). And I think that it is it.
As per my implementation, I am using an Arduino Mega board. Measurement has a ~1ms precision. For my first test, I am using a SHARP PC-G850VS. The picture /movie file names should be self-explanatory. https://plus.google.com/photos/11113672 ... 0866175361

Have fun,
-Jamel

Note: this post is in English because most of us can decipher it, and many non-french speaking folks may enjoy it :wink:

The header file (pocket_timer.h):

Code : Tout sélectionner

//-----------------------------------------------------------------------------
// This program allows an application running on a pocket computer to time
// itself issuing command to the micro-controller. The timer resolution is 1ms.
// The remote application can issue the following commands: START and STOP.
// Any other command is considered as NOP.
//
// Analog pins A and B are used to generate the commands. When a pin is in 
// high state, the corresponding bit is considered set.
//
//    +--------+--------+------------------+
//    |  PINA  |  PINB  |     COMMAND      |
//    +--------+--------+------------------+
//    |    1   |    0   | START            |
//    +--------+--------+------------------+
//    |    0   |    1   | STOP             |
//    +--------+--------+------------------+
//    |    x   |    x   | NOP              |
//    +--------+--------+------------------+
//
// Sample remote codes:
//
//    BASIC (SHARP PC-G850)
//    -------------------
//    10 OPEN "COM:"
//    20 C = 0
//    30 OUT 0
//    40 OUT 1
//    50 FOR I = 1 TO X (set X to any value)
//    60 NEXT I
//    70 OUT 2
//    80 OUT 0
//    90 C = C + 1
//   100 IF C < 101 GOTO 30
//   110 CLOSE
//
//    C (SHARP PC-G850)
//    -----------------
//    main(){
//      int i=0;
//      int c=0;
//      for(c=0;c<100;c++){
//        miniput(0);
//        miniput(1);
//        for(i=0;i<X;i++); (set X to any value)
//        miniput(2);
//      }
//      miniput(0);
//    }
//
//    In RUN mode (SHARP PC-G850)
//    ---------------------------
//    OUT 0
//    OUT 1
//    ... (do whatever you want to time)
//    OUT 2
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Defines.
// Notes:
//    +---------------+----------------------------------+
//    | SYSTEM        | INTERFACE/PORT:PIN               |
//    +---------------+----------------------------------+
//    | PC-G850VS     | 11 pin, A:7, B:5 (1=top). SG:3   |
//    +---------------+----------------------------------+
//    Also connect SG to GND if available.
//-----------------------------------------------------------------------------
#define START_PIN 4 // PIN A
#define STOP_PIN 6 // PIN B
#define HEADER_STRING "Measurement #, Time (ms)"
#define MAX_SAMPLE_VALUE 1023

//-----------------------------------------------------------------------------
// Enums.
//-----------------------------------------------------------------------------
typedef enum _commands {

	NOP = 0,
	START = 1,
	STOP = 2

} COMMAND, *PCOMMAND;

//-----------------------------------------------------------------------------
// Macros.
// Assumes char buffer[256] = { '\0' }; in the scope.
//-----------------------------------------------------------------------------
//#define _DEBUG 1
#define PRINT_START(n) \
	do { \
		snprintf( \
			buffer, \
			sizeof(buffer), \
			"%lu, ", \
			(n)\
		); \
		Serial.print(buffer); \
	} while(0)
//-----------------------------------------------------------------------------
#define PRINT_STOP(n) \
	do { \
		snprintf( \
			buffer, \
			sizeof(buffer), \
			"%lu", \
			(n) \
		); \
		Serial.println(buffer); \
	} while(0)
//-----------------------------------------------------------------------------
#define PRINT_INIT \
	do { \
		snprintf( \
			buffer, \
			sizeof(buffer), \
			"Initialized" \
		); \
		Serial.println(buffer); \
	} while(0)
//-----------------------------------------------------------------------------
#ifdef _DEBUG
	#define DEBUG_TRACE(s) \
		do { \
			snprintf( \
				buffer, \
				sizeof(buffer), \
				"%s", \
				(s) \
			); \
			Serial.println(buffer); \
		} while(0)
	//-------------------------------------------------------------------------
	#define DEBUG_READINGS(a, b) \
		do { \
			snprintf( \
				buffer, \
				sizeof(buffer), \
				"[%d%d]", \
				(a), \
				(b) \
			); \
			Serial.println(buffer); \
		} while(0)

#else // _DEBUG
	#define DEBUG_TRACE(s) \
		;
	#define DEBUG_READINGS(a, b) \
		;
#endif // _DEBUG
The code file now (pocket_timer.pde - this is C in a MSVC/Arduino project):

Code : Tout sélectionner

//-----------------------------------------------------------------------------
// This program allows an application running on a pocket computer to time
// itself issuing command to the micro-controller. The timer resolution is 1ms.
// The remote application can issue the following commands: START and STOP.
// Any other command is considered as NOP.
//
// Analog pins A and B are used to generate the commands. When a pin is in 
// high state, the corresponding bit is considered set.
//
//    +--------+--------+------------------+
//    |  PINA  |  PINB  |     COMMAND      |
//    +--------+--------+------------------+
//    |    1   |    0   | START            |
//    +--------+--------+------------------+
//    |    0   |    1   | STOP             |
//    +--------+--------+------------------+
//    |    x   |    x   | NOP              |
//    +--------+--------+------------------+
//
// Sample remote codes:
//
//    BASIC (SHARP PC-G850)
//    -------------------
//    10 OPEN "COM:"
//    20 C = 0
//    30 OUT 0
//    40 OUT 1
//    50 FOR I = 1 TO X (set X to any value)
//    60 NEXT I
//    70 OUT 2
//    80 OUT 0
//    90 C = C + 1
//   100 IF C < 101 GOTO 30
//   110 CLOSE
//
//    C (SHARP PC-G850)
//    -----------------
//    main(){
//      int i=0;
//      int c=0;
//      for(c=0;c<100;c++){
//        miniput(0);
//        miniput(1);
//        for(i=0;i<X;i++); (set X to any value)
//        miniput(2);
//      }
//      miniput(0);
//    }
//
//    In RUN mode (SHARP PC-G850)
//    ---------------------------
//    OUT 0
//    OUT 1
//    ... (do whatever you want to time)
//    OUT 2
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Header(s) inclusion(s).
//-----------------------------------------------------------------------------
#include "pocket_timer.h"

/*-----------------------------------------------------------------------------
Function: setup.
Purpose : Setup serial comms and analog port sampling.
          debug is active.
In      : none.
Out     : none.
Return  : none.

History
-------------------------------------------------------------------------------
Date        : Author                  Modification
-------------------------------------------------------------------------------
12/23/2012    Jamel Tayeb             Creation.
*/
void setup() {
	Serial.begin(115200);
	analogReference(INTERNAL2V56);
	Serial.println(HEADER_STRING);
}

/*-----------------------------------------------------------------------------
Function: loop.
Purpose : sample command pins, measure elapsed time and transmit data.
In      : none.
Out     : none.
Return  : none.

History
-------------------------------------------------------------------------------
Date        : Author                  Modification
-------------------------------------------------------------------------------
12/23/2012    Jamel Tayeb             Creation.
*/
void loop() {

	//-------------------------------------------------------------------------
	// Generic variables.
	//-------------------------------------------------------------------------
	static unsigned long int sequence = 0;
	char buffer[256] = { '\0' };

	//-------------------------------------------------------------------------
	// A/D variables.
	//-------------------------------------------------------------------------
	int start_pin_value = 0;
	int stop_pin_value = 0;

	//-------------------------------------------------------------------------
	// Timing variables.
	//-------------------------------------------------------------------------

	static unsigned long int start = 0;
	static unsigned long int stop = 0;
	unsigned long int elapsed = 0;

	//-------------------------------------------------------------------------
	// Driving variables.
	//-------------------------------------------------------------------------
	static int f_running = 0;
	int command = NOP;

	//-------------------------------------------------------------------------
	// Loop forever.
	//-------------------------------------------------------------------------
	do {

		//---------------------------------------------------------------------
		// Sample command pins.
		//---------------------------------------------------------------------
		start_pin_value = analogRead(START_PIN);
		stop_pin_value = analogRead(STOP_PIN);

		//---------------------------------------------------------------------
		// Filter readings.
		//---------------------------------------------------------------------
		if(start_pin_value == MAX_SAMPLE_VALUE) {
			start_pin_value = START;
		} else {
			start_pin_value = 0;
		}
		if(stop_pin_value == MAX_SAMPLE_VALUE) {
			stop_pin_value = STOP;
		} else {
			stop_pin_value = 0;
		}
		DEBUG_READINGS(
			start_pin_value,
			stop_pin_value
		);

		//---------------------------------------------------------------------
		// Decode command.
		//---------------------------------------------------------------------
		command = 
			NOP + 
			start_pin_value + 
			stop_pin_value
		;

		//---------------------------------------------------------------------
		// Process command.
		//---------------------------------------------------------------------
		switch(command) {

			case START:

				//-------------------------------------------------------------
				// Start timing sequence.
				//-------------------------------------------------------------
				if(f_running == 0) {
					start = millis();
					f_running = 1;
					PRINT_START(sequence++);
				}
				break;

			case STOP:

				//-------------------------------------------------------------
				// Stop timing sequence and report total duration (since last
				// START command).
				//-------------------------------------------------------------
				if(f_running == 1) {
					stop = millis();
					f_running = 0;
					elapsed = stop - start;
					PRINT_STOP(elapsed);
				}
				break;

			case NOP: // fall through
			default:
				;
		} // switch (command)
	} while(0);
}
Some data (taken from the BASIC sample):

Code : Tout sélectionner

Port open
Measurement #, Time (ms)
0, 117
1, 1338
2, 1339
3, 1337
4, 1340
5, 1337
6, 1339
7, 1337
8, 1339
9, 1337
10, 1340
11, 1338
12, 1339
13, 1337
14, 1339
15, 1338
16, 1339
17, 1338
18, 1338
19, 1338
20, 1339
21, 1338
22, 1339
23, 1337
24, 1340
25, 1337
26, 1340
27, 1337
28, 1339
29, 1337
30, 1340
31, 1337
32, 1338
33, 1338
34, 1339
35, 1338
36, 1339
37, 1338
38, 1339
39, 1339
40, 1339
41, 1337
42, 1339
43, 1337
44, 1340
45, 1337
46, 1340
47, 1337
48, 1340
49, 1338
50, 1339
51, 1337
52, 1339
53, 1339
54, 1339
55, 1338
56, 1338
57, 1338
58, 1339
59, 1337
60, 1339
61, 1337
62, 1340
63, 1338
64, 1340
65, 1337
66, 1340
67, 1338
68, 1339
69, 1337
70, 1339
71, 1338
72, 1339
73, 1338
74, 1339
75, 1338
76, 1339
77, 1339
78, 1339
79, 1337
80, 1340
81, 1338
82, 1340
83, 1337
84, 1340
85, 1337
86, 1340
87, 1338
88, 1339
89, 1337
90, 1339
91, 1339
92, 1339
93, 1338
94, 1339
95, 1338
96, 1339
97, 1337
98, 1339
99, 1337
And then, using the C interpreter:

Code : Tout sélectionner

Port open
Measurement #, Time (ms)
0, 42
1, 41
2, 41
3, 41
4, 41
5, 41
6, 41
7, 41
8, 42
9, 41
10, 41
11, 41
12, 42
13, 41
14, 41
15, 41
16, 42
17, 41
18, 41
19, 41
20, 42
21, 41
22, 41
23, 41
24, 41
25, 41
26, 41
27, 41
28, 40
29, 41
30, 40
31, 40
32, 41
33, 40
34, 41
35, 41
36, 41
37, 41
38, 41
39, 41
40, 41
41, 41
42, 41
43, 41
44, 41
45, 41
46, 41
47, 41
48, 41
49, 41
50, 41
51, 41
52, 41
53, 41
54, 41
55, 41
56, 41
57, 41
58, 41
59, 41
60, 41
61, 41
62, 41
63, 41
64, 41
65, 41
66, 41
67, 41
68, 41
69, 41
70, 41
71, 41
72, 41
73, 41
74, 41
75, 41
76, 41
77, 41
78, 41
79, 41
80, 41
81, 41
82, 41
83, 41
84, 41
85, 41
86, 41
87, 41
88, 41
89, 41
90, 41
91, 41
92, 41
93, 41
94, 41
95, 41
96, 41
97, 41
98, 41
99, 41
Répondre

Retourner vers « Silicium in English »