193 AandC: ixmRPC (eRPC lite) Remote Procedure Calls (193.html)

My earlier article (191) introduced the eRPC system. Another significant application of the WioTerminal is for Acquisition and Control (ie Sense and Control) such as my PiR2 Temperature Logger. This article describes in detail, a new eRPC system: the ixmRPC using MicroPython (not c/c++). I intend to use ixmRPC to port code between cores (computers) and between programming languages. The ixmRPC system will hopefully simplify the interchange of various sensors and actuators, by keeping much of the software intact.

A Remote Procedure Call (RPC) is software that replaces a physical "wire". For this software to function correctly, it must reside in a folder in a computer. The software makes use of data that moves (is transported) from one computer to another. Some text files are required because they hold the definitions of the type of data, where it comes from and where it goes to. Finally a person (or the software) must prepare the data that is sent to the other computer. In eRPC, the data must be defined in enough detail so that the eRPC system, itself, can create all of this software. In the ixmRPC system, a programmer must actually write (ie code) the software. The CRS table is where much of this technical information is stored.

Keywords

"193 AandC: ixmRPC (eRPC lite) Remote Procedure Calls (193.html)" A&C ambientLight ambLight "Acquisition and Control" "Acquisition & Control" "A & C" Acquisition amplitude API Blocking-Server "Blocking Server" c-wrapped Catch CfromF CfromF() CPython CircuitPython Client codec complex Control CRS .crs D@CC datum email eRPC "eRPC function names" eRPC-lite eRPClite "eRPC lite" "Fast Fourier Transform" FFT frequency github Grove HDMI header I2C ICH180RR IDL .idl imaginary Invert() IXcomplex "IXcomplex header" "IXcomplex preprocessor" ixmRPC ixTransport "Maker Pi Pico" MicroPython minicom Pico short PuTTY PIO PiR2 PiR2D PiR2Null PiR2P PiR2W Pix "Pix Explorer" PWM py Python Raspberry Reading "Remote Procedure Calls" RP2040 RPi sampling"SD card issue" Sense "serial USB" Server shim "shim code" "short integers" "Signal Reading Request" "short Python integers" sin sine SRR SPI state-machine "state machine" TA TAR TARK TCC TCCK TCK TCR "temperature sensor" Thonny Throw Transport uJoyStick Unity unity() "very slow Throw" VT100 wave waveform WioTerminal "Wio Terminal SD card issue".

(To enlarge .....Click it)
thumb: IXimage.jpg
IX or DC (IX by DC) or "|><"


This prepIX.py software is a part of the IX family of software.

Table of Contents

Introduction to ixmRPC (eRPC lite) Remote Procedure Calls 
ixmRPC (eRPC lite) Remote Procedure Calls
AandC My First RPC System: PiR2
    AandC System Description
    Essential Functions
    Secondary Functions
    Other Functions
IDL (Information Data or Library) 
Combining Two Readings
Client Code
Blocking-Server Code
The Actual Transport Mechanism
The ixTransport
Signal Reading Request (SRR)
Recommended ID ranges
IDL Connections: the Absolute Need for a CRS Table
The CRS Tables

still needs more work. . . . . . 

Signal Reading Request (SRR)
Definition of each Transport Cable
Using a VT100 (or minicom or PuTTY) with ixmRPC
Recommended ID ranges 
IDL Connections: the Absolute Need for a CRS Table
CRS Tables 
Various ConvertFunc Routines Are Needed
Folders Used By ixmRPC 
ixmRPC Waveforms
ixmRPC Lexicon (c2023)
SD card Issue Resolved as of 2021LDec17
Other Thoughts
Conclusion
Sources

Blacklist Virus was encountered

During a recent edit of this article (on 2023EMay04), Filezilla was not allowed to write to the Web, because the 193.html file was said to contain a Blacklist virus. I undid (Ctrl-z) then redid some edits and the problem disappeared. This is the second time today that this has occurred. It has never happened to me before.

Introduction to ixmRPC

Unfortunately, for a short while, the same "Introduction to ixmRPC" information was stored (and updated) in two places, in Articles 193 and 195. I will need to compare the text to ensure that both are identical and then delete one of them.

The eRPC mechanism provides a very comprehensive RPC (Remote Procedure Call) mechanism for the AandC (Acquisition and Control) world. It supports both c/c++ and Python code. But eRPC is a very powerful RPC mechanism. It is almost impossible to envisage eRPC in the Wio Terminal world, where only small amounts of RAM and Flash Memory exist.

The author decided to create ixmRPC which is a lite version of eRPC. The concepts of eRPC are maintained, but some of the powerful features of eRPC are left out. For example, ixmRPC only addresses the Python Server world. The Server cores are limited to Raspberry compatible cores such as the Raspberry Pi cores, the Raspberry RP2040 cores (eg in the Pico) and Wio Terminal cores. The eRPC system generates shim code for the Client and the Server. In ixmRPC, Client cores include the Raspberry Pi 4 and the Windows PC cores. But the ixmRPC system does NOT generate the final code nor the shim code automatically. The user (the programmer) must develop this code.

The ixmRPC tables are very limited at first. As more sensors are included in ixmRPC, more functions will be created in ixmRPC. These tables are not automatically used by ixmRPC. They are mostly references used when writing ixmRPC code or they are text files read by the ixmRPC code. Therefore they might be more forgiving of errors than the tables in the eRPC system. These articles by D@CC, introduce the concept of storing data samples in complex variables. The "real" part of the complex variable is used to store the datum (sample value) while the "imaginary" part (of each complex variable) is used to store the time. This "marries" the time of each sample to the sample. Simple math functions can be used to convert a Python "list" of complex variables into a "list" of real variables whenever necessary. Alternatively, if the samples are taken at very regular intervals, the imaginary information becomes redundant. For more information about this use of complex variables, refer to the author's articles numbered 75, 164, 165, 171 and 180.

For an explanation of the terms used in this article, refer to the "ixmRPC Lexicon" Heading near the end of this article.

This article covers the following topics that describe ixmRPC:

	Introduction to ixmRPC (eRPC lite) Remote Procedure Calls 
	The First Function Coded For ixmRPC
	IDL (Information Data Library) 
	Combining Two Readings
	Client Code
	Blocking-Server Code
	The Actual Transport Mechanism
	The Signal Reading Request (SRR)

	needs editting . . . . . . . 

	The ixTransport
	IDL Connections 
	Recommended ID ranges
	The CRS Tables
	Various ConvertFunc Routines Are Needed
	Folders Used By ixmRPC 
	Signal Reading Request (SRR)
	Using a VT100 (or minicom or PuTTY) with ixmRPC
	ixmRPC Waveforms
	ixmRPC Lexicon (c2023)
	SD card Issue Resolved as of 2021LDec17
	
This article (193) has been fully moved from Article 191 (as of 2023DApr28)

Introduction to ixmRPC (eRPC lite) Remote Procedure Calls

The ixmRPC is a lite version of eRPC. For those new to RPC, multiple tables must be created to define the characteristics of the AandC (Acquisition & Control) sensors and actuators. In ixmRPC, various programming languages (eg MicroPython and Circuit Python) are supported. The name "ixmRPC" implies that Remote Procedure Calls are defined in a Client core (machine). The requested action is sent to a Server Core (machine) where the action occurs. An RPC system usually permits the Client and Server to be the same machine. This is especially useful during testing.

The first advantage of the ixmRPC system is that code created to deal with "one set of sensors and actuators" can be easily ported to "a different set of sensor and actuators". Code written in CircuitPython can more easily be converted to the MicroPython world if the different routines for the two Pythons are easily implemented.

Another advantage of the ixmRPC system is that a totally different sensor (or actuator) from a different manufacturer can be easily implemented with minor code changes.

Two main tables of information are used in the ixmRPC system. The first is the IDL. The second is the CRS table. They are described below. The combination of these two tables pales when compared to the powerful eRPC system. But ixmRPC is not intended for the commercial world. Our target audience, the amateur programmers and electronics buffs are expected to make use of the ixmRPC system.

One drawback of the ixmRPC system is that more calling parameters are passed than in the eRPC system. But the passing of more calling parameters contributes to making ixmRPC simpler to implement than eRPC.

The main parts of ixmRPC are:

IDL - Interface Data Library
          defines a single datum source or target: signal or pin on a device (including the calling 
	  parameters with the Client IDL). Two IDLs are needed.
CRS - Client Routing to Server
          defines a "connection to be made" between Client (source) & Server (target). One CRS is needed.
SRR - Signal Reading/control Request
          is an instance of a reading/control signal. Each is a datum (a data instance) at a specific time.
          This requires two things: a "datum" and a "time-stamp".  I would recommend the use of complex 
	  numbers including the time-stamp as the "imaginary" part, but fear that it is too "complex" a
	  concept for the general public.

The above three parts of the ixmRPC must be defined.  They are needed when the UDR action occurs.

UDR - Unique Data Request
	Each UDR corresponds to a signal being "Thrown" ie transmitted.  For a signal to be 
	transmitted, the IDL, CRS and SRR must be referenced.
Each UDR is a signal that is thrown by defining a SRR that goes from an IDL via a CRS to another IDL.

Each UDR needs 6 things to be specified:
ID#  (unique identifier for this "signal" instance)
SRR# time stamp
IDL# source (ie client)
CRS# routing
IDL# target (ie server)
SRR datum  (data object with units of measurement)
The above concepts form the heart of the ixmRPC mechanism. They must be sufficient to completely define an instance of a signal that goes from a Client machine to a Server machine. In actual practise, two "commands" (or phrases) are necessary: one to define the routing (a virtual link or wire) and the second to define each (or many) signal instance(s) that is/are sent or received. Once a routing is defined, more than one signal instance can pass through the defined "routing" although different routing instances must be defined.

Example

An example of such an instance is as simple as:
"1,,6,0,0,1"   which defines the "Routing" or "Link" (the "6" is physical pin # 6 which is tied to a LED.)

and

"1,,TC,True"   which defines the signal (a reading or control action). 
               "TC,True" means "T"hrow a "C"ontrol signal to set the LED to "True" ie On.
The omitted parameter is the "time-stamp" which can automatically be inserted by ixmRPC.

To accomplish each action, the user (or his program) can merely send a pair of phrases like those in quotes above. All of the complexity around a single signal instance along a single wire is reduced to two simple text phrases. Of course, much more must be defined somehow somewhere for this to be possible. This article hopefully explains all that a user needs in order to understand how the ixmRPC (or any RPC) mechanism is possible.

The author apologises in advance for all of the "bad untested" Python code that is found below. However, some actual code is needed to truly "show" how RPC works at a "code" level. Python was chosen because it is the most popular programming language today (in 2023).

The First Function Coded For ixmRPC

The author has chosen a simple PushButton to be the first sensor function used by ixmRPC. A PushButton sensor was chosen because it requires the "Throwing" of a Request action. It also requires a Response which contains the status of the PushButton. Most actuators do not absolutely need a response. When a Client Request is "Thrown" to a Server, the Server "Catches" the request. Then the Server performs the requested action and/or returns the status of the sensor as a Response. The Throwing of the request means that the Request is transferred from one core (one machine ie a computer) to another core. The ixmRPC system often uses a serial USB cable to transport the Requests and the Responses. The eRPC system can also use I2C, WiFi, Bluetooth etc to transport the Requests and Responses. In the cases when the Client and Server cores are the same machine, no Transport is required; the Client routines communicate directly with the Server routines in the same machine.

The first AandC system to be described is the PiR2 Control system that was built by the author some years ago.

AandC My First RPC System: PiR2

The name of the AandC System is "PiR2 Temperature Control". It is a very simple RPC system.

AandC PiR2 System Description

The "PiR2 Temperature Control" system controls the ambient temperature in a local area. It measures the ambient temperature using an electronic thermometer. The system can also control a "Heater" that increases the temperature in the local area.

(To enlarge .....Click it)
thumb: IMG_4569.JPG
The first PiR2A Prototype



At the very left edge, one can see a set of pins that are used to plug into the Raspberry Pi GPIO connector. In the top left corner, the tiny red square board is the TMP102 thermometer. Barely visible is the little "heater" resistor than can be controlled to provide heat to the thermometer. This PiR2 prototype was the first server that the author created. A few internal test points are labelled near the left: 9, 11, 13 and 15 which are physical GPIO pin numbers. A number of labelled external test points can also be seen on the right. The name of the text file containing the external labels is perhaps the first IDL that the author created.

    Essential PiR2 Functions

The five essential functions (or parameters) are:

a) ask the user to define the desired temperature for the area. e.g. 16 degrees Centigrade.
b) function to read the temperature
c) function to add heat to the area. Because the "local area" is small enough, a tiny resistor is used as a heater.
d) ask the user to set the allowable range of temperatures. e.g. plus or minus 2%.
e) the name of the local area being controlled.

Three additional primary functions in the first PiR2 are:

f) the temperature of the internal processor (procTemp). It is included because it is easy to read.
g) the Serial Number of the Client core (which is also easy to read).
h) the IP address of the local Client router (similar to a TransportID).

The "Set-Point" is usually a little higher than the average temperature. This means that the temperature of the local area will slowly be lowered by ambient conditions.

The system is given some freedom so that the heater does not need to continually be functioning. To do this, the system also asks the user to define the acceptable range of termperature for the local area. The electronic thermometer is usually a TMP102 IC that communicates using I2C communications.

    Secondary Functions on some PiR2 models

The "Setting" and the "Range" are built into the program and cannot be changed in the first release of the PiR2 system. The secondary functions are:

i)	The system will display on a monitor the status of the system and what control actions are being taken.
ii)	The system will turn ON a yellow LED whenever the heater is turned ON.
     At first, the system has very limited comunications with the user. This communication is:
iii)	The system can only "talk" to the user by turning on a red led for a variable amount of time.
iv)	The system can ask the user a simple question by printing the question on a monitor.
v)	The user can answer the question by pressing a pushbutton for a variable amount of time.

    Additional Functions on some PiR2 models

Some of the PiR2 systems have the following latent functions:

	A Green (or White) LED
	digIn and digOut
	algIn and algOut
	1 or 2 digLight and/or algLight (using CD cells)
	an additional pushButton
	adcIn01 and adcIn02 (analog to digital converters)
	buzzer

    Additional Peripherals on some PiR2 models

Some of the PiR2 systems have the following peripherals or test-points:

	audioOut (via bluetooth or an audio jack or hdmi)
	hdmiOut (television monitor)
	humidity sensor
	USB charger (for iPhones etc)
	GND
	3v3
	5v0
There are two additional (non-physical) features of the PiR2: a data log and a web-site called "MehInCharge.com". The data log usually keeps a record of a set of samples every 10 seconds. This log can be uploaded to the MehInCharge.com website where the log can be viewed and/or graphed. The uploading of the log must be initiated manually. The MehInCharge website accepts control requests, that are saved until the next log is uploaded. At that time, the current list of latent control requests is downloaded and activated. Source 10 (www) is a link to the MehInCharge.com website. The non-www link of Source 10 is an Article describing the Meh In Charge website. At the www.MehInCharge.com website (shown below), one can see the first list of parameters (log data names) that were built into the PiR2 system. This site was the second Client RPC created by the author. The PiR2 Prototype in the above image is the Server for this RPC system. The first Client of this RPC system was the keyboard and monitor of the Raspberry Pi that is the Client core of this PiR2 RPC system.

(To enlarge .....Click it)
thumb: MIC.jpg
MehInCharge Web Site


CLICK HERE TO GO TO THE WEBSITE

IDL (Information Data or Library) A pushButton_001

The author (Webmaster D @ CC ) has created his first IDL for the ixmRPC system (shown below. It has been stored in Source 02. The first version of it appears below:

# This was changed on 2023DApr29
	Row Characteristic	Value		#Parm#  eg Value
	### #################	###########	#######	## ######

	01 IDL_ID		01		numeric

	#  Parameters Passed In
	#02 deviceObject			#Parm01 eg PB22
	#03 clientCoreID                     	#Parm02 eg "abf3"
	#04 serverCoreID                   	#Parm03 eg "abf3"
	#05 RPC:		ixmRPC		#Parm04 eg "ixmRPC"
	#06 GPIOPin:				#Parm05 eg GPIO22
	#07 PhysPin:				#Parm06 eg 15
	#08 SensorMfr:		Generic		#Parm07 eg "Generic"
	#09 SignalName		C(digIn00)	#Parm08 eg "digIn00"
	#10 TimeOutMSecs:	50000		#Parm09 eg 50000

	#   Transport (Virtual Wiring)
	11A TransportAID	Transport Cable ID
	11L LinkageA		serialUSB10	
	11F FactorA		lowTemp00
	12F FactorB		other IDL_ID	#	eg "" nul
	13 ReturnParm01:	OR(FactorA,FactorB)

	#   Shim-Specific
	14 Code:		MicroPython
	15 Mfr:			RPi
	16 Board:		4
	17 SensorModel		Raspberry

	#   "Constant" Attributes
	18 Unique ID		A_PushButton_001
	19 IDLvsn		01.00
	20 IDLauthor:		D@CC
	21 Date:		2023DApr24
	22 AorC:		A		#	meaning Acquire
	23 SensorType:		pushButton
	24 Units		Bool
	25 InitialState:	False

	#   Input Data Meaning
	26 Control Parm01	na
	27 CMeaning		na		#	na

	#   Returned Information
	28 ReturnParm01:	False		#	Returned
	29 AMeaning01:		Low		#	Voltage
	30 ReturnParm00:	intECode
	31 intECode00:		Success
	32 intECode01:		Timed Out
	33 intECode02:		Error Bad Parameter
	34 intECode03		Error na

	#/ixmRPC_pushButton_001.idl
	
The characteristics listed in the IDL above describe the sensor in fine detail. The IDL characteristics are grouped by:
	parameters passed in
	transport-specific
	shim-specific
	"constant" attributes
	input data meaning
	returned information

When generating the Client and Server routines (code), the IDL information is needed. Therefore it is in the .idl file (except for the passed parameters).

Note that, in the above IDL, there is no actual mention of the details of which pin the pushButton is connected to. Also the identification of the actual machine "cores" is not included. Such information could be defined in a client-specific file and in a server-specific file or in the parameters passed. To simplify the ixmRPC system, these specifics are sent as parameters when calling the client and server shim routines. Users who are familiar with sensors and actuators will be familiar with the idea of including these parameters when the devices are referenced. In the complex world of eRPC, the definition of the client and server core machines will be specified somewhere in text files. These Client and Server equipment details are also used when the shim files are modified to generate the final code from the shim routine code. The eRPC system is designed to "hide" all these details in the final code that is automatically generated.

Usually a Client sensor's value is equal to a Server sensor's value. In this case the RetunParm01 will be equal to the value of the Server's sensor. But occasionally, the Client sensor's Value is a function of two different readings. This is slightly awkward because the ReturnParm01 must be produced using a function of two values. These two values can be from a Client sensor's value and/or a Server sensor's value. These first two examples use functions of only one value. This is done by the following process:

FactorA      = S(digIn00)
FactorB      = Unity(1)
ReturnParm01 = FunctionC(FactorA,FactorB)

or

FactorA      = Unity(1)
FactorB      = Unity(1)
ReturnParm01 = S(digIn00)

In the case of a Server value, the result will be equal to S(digIn00)

IDL (Information Data or Library) C led_001

	Row Characteristic	Value		#Parm#  eg Value
	### #################	###########	#######	## ######

	01 IDL_ID		02		numeric

	#  Parameters Passed In
	#02 deviceObject			#Parm01 eg LED12
	#03 clientCoreID                     	#Parm02 eg "abf3"
	#04 serverCoreID                   	#Parm03 eg "abf3"
	#05 RPC:		ixmRPC		#Parm04 eg "ixmRPC"
	#06 GPIOPin:				#Parm05 eg GPIO12
	#07 PhysPin:				#Parm06 eg 32
	#08 SensorMfr:		Generic		#Parm07 eg "Generic"
	#09 SignalName		C(led12)	#Parm08 eg "led12"
	#10 TimeOutMSecs:	50000		#Parm09 eg 50000

	#   Transport (Virtual Wiring)
	11A TransportAID	Transport Cable ID
	11L LinkageA		serialUSB10	
	11F FactorA		led12
	12F FactorB		other IDL_ID	#	eg False
	13 ReturnParm01:	OR(FactorA,FactorB)

	#   Shim-Specific
	14 Code:		MicroPython
	15 Mfr:			RPi
	16 Board:		4
	17 SensorModel		Raspberry

	#   "Constant" Attributes

	18 Unique Name		A_led_001
	19 IDLvsn		01.00
	20 IDLauthor:		D@CC
	21 Date:		2023EMay11
	22 AorC:		C		#	meaning Control
	23 SensorType:		led
	24 Units		Bool
	25 InitialState:	False

	#   Input Data Meaning
	26 Control Parm01	True
	27 CMeaning		On		#	Lit

	#   Returned Information
	28 ReturnParm01:	True		#	Returned
	29 AMeaning01:		na		#	na
	30 ReturnParm00:	intECode
	31 intECode00:		Success
	32 intECode01:		Timed Out
	33 intECode02:		Error Bad Parameter
	34 intECode03		Error na

	#/ixmRPC_led_001.idl

Combining two readings

A case (real life example) of where two values must be combined into a single value is where either of two thermostats can call for heat. Say that 1 thermostat produces a lowTemp00 signal and the other produces lowTemp01. The formula to combine their signals is:

anyLowTemp = OR(lowTemp00,lowTemp01)
or
anyLowTemp = Sum(lowTemp00,lowTemp01)

IDL (Information Data or Library) A thermostat_001

The Sum of two boolean values is the same as the OR of the two values. The IDL to do this would be:
	Row Characteristic	Value		#Parm#  eg Value
	### #################	###########	#######	## ######

	01 IDL_ID		03		numeric

	#  Parameters Passed In
	#02 deviceObject			#Parm01 eg PB22
	#03 clientCoreID                     	#Parm02 eg "abf3"
	#04 serverCoreID                   	#Parm03 eg "abf3"
	#05 RPC:		ixmRPC		#Parm04 eg "ixmRPC"
	#06 GPIOPin:				#Parm05 eg GPIO22
	#07 PhysPin:				#Parm06 eg 15
	#08 SensorMfr:		Generic		#Parm07 eg "Generic"
	#09 SignalName		C(anyLowTemp00)	#Parm08 eg "anyLowTemp00"
	#10 TimeOutMSecs:	50000		#Parm09 eg 50000

	#   Transport (Virtual Wiring)
	11A TransportAID	Transport Cable ID
	11L LinkageA		serialUSB10	
	11F FactorA		anyLowTemp00
	12F FactorB		other IDL_ID	#	eg False
	13 ReturnParm01:	OR(FactorA,FactorB)

	#   Shim-Specific
	14 Code:		MicroPython
	15 Mfr:			Honeywell
	16 Board:		na
	17 SensorModel		RTH221B1039

	#   "Constant" Attributes

	18 Unique Name		A_Thermostat_001
	19 IDLvsn		01.00
	20 IDLauthor:		D@CC
	21 Date:		2023DApr24
	22 AorC:		A		#	meaning Acquire
	23 SensorType:		Thermostat
	24 Units		Bool
	25 InitialState:	False

	#   Input Data Meaning
	26 Control Parm01	na
	27 CMeaning		na		#	na

	#   Returned Information
	28 ReturnParm01:	False		#	Returned
	29 AMeaning01:		Low		#	Voltage
	30 ReturnParm00:	intECode
	31 intECode00:		Success
	32 intECode01:		Timed Out
	33 intECode02:		Error Bad Parameter
	34 intECode03		Error Constant Signal

	#/ixmRPC_thermostat_001.idl
Now, returning back to the first function example: the PushButton.

The first IDL text file (before the Thermostat) defines the specifics of the many parameters that might need to be taken into consideration when the shim code is created for each sensor, actuator or conversion function. The author plans to refer to this ixmRPC_PushButton.idl definition when creating the first shim code for the "RPC client request" (and for the "RPC server response"). A similar IDL file will be generated for the LEDs that are usually driven by an eRPC system as an early example. The PushButton IDL file (named "ixmRPC_pushButton_001.idl" shown high above) will be stored in "/ixmRPC/f_pushButton/client/IDL_definitions/" and in "/ixmRPC/f_pushButton/server/IDL_definitions/". Different shim files will be created for the Client and for the Server. The name of the shim code contains the function name and the programming language. In the case of a simple pushbutton connected to an RPi GPIO pin, on a Raspberry Pi 4, the client shim name will be:
PushButton_MicroPython_Shim_ixmRPC_Client.py
and the server shim name will be:
PushButton_MicroPython_RPi_OnBoard_Shim_ixmRPC_Blocking_Server.py

Client Code

The Client code will be defined in two parts, "the initialization" code and the "read the PushButton" code. For the moment, we shall presume that the Client and the Server are on the same RPi core machine.

The client "initialization" code will be:

    #identify the client and server core by ID
    clientCore="abf3"
    serverCore="abf3"

    GPIO22="22"
    intTimeOut=20000

    #Create the pushButton object only if the client and serverCore are the same
    if clientCore==serverCore :
        isCreated,PB22 = Init_PushButton_RPi_OnBoard_MicroPython_Shim_ixmRPC_Blocking_Server( \
        null,clientCore,serverCore,"ixmRPC",GPIO22,15,"Generic",lowTemp00,intTimeOut)
        if not isCreated :
            print("Error the PB22 object was not created.")
        else:
            print("The PB22 object was created.")
        #if end
    #if end
The actual code to initialize the PB22 object must appear somewhere. That "somewhere" is here.


    def Init_PushButton_RPi_OnBoard_MicroPython_Shim_ixmRPC_Blocking_Server( \
    null,clientCore,serverCore,"ixmRPC",GPIO22,15,"Generic",intTimeOut):

        #Create the pushButton object only if the client and serverCore are the same
        if clientCore==serverCore :

            ######################################################
            # 
            #PB22 = etc    #initialize the PB22 object here
            import time
            import RPi.GPIO as GPIO
            GPIO.setmode(GPIO.BCM)
            GPIO.setup(GPIO22,GPIO.IN)
            ######################################################

        #if end
        isCreated = True
        # I don't think GPIO is the same as the object PB22
        # But the following statement might work
        return isCreated,GPIO
    #def end

The client MicroPython ixmRPC "read the pushbutton" code usage should have the usual error-checking mechanisms. That is the reason for the "long code segment" that follows. The code will be:

    #main.py

    GPIO22 = "22"
    intTImeOut=20000

    #The PB22 object must be created before the first RPC "throw"
    #This is true whether or not the client and server are the same machine

    isCreated, PB22 = Init_PushButton_MicroPython_Shim_ixmRPC_Client( \
    null,clientCore,serverCore,"ixmRPC",GPIO22,15,"Generic",lowTemp00,intTimeOut)
    if not isCreated :
        print("ERROR PB22 was not created")
    #if end

    # End of client initialization

    #

    # Begin client "read the pushButton" routine

    intMaxWait = 60000	# allow the user 60 seconds to push the pushbutton
    intTimeOut = 20000	# 20 seconds
    if intMaxWait < intTimeOut :
        print("ERROR - Max timeOut must be greater than Loop timeOut")
    #if end

    intSecsMaxWait = intMaxWait/1000  #convert msec to sec
    # wait until PushButton on GPIO22 is pressed
    print("Press pushButton on ",GPIO22, "within ",intSecsMaxWait, " seconds")

    intCode = 1          #intCode means "Timed Out"

    while intCode==1:
        # The Blocking-Server needs the Client Routine to handle the time-Outs.

        # NOTE that the PB22 object must be created (as above) before the Throw
        #      if the client and the server are the same machine
	intCode,isPushButton01_True = Throw_PushButton_MicroPython_Shim_ixmRPC_Client( \
        PB22,clientCore,serverCore,"ixmRPC",GPIO22,15,"Generic",lowTemp00,intTimeOut)

        if intCode>1: print("Error code during Throw:",intCode)
        if intCode==0 : break
        intMaxWait = intMaxWait - intTimeOut
        if intMaxWait < 0 :
            print("Error: No response within ", intSecsMaxWait)
            break
    #while end
    if isPushButton01_True :
        print("PushButton was pressed.")
    else:
        Print("ixmRPC GPIO22 pushButton Error")
    #if end
    #etc

Blocking-Server Code:

The server code will be defined in two parts, "the initialization" code and the "read the pushButton" code. For the moment, we shall presume that the client and the server are on the same RPi machine.

The following code is for a "Blocking-Server". A "Blocking-Server" is a simple server that can only perform one task at a time. Small computers are often "Blocking-Servers" and are not "smart enough" to "juggle" two tasks at a time. They must complete the task at hand before going on to the next task. Some of them just queue up the waiting tasks. Bigger and better computers use electronic interrupts that permit one task to go to "sleep" when its computer has to wait for an external task to be completed. An example of this is when it is waiting for a human to push a button, or when it is waiting for a disk drive to read some data. While the "smart" computer is "sleeping" it can turn its attention to another task and then return to finish the previous task(s) later.

It is interesting to note that the client routines do not need to contain any actual detailed pushButton code. This is normal because it is the server code that must deal with the "messy details" of actually reading the pushButton.

The Blocking-Server MicroPython "initialization code" will be:
    #This code must appear in the main.py
    #identify the client and server core by ID
    clientCore="abf3"
    serverCore="abf3"

    GPIO22="22"
    intTimeOut=20000

    #Create the pushButton object only if the clientCore and serverCore are different
    if clientCore<>serverCore :
        isCreated,PB22 = Init_PushButton_RPi_OnBoard_MicroPython_Shim_ixmRPC_Blocking_Server( \
        null,clientCore,serverCore,"ixmRPC",GPIO22,15,"Generic",lowTemp00,intTimeOut)
        if not isCreated :
            print("Error PB22 was not created")
        else:
            print("PB22 was created")
        #if end
    #if end
    print("PB22 object is available")
    #etc
The Blocking-Server MicroPython "read the pushbutton" shim code will be:
        #If the clientCore and the serverCore are the same, this code should be in the 
        # Throw shim routine. . . and it should be invoked within the Throw routine.
        #In fact, this statement will be the only major statement in the throw 
	#routine definition.

        #The PB22 object will be an incoming Parameter to the Throw routine as will
        #GPIO22 = "22"
        #intTimeOut=20000
        #clientCore="abf3"
        #serverCore="abf3"

 	Catch_PushButton_RPi_OnBoard_MicroPython_Shim_ixmRPC_Blocking_Server( \
        PB22,clientCore,serverCore,"ixmRPC",GPIO22,15,"Generic",lowTemp00,intTimeOut)
However, it IS necessary for the actual server shim code to be defined somewhere. That "somewhere" is here:
        #If the clientCore and the serverCore are the same, this code should be called by the 
        # Throw shim routine. That is, it should be invoked within the client Throw routine.
        In fact, a call of this routine will be the only statement in the client Throw routine definition.


 	def Catch_PushButton_RPi_OnBoard_MicroPython_Shim_ixmRPC_Blocking_Server( \
        PB22,clientCore,serverCore,rpc,GPIO22,physPin,"Generic",lowTemp00,intTimeOut):

            ###############################################################

            # BP22 should be GPIO in the statement above
            #
            #The actual code to read the pushButton on GPIO22 is needed here
            # This code will not work because GPIO is not PB22

            # default return values if timed-Out
            intCode = 1    		# 1 means "timed out"
            isPushButton01_True = False	# default is "PB was not pressed"
            intSleepTime=intTimeOut/1000
            try:
                while True
                    if GPIO.input(GPIO22):
                        isPushButton01_True = True
                        intCode = 0    # 0 means success
                    else:
                        # needs some "time-Out code" here
                        Doh = True
                        # sleep for a "few" seconds
                        time.sleep(intSleepTime)
                        break
                    #if end
                #while end
            finally:            # CTRL-C comes here
                GPIO.cleanup()
            #try end
            ###############################################################

            #isPushButton01_True = True     #This return with no code above would
            #                             indicate that the GPIO22 is always pushed.
            return intCode,isPushButton01_True
        #def end

The Actual Transport Mechanism

When the clientCore and the serverCore are the same machine, it is not necessary to have a transport mechanism. When the two cores are different machines, it IS necessary to have a communications channel ie a transport such as a serial USB line (or cable) linking the two machines. [ The author has moved the whole ixmRPC part of this article into a new different article (to Article 193 from Article 191) before addressing the Transport mechanism. The actual detailed code dealing with the pushButton will also be deferred until then. This move has now been done and this note will soon disappear. ]

The ixTransport

The ixTransport mechanism is a greatly simplified version of the eRPC transport mechanism. The eRPC is designed to be used by many companies and many individuals to link anyone to anyone across the Internet. Often, the ixmRPC will be used within a single company or household. Such a small purview greatly simplifies the need for a Transport. The transport layer within eRPC needs to route signals between two machines going through many layers such as shown below:

	Client: pin OF device OF machine OF core
	          Routing Between
	Server: pin OF device OF machine OF core
	
In the ixmRPC, only a single identifier (the unique "transportID") is sufficent to link the Client and the Server in ixmRPC. It is sufficient for each signal instance to merely refer to a single identifier such as the following:"

	Client: transportID
	  Routing Between
	Server: transportID
	

Signal Reading Request (SRR)

In fact, the Client and the Server transportIDs could be included as part of the data item when the request (for a datum reading) is Thrown, but they are not because they are already defined in the IDL. Such a Signal Reading Request (SRR) could simply have the following components:

	UniqueDatumRequestID 		(the unique "Throw ID" defines the Throw and the Catch and data)
	TimeStamp			(the Unix timestamp when this DatumRequest was created)
	TransportID			(the TransportID, one ID per virtual Transport Cable; 
						bundle of "virtual" wires)
	
This is sufficient information to request an "acquisition" (or "control") "Throw" in ixmRPC. Often the complete routing information in ixmRPC will be limited to one or two (or a small number) of signal pins between only two cores. Merely the Client and Server TransportIDs and other information in the IDL are sufficient to correctly route the signal information. The SRR simply defines a single datum request by its TransportID and TimeStamp. The same SRR can be used for all Signal Requests taken at one TimeStamp. Or a different SRR can be used for each Signal Request. The purpose of the SRR is to define which TransportID unites the data in the SRR records.

Definition of Each Transport Cable Signal

All of the ClientTransportID and ServerTransportID definitions should be stored in the /ixmRPC/transports/ folder. Each pair represents a virtual "wire" and is defined by a file in the /ixmRPC/transports/ folder. Each virtual "wire" can be defined by a TransportLink which is identified by a TransportID, as shown below:
	TransportID			(the unique "Transport ID")
	ClientTransportID		(the Client Transport I/F ID)
	C(GPIO22)			(the Client pin name)
	signalName			(containing the name of the signal being Transported by this Transport Link
	S(GPIO11)			(the Server pin name)
	ServerTransportID		(the Server Transport I/F ID)
	
Note that more than 1 file in the folder will usually appear with the same unique "Transport ID". This occurs when many virtual "wires" are bundled together in the same Transport Bundle. But note that this Transport Bundle (of virtual wires) need only be defined once. It may never change unless a virtual wire or signalName changes. The ixmRPC mechanism will not use the data in the Transport Links, but will only use the TransportID. At a minimum, each unique TransportID can be the only datum in each record. The TransportID is not to be confused with the ClientTransportID nor the ServerTransportID (both which are not needed in ixmRPC).

In "quick and dirty" ixmRPC code, only one Transport Cable (with its unique TransportID) is needed for a whole collection of data. Again, the TransportID is simply an ID number for a virtual bundle of virtual wires. In the ixmRPC system, only one SRR record need be defined for each "signal" instance to be sensed or controlled. This is explained next.

	Transport Cable Name		Unique Cable Name
	TransportID			the unique "Transport ID"
	TID_TimeStamp			the Unix Time timestamp when the Transport ID was defined.
	
The above record is all that is needed to define a virtual Cable (a virtual bundle of wires). Unfortunately, it does not document the bundle at all. The code developed by the user defines everything. A second, different virtual bundle of wires must be assigned a different TransportID. This is one major way that the ixmRPC system is much simpler than the eRPC system.

It is not necessary to define the Transport Cables in any detail, except as a good means of documenting the Transport. Only the TransportID (a single number) and its name need to be defined. However it is recommended that a description of each Transport Cable be made for future coding references. Note that these TransportIDs are an important part of the definition of each UniqueDatumRequestID. The "cost" in number of bytes of each "Throw" request can be limited to:

	UniqueDatumRequestID 		 30 characters
	Each "Throw" Request		 22 characters
	Client Signal/Pin Name		  6 characters (eg GPIO22)
	Signal Data Response		  6 characters (Variable length, minimum 6 characters)
	Each signal Data "Overhead"	 25 characters
	Each Acknowledgement		 24 characters
		TOTAL			121 characters
	
This should be an average "reading cost" or "signal data storage cost" of 121 characters (or 115 characters plus the length of each Signal Datum string.) This is comparable to the cost of "simple logging" of such signals which is of the order of 100 characters per Signal Datum. Another consideration is that each "Signal Datum" travels along a real wire at the speed of light, limited only by the processing speed of the cores involved. Whereas an RPC system transfers Signal Data which moves at a speed that is dependant upon the speed (in MBits/second) of the primary Transport mechanism used by the RPC system. The ixmRPC system often uses a serial USB speed of 115,200 bits/second, which is quite fast (but very slow compared to the speed of light).

Each set of ixmRPC data Acquisition packets need only be comprised of:

	UniqueDatumRequestID 		(the "Throw ID")
	TimeStamp			(the Unix timestamp when the SRR was created)
	"TA"				(signifying an Acquisition request being Thrown)
	
Note that the TimeStamp of the UniqueDatumRequestID need not be the same as the TimeStamps of the SRR datumRequests that refer to one UniqueDatumRequestID. In fact, a "pair" (or group) of SRR UniqueDatumRequests (a Throw and a Catch) with different TimeStamps will always relate (link) to the same SRR UniqueDatumRequestID. Then the Response to an Acquisition Request might be:

	UniqueDatumRequestID 		(the same "Throw ID")
	TimeStamp			(the Unix timestamp which may be different)
	"TAR"				(signifying a Response to a Thrown Acquisition request)
	Signal Data			(will be a single bool or integer or alphanumeric datum)
	CompletionCode			(indication Success or Failure Code)
	
possibly followed by an acknowledgement data packet (which might optionally not even be sent)
	UniqueDatumRequestID 		(the same "Throw ID")
	TimeStamp			(the Unix timestamp which may be different)
	"TARK"				(signifying an acKnowledgement Response to a 
						Thrown Acquisition request Response)
	
A Control request signal packet might be:

	UniqueDatumRequestID 		(the "Throw ID")
	TimeStamp			(the Unix timestamp of the Control request)
	"TC"				(signifying Throwing a Control request)
	Signal Data			(will be a single bool or integer or alphanumeric datum)
	
possibly followed by an acknowledgement data packet (which might optionally not even be sent)
	UniqueDatumRequestID 		(the same "Throw ID")
	TimeStamp			(the Unix timestamp which may be different)
	"TCK"				(signifying an acKnowledgement Response to a 
						Thrown Control request )
	
... And the optional response to a Control Request might be:

	UniqueDatumRequestID	 	(the same "Throw ID")
	TimeStamp			(the Unix timestamp which may be different)
	"TCC"				(signifying a confirmation
					  of Completion of Thrown Control request)
	CompletionCode			(indication Success or Failure Code)
	
possibly followed by an acknowledgement data packet (which might optionally be sent):

	UniqueDatumRequestID	 	(the same "Throw ID")
	TimeStamp			(the Unix timestamp which may be different)
	"TCCK"				(signifying  an acKnowleddement of
					  Completion of a Thrown Control request)
	
All of these packets are only necessary if the user needs absolute confirmation of every single datum that is exchanged. In today's world, signal datums are seldom lost. Furthermore when a single signal datum is lost, it rarely creates a life-threatening or costly emergency. The ixmRPC should never be used in such dangerous cases, eRPC should be used instead.

Each data packet should be less than 50 bytes total. The ixmRPC system will only use 8-bit ASCII characters and the English language (no EDCDIC or UNICODE fonts). The overhead of the ixmRPC is very "lite", making it usable in tiny devices like the Wio Terminal often requiring only local Transport capability.

Perhaps it will be necessary to transport whole IDL or SRR files from the Client to the Server, but that requirement has not been planned for. If deemed necessary, the Unique Data Requests will need to be expanded to include the transport of small (under 5000 characters long) .idl or .srr files. This will not be a major problem.

Note that the length of the Signal Data might, in the future, be expanded to permit the transfer of larger objects such as files with the following extensions: .uf2, .py, .jpg, .wav and .zip . In fact, a small number of "OS-like" requests might also be included. To transfer the contents of uSD cards using pathed file names will also be useful, although nothing in this paragraph will be included in the original (first) release of ixmRPC.

Using a VT100 (or minicom or PuTTY) with ixmRPC

Once the UniqueDatumRequest "Line" has been defined, it is possible to Manually request individual Data Acquistion Signal Data (or individual send Data Control Signals). This is normally done using a VT100 emulator such as minicom (or Putty). To request a signal datum (a single reading) the user need only type:

	"1,2,TA" and hit Enter
	
Of course, this must be preceded by the definition of the cores and the ".csr". However the "signal definition" can be defined by:

	Field				Description						Eg. Value
	----------------------		---------------------------------------------------	------
	UniqueDatumRequestID 		(the "Throw ID")					0
	UDR_TimeStamp			(the Unix timestamp)					1 (or blank)
	Client Signal/Pin Name/physPin	(eg pbTrue,GPIO22 or 15)				15
	TransportID			(the Client Transport Signal I/F ID similar to a wire)				3
	CRSFolderID			(containing the list of CRS files defining the pins)	4
The signal reading could be setup very simply by typing "0,1,15,3,4,5" followed by Enter. Or it could even be as simple as "0,0,15,0,1". If the timestamp field is empty, the ixmRPC system will insert the Unix Timestamp automatically into the Throw command. Defining the Signal Datum Request followed by the actual "Throw" request would require the user to only type into the serial USB:

"0,,15,0,1" Enter "0,,TA" Enter.
The status of the pushButton at physical pin 15 will then be displayed on the "Client" screen as "True" or "False" meaning the PushButton is "closed" or "Open" for each reading.

To turn on/off a LED at physical pin 6, once the Transport etc has been defined, simply type in:
"1,,6,0,1" Enter "1,,TC,True" Enter 
"2,,6,0,1" Enter "2,,TC,False" Enter
Of course, the ixmRPC will reply by displaying appropriate responses on the screen. The ixmRPC system is forgiving in that acknowledgements are not necessary.

Recommended ID ranges

It is recommended the the various IDs be assigned numbers as follows:
pin numbers		  	    00 to    99
signal numbers eg puButton00	    00 to    99
transportIDs		 	   200 to   499
IDL			 	   500 to   999
CRS folder ID			  3000 to  9999
SRR				 40000 to 99999
UniqueDatumRequestID		100000 and up   (all unique)
timeStamps			actual Unix Times (in seconds or milliseconds)
Using low recommended numbers, the previous Throw requests would be as in the example following the naming of the fields in the first "datum request".

"UniqueDatumRequestID, Unix time-stamp, physical pin number, transportID, CRSfolderID
"100000,,15,203,3008" Enter "100000,,TA" #request pb status Enter.
and
"100001,,6,203,3009" Enter "100001,,TC,True"  #led on. Enter 
"100002,,6,203,3009" Enter "100002,,TC,False" #led off immediately. Enter
In the above, note that the UniqueDatumRequestID precedes the unix timestamp. This is done so that when the records in the Log File are sorted, all the records pertaining to the same UniqueDatumRequesID will be together, even though each record was probably created at a different time. The other records having the same UniqueDatumRequestID would be the datum value (ie the Response) and/or the acknowledgement .

It is not absolutely necessary for IDs to be in the above ranges but being in the correct range permits the user to identify which value is in which field..

This completes the full definition of the ixmRPC Transport process.

3 UDR (Unique Data Requests)

In the above examples, 3 UDRs are defined: 100001,100002 and 100003. One TransportID, 203, is defined because only one virtual cable is used. Two CRS, 3008 and 3009, specify two devices: a PushButton and an LED. Three Throws are specified, one TA and two TC Throws. It is interesting to see that more folders are required than the number of Unique Data Requests. Of course, once the folders are defined, they can be used many, many times.

IDL Connections: the Absolute Need for a CRS Table


Consider that a Client program is written to read a pushButton on GPIO22 on machine A using ixmRPC. The Server program on a different machine (say machine B) would be coded to actually be interfaced to GPIO11 on its Server machine (core). A good RPC system should be able to convert the GPIO22 to GPIO11 without changing any (or very little) client code. To do this, a user-defined "routing" (or equivalence) table is needed. This table (with an extension of .crs) defines a Client signal Routed to a Server signal. When this is done using hardware, a wire is connected from the Client GPIO22 to the Server GPIO11. Within the ixmRPC system, the C_IDL_R_S_IDL.crs table can be used. The naming of the .crs file applies to control actions that go from the client to the server. Some readers might say that name is not valid for data being sent from the server to the client. (It is true, the name doesn't apply to both directions, we must learn to "just live with it".) To accomplish the equivalent of the GPIO22 to GPIO11 substitution, within the same machine, the C_IDL_R_S_IDL.crs file would be:

	#Note: Route GPIO22 to GPIO11 on the same server
	#
	#attribute	#client	    <->	#server
	------------	-----------	-----------
	core		"abf3"		"abf3"
	sensorMfr       Raspberry	Raspberry
	Code:		MicroPython	MicroPython
	AorC:		A		A
	SensorType:	PushButton	PushButton
	SignalName	digIn		digIn
	sensorModel	generic         generic
	device		onBoard		onBoard
	GPIOpin		GPIO22		GPIO11
	PhysPin		15		23
	InitialState:   False		False
	Units		Bool		Bool
	ConvertFunc	unity()         1

	#/C_IDL_R_S_IDL_a.crs
	
As can be seen the GPIOpin or the PhysPin can either be defined in core code as a parameter or in the CRS. If defined in both places, the core code parameter will take precedence over the CRS file. The ixmRPC data log, in the "/ixmRPC/signalData/UniqueDatumRequestIDs/" folder, will certainly show which pins were actually used.

In the above case, consider that the ixmRPC will imitate a "wire" being run from client core GPIO22 to server core GPIO11. The real electronic signal (or data) from the server core will be read from the real server pin GPIO11 and will be "sent" (via the ixmRPC system Transport) to the software on the client core as if it were being read from client core pin GPIO22. No signal will actually be noticed on the pin GPIO22 of the client core machine. This will be done soley by the client core's ixmRPC software in the absence of the existance of a real "wire". Instead, the information sent via the ixmRPC Transport will accomplish what a real "wire" would have done. The software in the client core will "think" that the data on its pin GPIO22 was the same as the data that was on the server core pin GPIO11. This is the beauty of the concept of an RPC. If this concept remains unclear, please re-read this article or ask a knowledgable RPC person for a clearer explanation.

This concept permits the "magical" ixmRPC system to transfer signals from one computer to another without using actual real wires. RPC systems have "super powers". An eRPC system can make i2C transports work like "magic" wires and can turn router Transports into the equivalent of real wires. What an amazing concept! Sampling at its best.

CRS Tables

Within an RPC system, the CRS table is what defines the equivalent of a "real wire" to the Client and Server software. Hopefully the following few examples will illustrate how this is done.

A .crs Table to Route GPIO22 to an Adafruit 4132


To route the GPIO22 signal to an Adafruit model 4132 board (from pin GPIO22 to 4132 pin B01), use the .crs table shown below:
#Note Route RPi GPIO22 to Adafruit 4132 pin B01 on same server
#
#attribute	#client	    <->	#server
----------	-----------	-----------
core		"abf3"		"abf3"
sensorMfr       Raspberry	Adafruit
Code:		MicroPython	MicroPython
AorC:		A		A
SensorType:	PushButton	PushButton
SignalName	digIn		digIn
sensorModel	generic         4132
device		onBoard		onBoard
GPIOpin		GPIO22		B01
PhysPin		15		9
InitialState:   False		False
Units		Bool		Bool
ConvertFunc	unity()         1

#/C_IDL_R_S_IDL_b.crs

A .crs Table to Route GPIO22 to a digLight CD sensor on PiR2null


The routing table shown below will route GPIO pin GPIO22 to a digLight sensor on PiR2null connected to the same core (machine). This is shown in the C_IDL_R_S_IDL_c.crs table shown below. The digLight sensor is on GPIO17 on the PiR2Null device.
	#Note Route RPi GPIO22 to PiR2Null GPIO17 on same server
	# Source 01: Article 153: PiR2Null digLight on GPIO17(phys pin 11)
	#
	#attribute	#client	    <->	#server
	------------	-----------	--------------
	core		"abf3"		"abf3"
	sensorMfr       Raspberry	ICH180RR
	Code:		MicroPython	MicroPython
	AorC:		A		A
	SensorType:	PushButton	CDambientLight
	SignalName	digIn		digLight
	sensorModel	generic         PiR2Null
	device		onBoard		onBoard
	GPIOpin		GPIO22		GPIO17
	PhysPin		15		11
	InitialState:   False		False
	Units		Bool		Bool
	ConvertFunc	unity()         1

	#/C_IDL_R_S_IDL_c.crs
	
A collection of numerous .crs tables define all the routings for any single environment. These files must be placed in the folder named "/ixmRPC/crs_routings/". The ixmRPC should verify that the same client pin (ie signal) is not routed to more than one server pin and vice-versa. If all three .crs files (above) were all located in the "/ixmRPC/crs_routings/" folder, the ixmRPC system would reject them as erroneous. The ixmRPC system should also verify that the InitialState of the client and server signals are identical in any single .crs file. If they are not, a WARNING message should result.

Each of the above examples of CRS tables does the equivalent of connecting a real "wire" from the Client core (machine) to the Server core (machine). This is done in the absence of a real "wire".

The whole complexity of the ixmRPC lies in the combination of the CRS table and the parameters passed to the Function called for each signal line. The power of the ixmRPC system is that the parameters and CRS tables can house a host of information describing each virtual wire for each signal line (ie each pin). In ixmRPC, each signal Transport can be very simple or quite complex. It is up to the user (the programmer) and the exact situation at hand.

Various ConvertFunc Routines Are Needed

Hopefully, the .crs files (explained above) will greatly simplify the transfer of code from one application to another, whether it applies to transfers within the same core (machine) or from one core to another via a transport such as a serial USB connection.

Note the potential requirement for a "ConvertFunc" that will be used to convert the units in the server "signal" to units in the client "signal". Examples of different ConvertFunc functions are:

	Unity() - This function makes no change to a numerical signal.
	          This function makes no change to a logical signal.
	          This function makes no change to an alphanumeric signal.
	Invert()- This function converts True to False and vice-versa
	          This function converts a 1 to a 0 and vice-versa
	CfromF()- This function converts Fahrenheit to Centigrade (or Celsius)
	          A sensor on the server might read in Fahrenheit.
	          The conversion CfromF() would be as follows:
	             tempC = CfromF(tempF) where the formula CfromF() is
	             tempC = (tempF - 32 )* 100 / 180.
	          The number read by the server in Fahrenheit must be converted 
	             to Centigrade by RPC software using the CfromF() function before
                     it is returned as a result in Centigrade.
	
It is a valid situation if the .crs folder is empty. Perhaps this is simply to test that the shim routines all work correctly before making any pin changes. Perhaps this is a case of using the transport to use all the device-specific software "as is" on one core. Then to permit sense and control from another identical core using identical GPIO pins. In the latter case, a transport such as a serial USB line is used to connect the 2 cores.

It is the responsibility of the person (the programmer) creating the .crs file to ensure that its contents are correct (including the correct conversion function). The eRPC system will do some of this work automatically when it uses the final code that the user made from the shim code. But the ixmRPC system generates very little code automatically other than invoking the ConvertFunc() when needed.

In this way, the use of the .crs files can greatly simplify the software coding needed to accomplish simple changes of GPIO pins to accomodate different hardware situations. But this is only possible if the ixmRPC code modifications have already been made to the original programs. It is possible to use generic GPIO pins such as "GPIOaa" in the client code, but I believe that a set of working GPIO pins facilitates the coding and testing of the former client code. Generic GPIO pins can often cloud the situation. Furthermore, when converting "old" code to ixmRPC code, it is easier to fact-check the new code if the exact same GPIO pin numbers or names are retained.

It is interesting to note that a conversion from MicroPython to CircuitPython (or vice-versa) can easily be done using .crs files that define two different machines (one with MicroPython and the other with CircuitPython). It is only the one set of shim code that will need to be altered instead of making changes to all of the "deprecated" code. Even changes to the pin names can be automated in this fashion, if necessary. Of course, the "deprecated" code will still need to be converted to its ixmRPC equivalent, manually by the user (ie the programmer). This should be a simpler task than converting the old code directly to CircuitPython code. Furthermore, once the old code has been changed to a type of RPC code, future pin/device adjustments will be much simpler to accomplish.

In the past, the author has found it "bothersome" to pass the actual machine objects as calling parameters to subroutines or functions that need to deal with the pins. The use of the ixmRPC does not change this situation, the objects (eg PB22 in the above examples) still need to be passed as calling parameters.

Folders Used By ixmRPC

	/ixmRPC/f_deCUTime_WioT/client/IDL_definitions/
	/ixmRPC/f_deCUTime_WioT/server/IDL_definitions/
	/ixmRPC/f_deCUTime_WioT/client/shims/
	/ixmRPC/f_deCUTime_WioT/CRS_routings/
	/ixmRPC/f_deCUTime_WioT/server/shims/
	/ixmRPC/f_uTimeoTime_WioT/client/IDL_definitions/
	/ixmRPC/f_uTimeoTime_WioT/server/IDL_definitions/
	/ixmRPC/f_uTimeoTime_WioT/client/shims/
	/ixmRPC/f_uTimeoTime_WioT/CRS_routings/
	/ixmRPC/f_uTimeoTime_WioT/server/shims/
	/ixmRPC/f_ix_UUID_WioT/client/IDL_definitions/
	/ixmRPC/f_ix_UUID_WioT/server/IDL_definitions/
	/ixmRPC/f_ix_UUID_WioT/client/shims/
	/ixmRPC/f_ix_UUID_WioT/CRS_routings/
	/ixmRPC/f_ix_UUID_WioT/server/shims/
	/ixmRPC/f_pushButton/client/IDL_definitions/
	/ixmRPC/f_pushButton/client/shims/
	/ixmRPC/f_pushButton/CRS_routings/
	/ixmRPC/f_pushButton/server/shims/
	/ixmRPC/f_pushButton/server/IDL_definitions/
	/ixmRPC/f_led/client/IDL_definitions/
	/ixmRPC/f_led/client/shims/
	/ixmRPC/f_led/CRS_routings/
	/ixmRPC/f_led/server/shims/
	/ixmRPC/f_led/server/IDL_definitions/
	/ixmRPC/transports/TransportCables/
	/ixmRPC/transports/SignalLines/
	/ixmRPC/signalData/UniqueDatumRequests/
	
There is no need for a folder for Signal Reading Requests (SRR). The SRR are sufficiently defined by each UniqueDatumRequest. There is an ixmRPC folder (beginning with "f_" for each ixmRPC function. Each ix function has the following 5 folders:

	client/IDL_definitions/
	client/shims/
	CRS_routings/
	server/shims/
	server/IDL_definitions/
	
Note that the above 5 folders are in 3 folders directly under the function folder. Often the shim folders are empty. The CRS_routing tables are perhaps the most important because they specify the manufacturer device names, part numbers models and pin numbers. Unlike in eRPC, none of the data in these folders is used directly by the ixmRPC system. Very few of the ixmRPC software coding make direct use of the information in these folders. All of the information in the folders is gathered for the coder (programmer) to reference. The ONLY folders that truly need information are the ixmRPC/transports/, ixmRPC/CRS_routings/ and ixmRPC/signalData/UniqueDatumRequests/. The CRS_routingID numbers must be listed in the ixmRPC/transports/ folder under the appplicable folder. (This has not been explained yet.) No explicit definition of each CRS_routingID is needed. Note that the folder "/ixmRPC/signalData" can be emptied or backed up without losing the integrity of the ixmRPC system. It is recommended that all the "CRS_routings" files be retained in case the same situation should need to be repeated in the future.

Of course, the user's AandC programs should be backed up on a regular basis. When such a backup is done, it is recommended that all of the "/ixmRPC/f_*/ folders (and the /ixmRPC/transports" folders) should also be backed up as well (and stored along with the AandC programs).

As more and more RPC functions are defined, more functions must be given different names. These unique function names should specify the different devices, manufacturers and programming languages that distinguish them.

ixmRPC Waveforms

The waveforms (eg a sine wave at a certain frequency and amplitude) can be passed along a virtual wire using the ixmRPC system. The waveform must be sampled often enough for the "shape" of the sine wave to be evident. When digital computers are used to "emulate" waveforms, a sampling technique is used very often. A list of samples of the signal is the result. The list of signal samples that accumulates in the "/ixmRPC/signalData/UniqueDatumRequestIDs/" folder is a similar list of samples. In Article 164 (Source 07) and Article 168 (Source 06) the author has written about the use of "digital oscilloscopes" and "digital signal generators" using digital sampling software. Article 164 is a very long article that describes actual sampling hardware, methods and examples. The Raspberry Pi Pico computer is equipped to create a set of electronic samples (a "sampled" waveform) and to do the sampling of an analogue waveform. The Raspberry Pi Pico uses the Raspberry RP2040 IC chip to incorporate a small number of very simple high speed state-machines that can be used to create high frequency digital waveforms or to sample the equivalent analog waveforms. These state-machines generate PIO, PWM, SPI, I2C etc. The "Maker Pi Pico" (described in Article 164 in Source 07) by Cytron adds tiny peripheral devices to the Raspberry Pi Pico to convert it into a great device for digital waveform analysis and generation.

ixmRPC Lexicon (c2023)

word/phrase	meaning
-----------	-------------------------------------------------------------------------

AandC		Acquisition and Control (Sense and Control) of a process
acquire		gather or read information
actuator	a device that causes (effects) a control action
AorC		Acquire or Control
backup		making a copy of programs or data so that it will not be lost
Blocking-Server	A server that doesn't use interrupts
BlueTooth	a wireless communication system used by computers
board		a physical circuit containing electronic devices
Bool		Boolean
cable		a group of wires bundled together going between a client and a server
Client		the originator of action requests
code		software programs or firmware (collection of statements)
complex		a data type composed of real and imaginary numerical fields
connector	part of a physical interface connecting two devices
control		to cause some sort of action eg turn ON a led
controller	a device that causes an action or a value to be sent/received
ConvertFunc	a function that converts one or more datum values from a server 
                  into a different datum value (eg from Fahrenheit to Celsius)
core		single computer or device containing at least one processor
CRS		Client Routing to Server
data packet	a (usually small) set of data items packaged together before being sent
datum		value of data (eg a number, character, word or null) 
		   usually sensed or created at a specific Unix Time
deprecated	something (such as a software concept) that is no longer being used
digLight	a signal that measures the amount of brightness (light or dark)
Enter		the "Enter" key on a computer keyboard
event		the time when an action happens or is seen to have happened
folder		part of a path to a location where files are stored
github		a popular library of software functions and routines
GP		a logical name for a pin on a Raspberry Pi Pico computer
GPIO		a logical name for a pin on a Raspberry Pi computer
Grove		a popular connector used in sensors/actuators sold by Seeed Studio
I2C		a serial asynchronous transport originally designed for automobile wiring
IDL		Information Data or Library file
IoT		Internet of Things
IXcomplex	using Python complex variable types for a list of time-stamped samples
ixTransport	Transport used in ixmRPC
ixmRPC		a lite version of RPC (lite eRPC) only for MicroPython users
linkage		a routine or transport (either virtual or physical)
lite		a small version of something
log		a time-stamped collection (list) of readings or control actions
Mfr		manufacturer
minicom		software permitting a person to use a serial USB line
parameters	values passed to (or returned by) a function
pin		a metal place in a device where a signal originates or is received
port		verb: to transport information
pushButton	A switch that turns "on" (completes) a (usually single) signal when depressed
PuTTY		a modern version of minicom
Python		a very popular programming language c2020
Raspberry	A popular inexpensive computer developed around 2010
return		the final action of a function; often with value(s) being returned
routing		a transport, path or wire
RPC		Remote Procedure Call
SD card		a tiny electronic card used to store programs and/or data 
		   (usually using a uSD memory card designed for digital cameras)
sensor		a device that reads one or more data value(s)
SensorModel	manufacturer model number
Server		the object/device that carries out a Client's action requests
serial USB	a popular physical cable that connects computing devices
shim		special code segment used in an RPC system
signal		a single datum (eg True or 3.3 volts or 15 degrees C)
SRR		Signal Reading/control Request
S&C		Sense and Control
signalLine	a virtual wire (in a virtual Transport Cable)
table		a seldom changed data file referenced by an RPC system
Throw		the sending of a single action (pertaining to a value) at a specific time.
		This should not be confused with a switch that might have 2 poles and 3 throws.
time-stamp	record of the time when an event occurred (often using Unix Time)
transport	a means of conveying information from one device to another
transport Cable	a collection of signalLines that together form a transport  (identified 
		   by a transportID) going between a client and a server
Unity()		a function that returns the single value presented to it
Unix Time	number of seconds since midnight 0:00 Jan 1 1970
VT100		an popular ancient serial asynchronous 
		   screen & keyboard in use 30 years ago
Wio Terminal	a tiny inexpensive computer containing many peripherals
wire		a single physical copper wire going from one pin of one device to 
		   another pin of another device.  A group of wires form a physical cable.

SD card issue resolved as of 2021LDec17

Source 04 provides a solution for a known SD card library bug that, until Dec 17,2021, was unresolved. Source 04 also provides an FTP routine that can be used with the Wio Terminal. The author (RENZO) had created a SimpleFTPServer library prior to this.

At Source 04, RENZO says:

About Seeed Studio

Seeed is the IoT hardware enabler providing services over 10 years that empower makers to realize their projects and products. Seeed offers a wide array of hardware platforms and sensor modules ready to be integrated with existing IoT platforms and one-stop PCB manufacturing and Prototype PCB Assembly. Seeed Studio provides a wide selection of electronic parts including Arduino, Raspberry Pi and many different development board platforms. Especially the Grove System helps engineers and makers to avoid jumper wires problems. Seeed Studio has developed more than 280 Grove modules covering a wide range of applications that can fulfill a variety of needs.

and

Wio Terminal

RENZO recommends that you also read the introductory article on this device Wio Terminal: pinout, specs and Arduino IDE configurations . That Web Site also includes many references to other "working" Wio Terminal software.

Wio Terminal PinOuts

(To enlarge .....Click it)
thumb: Wio-Terminal-pinout-mischianti-high-resolution.png

Wio Terminal Best PinOuts (from mischianti.org)

Other Thoughts

exploreAndAdopt() function

Source 05, Article 179 describes how the author plans to monitor a serial USB line to see what "traffic" and types of Transports exist on a serial USB line. Refer to Source 05 to see that client and server IDs are already included, as are data packets, escaping special characters etc. Furthermore the concepts described are designed to be quite forgiving.

email as a Transport

An interesting new (or novel) Transport for ixmRPC might be a "very slow Throw" that is an email being sent to a Server to Throw an action such as the delivery of a datum (or a .txt file or a .log file or a .jpg or a .py or a .zip file) to a Server or to a Web Site (such as to www.MehInCharge.com at Source 10). Automatic delivery of logs from MehInCharge currently is a sore need for such a delivery system. All that is needed is to create a Python mechanism for various cores to send and accept emails. I already know how various cores can use Python to send emails. Automated receiving emails is still problematic for me. This could become an interesting way to install new versions of personal (home brew) software via an RPC such as ixmRPC.

A Wio Terminal as a tiny HDMI Raspberry Pi console

It is also interesting that the tiny display on a Wio Terminal (costing US$ 35.00) can easily become a miniature HDMI monitor for a Raspberry Pi computer. Imagine using ixmRPC to update the tiny HDMI screen on (by sending a .jpg to) a little Raspberry Pi board that is functioning as an RPC Server.

RPC With The Pix Explorer

The Pix Explorer, described in Source 05 is an interesting side-bar to the RPC concept. The Pix Explorer is designed to explore "who" or "what" exists on a serial USB cable. Extending the ixmRPC concept a little will permit a number of new client cores to be "discovered" on a virtual Transport "wire" such as a serial USB. A "Home Automation System" might be very easily expanded with little reprogramming. This expanded ixmRPC system is beginning to resemble an I2C Transport. It will be important to ensure that interrupts will, one day, be handled by ixmRPC. It will be very difficult to keep the size of the ixmRPC code blocks small enough to fit into small cores like the Wio Terminal. Fortunately, bigger and better cores than the Wio Terminal will surely appear on the market. Perhaps one day, ixmRPC might become a subset of eRPC. Wow!

IXcomplex Pico Samples With/Without Imaginary Time Components

This section (IXcomplex...) should be moved to a separate Article in the near future

Under this heading, the word "real" is the "real" part of a complex number.
Similarly, the word "imaginary" is the "imaginary" part (followed by a "j" in Python) of a complex number.

It occurs to the author that there are other interesting twists to the use of a list of complex numbers to store time-stamped samples. The thoughts are:

readings at definite regular intervals

-The first two elements of an IXcomplex list of voltage samples could form a special "heading" that defines the sample interval and the first Unix timestamp. This is done by making the first two "samples" contain this information, as follows:

( ("",.001j), ("",12789654.034j) . . .
Note that the real sample value is null in each complex sample item of each of the 2 "header" samples. The rest of this list would only contain real samples because the regular sample interval and the first Unix time are already defined. This is the default set of data values for a Raspberry computer that always knows the exact Unix Date/Time. The software has been instructed to record readings at a specified regular time interval. The readings are recorded on a "best efforts" basis. This is because the OS cannot guarantee that OS delays do not occur (or have not occured). Such delays might be due to garbage collection of available memory or interrup routines that "steal" time from the main routines.

Wio Terminal or a Stand-Alone Pico

A different IXcomplex sample list could begin with

( ("",-1j), ("",12789654.034j) . . .
Describing this header in more detail: the complex sample list (following the 2 header items) would consist of complex samples, each complex sample has a real sample value, followed by the exact "imaginary" time relative to an inexact Unix Date/Time in the second header record. Each of these relative time intervals (relative to the inexact Unix Date/Time) is small enough for the Raspberry Pico to store it in a short Pico integer. The large Unix time stamp need only be included in the second complex number of the header. In this case the imaginary timestamp numbers are all relative to the Unix timestamp in header record 2. Often the Pico will "know" the Unix date at some future time after start-up, but the internal Pico clock will contain a value relative to the Unix timestamp in the second header record. The above header is the default header for a Pico that is operating with knowledge of the relative offset between the internal timer and the estimated start-up Unix date/time. The "-1j" (minus 1j) in the first record means "Do not presume that the unix Date/Time are exact GMT times. It is a warning to this effect. This header is very appropriate for the Wio Terminal. or for a Pico with neither access to a Real Time Clock nor to the Internet via WiFi. Perhaps a user has set the Clock with a "best guess".

A Server with very poor Clock or Timer information

The subsequent list of samples does not make use of the long Unix date/time information in the second Header record (but only uses times relative to the stated Unix Date/Time in the 2nd record which cannot be relied upon). A short relative time will be recorderd for each following sample. The Unix Date/Time in the second record can be 0 or any Unix Date/Time. This type of list should not be considered exactly relative to Unix GMT, nor shouls the time zone information be considered to be correct. This header should be used if timing is done using "For Next Loops" to implement time delays, often in the absense of any timer or interrupt facilities. The header records will be as follows:

( ("",0j),("",12789654.034j) ) . . . 
This header indicates that the time between readings will be recorded, not the time relative to the beginning of the list of readings. The readings of samples are supposed to be done at regular intervals, but this cannot be guaranteed due to operating system over-head. For example the OS might be held up due to an operator intervention or a longer-than usual interrupt chain. This format should be used when only relative times between readings is known. This happens in the absence of any real-time clock and in the absense of any timer at all. In these cases, the timestamps are often guesses or from a one or more different sources. One source might be based on the Client core's clock plus or minus transmission delays due to Transport issues. The Unix Date/Time in the second header record might in fact be wrong. (One case of a bad Unix Date/Iime in the second record would be between the start-up time of a Wio Terminal and when it gets a clue about the real Exact date/Time. In the minutes before any communication with the outside world (no WiFi, no BlueTooth, nothing) the best guess for the Date/Time would be the Date/Time when the Flash memory were last flashed, which might be incorrect by days or weeks. This header should be avoided unless it is best guess among many poor options. This header is used when the data is going to be viewed then thrown away. This type of data should not even be logged because its timestamps are questionable.

If a timer is poorly calibrated (perhaps due to over-clocking) this might be the best header. In any case, this header is based on a possible invalid start-up date/time. It also cannot guaranteed that the time-intervals are accurate. This is purely a "best guess" which might be better than nothing. In this case the intervals are relative to the previous reading. Perhaps the recording of a child's height irregularly each month might be a good example of such a reading that be kept with this header. The exact Date/Time are unclear, but the approximate time between readings can be estimated.

Accurate TimeStamped Sample List with no Need for Unix Date/Times

The next header designates successive readings with accurate time-stamps, with no attempt to have a known Unix Date/Time at the outset. An exsmple of this is when a list of readings designate a specific wave-form by samples that are relative to the beginning of the wave-form.
( ("",-2j),("",0j) ) . . . 
Each sample would contain sample timestamps that are relative to the time of the first sample. The "-2j" (minus 2j) in the first sample (header) means that the longer Unix date/times are NOT used and that the timestamps are relative to 0, not relative to a certain Unix date/time. The above header is the default header for a Pico computer that is operating without access to a Real-Time clock. It is applicable to a Wio Terminal with a good interval time but no Real-Time Clock. Even a Raspberry Pi that is taking measurement that are relative to the time of the first measurement but have no relationship to the Unix Date/Time. Each timestamp will be a small enough number to be stored in a short integer on a Pico using Thonny or any computer.

Recommended Header

The recommended Header is defined by "-3j" in the first header record. The exact Unix Date/Time (for GMT) is specified in the second header record. If fact, the exact Unix Date/Time (for GMT) is specified in the imaginary part of each complex sample. This is the recommended format for recording and logging sample data.

Because the sample intervals are not specified in the first header record, the second sample (ie the second header sample) is very significant. If this second header is anything except "0j", it makes this the header of a normal IXcomplex list with the long Unix timestamps. This is the normal timestamp that is recorded when a Raspberry Pi or any computer has access to a valid Unix clock or Real Time Clock. The longer Unix dates will in fact be used for every sample. Every effort should be made to ensure that this is the Unix GMT time. This will ensure that 2 devices in different time zones will not have a time-zone issue. If no null records precede the list of complex entries, it is this header that could be presumed. It is the "default" header for the Raspberry Pi. This header is usually not the default header for the Pico. This header is as follows:

( ("",-3j),("",12789654.034j) ) . . . 

Pico issues

A complex sample list (without headers) can easily be created or used by a Raspberry Pi computer. But the Unix timestamp numbers are currently (in 2023) so large that a Raspberry Pico cannot easily generate or store the current (c2023) Unix timestamps in the longest Python integer used on the Pico. This is unfortunate because it greatly constrains the PIO processors on the Pico processors. It is therefore recommended that the IXcomplex format of sample lists with "-1j" in the first header record be used by the Pico. Every effort should be taken to correlate the Pico clock with the exact time as in a Client machine. This should be done each time (or at least once prior to the time) that a list of readings is recorded in IXcomplex format type -1j.

This IXcomplex format of sample lists can easily be transported between Raspberry Pi and RP2040-based system (such as the Pico). Note that it is possible to "encode" the header information (regular time interval & first Unix timestamp) in the name of any list of complex numbers, which is the way that many programmers/engineers/technicians might choose to use the IXcomplex formatted sample lists (without headers). Such lists can be used directly without the need for any IXcomplex preprocessor.

It should be noted that the Pico or Wio Terminal can be aware of a differential Unix timestamp that must be reset each time the Server machine is rebooted.

IXcomplex Sample Lists Without Headers

Any sample list without headers is a simple list of complex numbers with no Null entries, neither as real or imaginary parts. Such a list should have a complex number as each real Datum sample. Each Datum should also have a valid Unix time-stamp as the corresponding imaginary value that represents the time coupled with each real-value sample. This complex number list can be used to recreate any waveform in real-time. The absense of at least one imaginary components indicates that sample times cannot be inferred in the IXcomplex list.

This IXcomplex format (without headers) is inferred if the sample interval and the exact beginning Unix date/time are not both specified. Of course, if the imaginary parts of either of the first two header samples are not specified at all, they do not BOTH exist. If the imaginary portion of the first two samples in a supposed IXcomplex list of samples are both Null (each of the numbers are real ie with no properly formed imaginary component), the whole IXcomplex sample list should have no imaginary components at all. This means that normal (non-complex lists that don't have any imaginary parts at all) are valid IXcomplex lists. Any real-number list that begins with two Null real samples would be a valid header of an IXcomplex list, the header information is just Null ie undefined. To extend this just a little further, any list of real number samples that doesn't have two Null entries as a header is a valid IXcomplex list that is devoid of timestamps. This describes a normal Python list of sample values that many users currently recognize and use. Any 2 Null headers that might exist will be ignored by the IXcomplex processor.

Consider, next, an IXcomplex list with a header whose first imaginary portion is non-zero, but the second number in the list has a null valued imaginary number. This is a valid IXcomplex header. This second number with a null as the imaginary portion means that it is not a valid Unix timestamp. A null Unix timestamp differs from a zero-valued Unix timestamp (which means 0 seconds which also means 00:00 on Jan 1 1970). This null Unix timestamp alerts the IXcomplex preprocessor that Unix timestamps are not being used. It also means that non-Unix-stamped values of time are being used. This also means that all subsequent sample values have times that are measured relative to 0. These time-stamps might not even be sorted sequentially. In fact more than one sample can have the same time-stamp.

Often, the time-stamps will be sorted according to the values of their imaginary parts. Furthermore, their sample intervals may be at "almost" perfect regular time intervals. If the IXcomplex preprocessor is satisfied that the sample times are "regular enough", then the set of samples can be considered to be at regular intervals. Such a list of sequential regularly-enough-timed samples can be presumed to be valid samples for a FFT (Fast Fourier Transform) analysis to be performed. All this implies that a list of complex numbers can sometimes be adequate input to a FFT, whether or not it has header information. Even Unix-timestamped samples can be deemed to be at regular-enough intervals for FFT analysis. However if more than one of the time-stamps are identical, a FFT should not be performed. It would be surprising if a list of samples with unsorted time-stamps were acceptable for FFT analysis.

Using IXcomplex Sample Lists With Headers

Before using such a list of IXcomplex samples with any of the headers defined above, an IXcomplex preprocessor would need to convert the headered list into a non-headered list of complex samples. On a Raspberry Pi, this preprocessor can handle all headers of IXcomplex lists. However a Pico processor will not be able to handle complex numbers that need to contain Unix times in the imaginary portion of each sample. This is a limitation of the Pico Python code, not a limitation of the IXcomplex format.

But Pico processors can handle complex time-stamps that are relative to a time of 0 seconds. These timestamps are all relative to 0 seconds, not relative to the time-stamp of the first sample. This is similar to the concept that Unix timestamps are not relative to the timestamp of the first sample. IXcomplex timestamps without any headers are simply time-stamped samples, with each time-stamp being relative to 0 seconds. Time-stamps of any other nature must be defined using IXcomplex headers.

The use of a headered IXcomplex list of samples can address a limitation of the Raspberry Pico hardware. The limitation is that current Unix times are very large, for example a recent complex sample might be (0x1000+1621625066j). The issue is that a Raspberry Pico cannot store the numeric value of such a large imaginary part in a Python integer. But putting this large number in the header would address this issue. This is because the "clock" in the Pico cannot handle this large number, but the Pico is able to create a "text string" of this long a length. After the first two header samples, the imaginary part of the IXcomplex sample string need only convey the exact sample intervals since (ie relative to) the Unix Date/Time stored in the imaginary part of header record #2.

CONCLUSION: Pico Unix time interval problem is solved by IXcomplex Headers.

The Pico can easily generate (or Use) an IXcomplex sample list.

It is very interesting to note that the IXcomplex preprocessor can convert "ANY IXcomplex sample list" into an IXcomplex sample list with Headers that is usable on the Raspberry Pico. The only qualification is that each relative timestamp not exceed the size of a Pico's Python integer that can be stored in a Raspberry Pico in MicroPython. This will almost never be a problem because such an integer is equivalent to a number of days of Unix time.

An unexplored dimension of the IXcomplex sample list is how to address fractions of a second. Should the imaginary value associated with each sample be actual seconds, a whole number of milliseconds (without a decimal point) or a whole number of microseconds? That topic will not be addressed here. For now, a decimal point will always be included if the imaginary part is not a whole number of seconds.

It is interesting to note that it is very simple to implement the IXcomplex sample lists into programs that were not developed with IXcomplex sample files in mind. When a supposedly non-IXcomplex file is being processed, upon encountering a null value in the header of an IXcomplex file, the MicroPython "error" that is thrown must be transferred to the IXcomplex preprocessor which will produce a non-headered complex sample file. This file can then be converted to a list of integer values of samples or into two lists: one of samples and the other of Unix Date/Times. The user (programmer) must then choose which non-IXcomplex format he/she wishes to use. Most of the work will have already been done by the IXcomplex preprocessor.

The IXcomplex preprocessor can always convert two real number lists of sample values (and timestamps) into an IXcomplex list. The two incoming lists consist of a list of real-number sample values and a list of Unix times (or inter-sample time intervals). The complex list produced will be an IXcomplex list with or without headers. If the intervals between the relative timestamps are regular (consistenly) then an IXcomplex list will be produced including an IXcomplex Header. The IXcomplex processor will always relegate the "first" Unix time-stamp into the header, retaining only the relative time intervals between values (readings). The time-interval can be calculated from the differences between successive imaginary parts of each complex value. if they are regular (consistently), the time interval will also be moved from the imaginary field into the header, leaving all imaginary fields empty (except for those in the two header samples). The test of being "regular" can be forgiving, allowing small differences in inter-sample times. Perhaps a test of .1% variation could be adopted as satisfactory in IXcomplex files. The goal of the IXcomplex preprocessor is to convert lists of time-stamped samples into the smallest (least verbose) IXcomplex format possible.

The IXcomplex format (including headers) for storing time-stamped samples reduces complexity, minimizes processing time and permits the use of equivalent Unix-timestamped samples to be used by the Raspberry Pico. It also converts a list of voltage values (sampled at regular time-intervals), into a very useful format, the IXcomplex format. The IXcomplex format can be directly converted into a regular waveform such as a digital form or into a regular analogue form (such as a sine wave or square wave). However a Raspberry Pi (instead of a Pico) is needed to do this easily. Interesting indeed!

WaveForms in IXcomplex format

Consider the IXcomplex format (with 7 header records). It would be as shown below:

( ("",.001j),("",0j),("","sin"),(60,4.5j),(-110,0j),(+110,0j),(anyChar,delayTj) )
This would mean a regular sine wave at a frequency of 60 Hz with an amplitude of +/- 110 RMS volts for a total time interval of 4.5 seconds. If the 4.5j is 0j, only 1 full cycle of samples will be generated as shown below.

( ("",.001j),("",0j),("","sin"),(60,0j),(-110,0j),(+110,0j),(anyChar,delayTj) )
A square wave (min 0v, max 1v) at a frequency of 3 Hz (per full cycle sampled 100 times per second would be:

( ("",.001j),("",0j),("","square"),(3,0j),(0,0j),(1,0j),(anyChar,delayTj) )

Each of the above waveforms define one unique list of IXcomplex samples (values). The first "0j" field even permits the exact Unix time of the first sample to be defined, if desired. The first 3 real null entries indicate that this is an abnormal (short) header that defines a regular wave. As with any regular wave, when the actual samples are created, the min and max values will be taken into account when the samples are created. The last value of (anyChar,delayTj) can be defined in the future. It may be used to note the time interval between the request and the time of the first sample reading: the delay Time.

IX callable functions

Note that, in this article, the waveform of the "sin" function is referred to as a "sine wave".

The first function is what a human would use to create the first regular wave. It is:
	def IXtoWave(sampIntervalSecs, Unix-timestamp, "sin",60,totalSecs,min,max,anyRJ):
	    #(creation of this wave with parameters suited to a human user)
	
The following IXpreprocessor function is used to convert IXcomplex formats to/from waves and/or non-complex list formats:
	def IXpreprocessor("WaveToIXcomplex:, listIn, listOut):
	    # note that the values of each field are parts of the list that define the wave.
	
	def IXpreprocessor("IXcomplexToWave:, listIn, listOut):
	    # note that the values of each field are parts of the list that define the wave.
	
	def IXpreprocessor("IXcomplexTolist", listIn, listOut):
	
	def IXpreprocessor("listtoIXcomplex", listIn, listOut):
	
See Source 09 for a main progam with a function named "def RAPasc(nn,cvrsFactor):" that reads 100 samples from an ADC pin on a Raspberry Pico and stores them in a complex list in a manner similar to an IXcomplex list. The actual main.py Python program is found there in S180:S01. Note that this "homemade" digital voltmeter attenuates the actual voltage readings by a factor of 10 in order to protect the electronic ADC components from being destroyed. It contains a visual example (an image) of a single complex voltage reading that contains the real sample component and the imaginary time component along with an image of the devices used to take the measurement (sample reading). Source 09 (Article 180) contains many Sources that show how the Pico can take a number of very rapid readings. It mentions a Fast Fourier Transform ( FFT ) which is a mathematical procedure that converts a list of regularly timed samples into a regular wave function such as a sine wave. The FFT also defines the frequency and amplitude of the sine wave, if it exists.

Conclusion

The ixmRPC system is still being developed. Do NOT expect any of the above code to work as-is. However, the concepts of an RPC system, are hopefully faithfully described. In fact, the ixmRPC system should not be much more complicated than this, in its infancy. It is the "Transport" that must next be expanded. As indicated above, there is no need for a "Transport" mechanism when the "client" core and the "server" core are the same machine. It is interesting to note that there is an application for a type of "almost null" RPC. Such an application is when the Pin usage of an existing AandC software application is changed. The change might be implemented very simply by changing one or two IDL files. The ixmRPC concept is as intriguing as the Wio Terminal. If only I had enough hours in each day to develop all this software. :(

Note that the ixmRPC system is designed ONLY to be used for MicroPython use. Users of CircuitPython have many references available to them. The ixmRPC system, and the new PiR2W device (Source 04), by David @ ColeCanada.com, are works-in-progress as of 2023DApr29.
This article, by D@CC, is of course, also a work-in-progress as of 2023DApr29.

Refer to Source 03 for Test_PB_Most_Simple_py.txt (Source 03) which is the first program to be written for this nascent ixmRPC system. Hopefully it will soon be tested.

The ixmRPC system will create a distinct need for a method of storing a list of datums ie readings. Initally these lists need only be stored in Client machines. But as Servers become more and more powerful, these lists will be generated and stored in the Servers themselves. The need for sending lists and files between Clients cores and Server cores will soon become more and more evident.

End of Article (Sources Follow)

Sources

Video Sources

Video Source V193:01:www Exploring the Wio Terminal ( 1:14 min) by Seeed Studio in 2021

Web Sources

Web Source S193:01:www Pi: PiR2Null Area Controller (153) by D@CC as of 2021BFeb08
Web Source S193:02:www ixmRPC Pushbutton V01.00 by D@CC as of 2023DApr28
Web Source S193:03:www ixmRPC Pushbutton V01.00 Test_PB_Most_Simple_py.txt by D@CC as of 2023DApr26
Web Source S193:04:www Simple FTP Server library now with support for Wio Terminal and SD by RENZO MISCHIANTI as of 2021LDec17
Web Source S193:05:www Pi: Pix Explorer RPC (179.html) by D@CC as of 2022FJun05
Web Source S193:06:www IT: Use a PC as an Oscilloscope (168.html) by D@CC as of 2022AJan22
Web Source S193:07:www Pi: Maker Pi Pico by Cytron (164.html) by D@CC as of 2022AJan22
Web Source S193:08:www Pi: Pix - Interactive Ascii Protocol for Pi Control of an RP2040 (177.html) by D@CC as of 2022EMay01
Web Source S193:09:www See vMeterIXA_pico_py.txt in Pi: Pix voltMeter_pico (180.html) by D@CC as of 2022FJun11
Web Source S193:10:www AandC: MIC -Meh In Charge .com (128.html) by D@CC as of 2022EMay01

WebMaster: Ye Old King Cole

following 5 folders There is a way to "google" all the part-numbers, words and phrases in all my articles. This "google" search limits itself ONLY to my articles. Just go to the top of "ePC Articles by Old King Cole" and look for the "search" input box.

Click here to return to ePC Articles by Old King Cole

Date Written : 2023 D Apr 15
Last Updated : 2023 J Oct 11

All rights reserved 2023 by (c) ICH180RR

saved in E:\E\2022\DevE\MyPagesE\Globat\ePhotoCaption.com\a\193\193.html
backed up to ePhotoCaption.com\a\193\193_2023EMay11.html
Font: Courier New 10 (monospaced)
/193.html