mirror of
https://github.com/digistump/DigistumpArduino.git
synced 2025-09-17 09:22:28 -07:00
Add OLED library - update tiny wire libraries - add support for all PWM channels and PWM on pin 8
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
TinyPinChange library
|
||||
=====================
|
||||
|
||||
**TinyPinChange** is an asynchronous (interrupt-driven) library designed to detect event (rising or falling edege) on pins.
|
||||
|
||||
Very often in the arduino world, users complain about conflicts between libraries.
|
||||
|
||||
This **TinyPinChange** library allows to share the "pin change interrupt" vector for several "clients".
|
||||
|
||||
For example, it's possible to use the **SoftRcPulseIn** library whilst using the **SoftSerial** library: both libraries rely on the **TinyPinChange** library.
|
||||
|
||||
Some examples of use cases:
|
||||
-------------------------
|
||||
* **Event detector** (on pins)
|
||||
* **Frequency meter**
|
||||
* **Pulse width meter**
|
||||
* **Tachometer**
|
||||
* **Duty cycle measurement**
|
||||
* **Software serial port** (see **SoftSerial** library which relies on TinyPinChange)
|
||||
|
||||
Supported Arduinos:
|
||||
------------------
|
||||
* **ATmega368 (UNO)**
|
||||
* **ATmega2560 (MEGA)**
|
||||
* **ATtiny84 (Standalone)**
|
||||
* **ATtiny85 (Standalone or Digispark)**
|
||||
* **ATtiny167 (Digispark pro)**
|
||||
|
||||
Tip and Tricks:
|
||||
--------------
|
||||
Develop your project on an arduino UNO or MEGA, and then shrink it by loading the sketch in an ATtiny or Digispark (pro).
|
||||
|
||||
API/methods:
|
||||
-----------
|
||||
* TinyPinChange_Init()
|
||||
* TinyPinChange_RegisterIsr()
|
||||
* TinyPinChange_EnablePin()
|
||||
* TinyPinChange_DisablePin()
|
||||
* TinyPinChange_GetPortEvent()
|
||||
* TinyPinChange_GetCurPortSt()
|
||||
* TinyPinChange_PinToMsk()
|
||||
* TinyPinChange_Edge()
|
||||
* TinyPinChange_RisingEdge
|
||||
* TinyPinChange_FallingEdge
|
||||
|
||||
Design considerations:
|
||||
---------------------
|
||||
On the arduino MEGA, as all the pins do not support "pin change interrupt", only the following pins are supported:
|
||||
|
||||
* 10 -> 15
|
||||
* 50 -> 53
|
||||
* A8 -> A15
|
||||
|
||||
On other devices (ATmega328, ATtiny84, ATtiny85 and ATtiny167), all the pins are usable.
|
||||
|
||||
Contact
|
||||
-------
|
||||
|
||||
If you have some ideas of enhancement, please contact me by clicking on: [RC Navy](http://p.loussouarn.free.fr/contact.html).
|
||||
|
@@ -70,7 +70,7 @@ void setup()
|
||||
{
|
||||
TinyPinChange_Init();
|
||||
|
||||
MySerial.begin(38400); /* Trick: use a "high" data rate (less time wasted in ISR and for transmitting each character) */
|
||||
MySerial.begin(57600); /* Trick: use a "high" data rate (less time wasted in ISR and for transmitting each character) */
|
||||
|
||||
VirtualPortNb = TinyPinChange_RegisterIsr(FIRST_INPUT, InterruptFunctionToCall);
|
||||
VirtualPortNb_ = TinyPinChange_RegisterIsr(SECOND_INPUT, InterruptFunctionToCall);
|
||||
@@ -118,7 +118,7 @@ uint16_t LocalFirstInputChangeCount;
|
||||
uint16_t LocalSecondInputChangeCount;
|
||||
|
||||
/* Blink the built-in LED */
|
||||
if(millis() - LedStartMs >= 500)
|
||||
if(millis() - LedStartMs >= 500UL)
|
||||
{
|
||||
LedStartMs = millis();
|
||||
digitalWrite(LED_PIN, State);
|
||||
@@ -141,7 +141,7 @@ uint16_t LocalSecondInputChangeCount;
|
||||
}
|
||||
|
||||
/* Diplay Transition numbers every second */
|
||||
if((millis() - DisplayStartMs >= 1000) && DisplayEnabled)
|
||||
if((millis() - DisplayStartMs >= 1000UL) && DisplayEnabled)
|
||||
{
|
||||
DisplayStartMs = millis();
|
||||
noInterrupts(); /* Mandatory since counters are 16 bits */
|
||||
|
@@ -70,7 +70,7 @@ void setup()
|
||||
{
|
||||
TinyPinChange_Init();
|
||||
|
||||
MySerial.begin(38400); /* Trick: use a "high" data rate (less time wasted in ISR and for transmitting each character) */
|
||||
MySerial.begin(57600); /* Trick: use a "high" data rate (less time wasted in ISR and for transmitting each character) */
|
||||
|
||||
VirtualPortNb = TinyPinChange_RegisterIsr(FIRST_INPUT, InterruptFunctionToCall);
|
||||
VirtualPortNb_ = TinyPinChange_RegisterIsr(SECOND_INPUT, InterruptFunctionToCall);
|
||||
@@ -118,7 +118,7 @@ uint16_t LocalFirstInputChangeCount;
|
||||
uint16_t LocalSecondInputChangeCount;
|
||||
|
||||
/* Blink the built-in LED */
|
||||
if(millis() - LedStartMs >= 500)
|
||||
if(millis() - LedStartMs >= 500UL)
|
||||
{
|
||||
LedStartMs = millis();
|
||||
digitalWrite(LED_PIN, State);
|
||||
@@ -141,7 +141,7 @@ uint16_t LocalSecondInputChangeCount;
|
||||
}
|
||||
|
||||
/* Diplay Transition numbers every second */
|
||||
if((millis() - DisplayStartMs >= 1000) && DisplayEnabled)
|
||||
if((millis() - DisplayStartMs >= 1000UL) && DisplayEnabled)
|
||||
{
|
||||
DisplayStartMs = millis();
|
||||
noInterrupts(); /* Mandatory since counters are 16 bits */
|
||||
|
@@ -70,7 +70,7 @@ void setup()
|
||||
{
|
||||
TinyPinChange_Init();
|
||||
|
||||
MySerial.begin(38400); /* Trick: use a "high" data rate (less time wasted in ISR and for transmitting each character) */
|
||||
MySerial.begin(57600); /* Trick: use a "high" data rate (less time wasted in ISR and for transmitting each character) */
|
||||
|
||||
VirtualPortNb = TinyPinChange_RegisterIsr(FIRST_INPUT, InterruptFunctionToCall);
|
||||
VirtualPortNb_ = TinyPinChange_RegisterIsr(SECOND_INPUT, InterruptFunctionToCall);
|
||||
@@ -118,7 +118,7 @@ uint16_t LocalFirstInputChangeCount;
|
||||
uint16_t LocalSecondInputChangeCount;
|
||||
|
||||
/* Blink the built-in LED */
|
||||
if(millis() - LedStartMs >= 500)
|
||||
if(millis() - LedStartMs >= 500UL)
|
||||
{
|
||||
LedStartMs = millis();
|
||||
digitalWrite(LED_PIN, State);
|
||||
@@ -141,7 +141,7 @@ uint16_t LocalSecondInputChangeCount;
|
||||
}
|
||||
|
||||
/* Diplay Transition numbers every second */
|
||||
if((millis() - DisplayStartMs >= 1000) && DisplayEnabled)
|
||||
if((millis() - DisplayStartMs >= 1000UL) && DisplayEnabled)
|
||||
{
|
||||
DisplayStartMs = millis();
|
||||
noInterrupts(); /* Mandatory since counters are 16 bits */
|
||||
|
@@ -0,0 +1,440 @@
|
||||
/*
|
||||
_____ ____ __ _ ____ _ _ _ _
|
||||
| __ \ / __ \ | \ | | / __ \ | | | | | | | |
|
||||
| |__| | | / \_| | . \ | | / / \ \ | | | | \ \ / /
|
||||
| _ / | | _ | |\ \| | | |__| | | | | | \ ' /
|
||||
| | \ \ | \__/ | | | \ ' | | __ | \ \/ / | |
|
||||
|_| \_\ \____/ |_| \__| |_| |_| \__/ |_| 2013/2014
|
||||
|
||||
http://p.loussouarn.free.fr
|
||||
|
||||
*******************************************************
|
||||
* <TinyPinChange> library Demo *
|
||||
* with display capabilities using *
|
||||
* <SoftSerial> object as single wire serial interface *
|
||||
*******************************************************
|
||||
|
||||
This "Tiny RC Scope" sketch demonstrates how to use <TinyPinChange> and <SoftSerial> libraries.
|
||||
"Tiny RC Scope" acts as a simple real time ASCII oscilloscope for displaying one RC Channel in the serial console.
|
||||
The displayed measurement (in µs) are: pulse width and RC period.
|
||||
|
||||
Trick: By connecting Pin#1 to Pin#0, through a 1K resistor, you can measure the RC Signal provided by the built-in RC generator for testing purpose.
|
||||
Output results are sent to a software serial port. If a real RC signal is connected to Pin0, the trace is displayed in real time in the terminal.
|
||||
|
||||
And the great thing is: using a <SoftSerial> object as a bi-directionnal software serial port (half-duplex) on a single pin to communicate with the outside world!
|
||||
|
||||
To display the sketch results on a PC (in a Terminal):
|
||||
1) Build the "Serial One Wire Debug Cable" and plug it to the regular RS232 port as depicted below.
|
||||
2) Open your favorite Terminal at 57600,n,8,1: HyperTerminal, Teraterm (Windows) or Minicom, GtkTerm (Linux) and CoolTerm (MAC) does the trick.
|
||||
3) You can also use the Serial Monitor of the arduino IDE: Tools->Serial Port and select your RS232 port (may be an USB virtual port), Rate=57600.
|
||||
4) To test "Tiny RC Scope", connect Pin1 to Pin0, and look at the Terminal (57600,n,8,1) connected to Pin2 through a debug cable ()
|
||||
5) The wave form should be displayed in the Terminal,
|
||||
6) Type - to decrease the pulse width (-10us),
|
||||
7) Type + to increase the pulse width (+10us),
|
||||
8) Type m to set the pulse width to its minimum (500us),
|
||||
9) Type n or N to set the pulse width to its Neutral value (1500us),
|
||||
10) Type M to set the pulse width to its Maximum (2500us),
|
||||
11) To measure real RC signals, disconnect the Pin1 from Pin0 and connect a RC receiver output to Pin0,
|
||||
12) The Terminal will display in real time the pulse width of the connected RC channel.
|
||||
13) If the channel is not connected, a flat line is displayed.
|
||||
|
||||
SERIAL ONE WIRE
|
||||
DEBUGGING CABLE
|
||||
_______________ ________________
|
||||
/ \___/\___/ \
|
||||
____
|
||||
.--------. | \
|
||||
| GND |--------------------------------+---o5 \
|
||||
| | 47K | | 9o |
|
||||
| | .--###--' | o4 |
|
||||
| DEBUG | 4.7K | | 8o |
|
||||
| TX_RX |-------------------###--+--|<|------o3 | ---> To regular RS232 SubD 9 pins Male of PC or Serial/USB adapter
|
||||
| PIN | ^ | 1N4148 | 7o |
|
||||
| | | '-----------o2 |
|
||||
'--------' | | 6o |
|
||||
ATtiny85 Single | o1 /
|
||||
(Digispark) I/O |____/
|
||||
(pro) SubD 9 pins
|
||||
Female
|
||||
*/
|
||||
#include <TinyPinChange.h>
|
||||
#include <SoftSerial.h>
|
||||
|
||||
#define RC_CHANNEL_PIN 0 /* RC Channel is connected to pin 0 */
|
||||
#define RC_GEN_PIN 1 /* Pin used as internal RC generator for test purpose */
|
||||
|
||||
#define RC_PINS_MSK (_BV(RC_CHANNEL_PIN) | _BV(RC_GEN_PIN))
|
||||
|
||||
#define DEBUG_TX_RX_PIN 2
|
||||
|
||||
#define DEF_TEST_RC_CH_WIDTH_US 1500 /* This value can be change via the Terminal */
|
||||
#define TEST_RC_PERIOD_US 20000
|
||||
|
||||
#define PULSE_MAX_US 2500
|
||||
#define PULSE_MIN_US 500
|
||||
#define STEP_US 10
|
||||
|
||||
#define ERR_MARGIN_US 150
|
||||
|
||||
#define SERIAL_BAUD_RATE 57600 /* 57600 is the maximum for Receiving commands from the serial port: 1 char -> #200us */
|
||||
SoftSerial MySerial(DEBUG_TX_RX_PIN, DEBUG_TX_RX_PIN, true); /* Tx/Rx on a single Pin !!! (Pin#2) */
|
||||
|
||||
#define ONE_CHAR_TX_TIME_US 200 /* @ 57600 bauds */
|
||||
|
||||
enum {PULSE_SRC_INTERNAL, PULSE_SRC_EXTERNAL};
|
||||
|
||||
typedef struct {
|
||||
uint32_t RisingStartUs;
|
||||
uint32_t RcWidth_us;
|
||||
uint32_t LastRxPulseMs;
|
||||
boolean FallingEdgeFound;
|
||||
}RcChSt_t;
|
||||
|
||||
volatile RcChSt_t Ch; /* volatile, since value are used in ISR and in the loop() */
|
||||
volatile uint32_t RcPeriod_us = TEST_RC_PERIOD_US;
|
||||
uint32_t TestRcWidth_us = DEF_TEST_RC_CH_WIDTH_US;
|
||||
|
||||
/* The different states of the display state machine */
|
||||
enum {DISP_COMPUTE, DISP_FIRST_LINE, DISP_PREP_SEC_LINE, DISP_SECOND_LINE, DISP_PREP_THIRD_LINE, DISP_THIRD_LINE, DISP_WAIT};
|
||||
|
||||
#define LINE_LEN 38
|
||||
|
||||
typedef struct{
|
||||
char Line[LINE_LEN];
|
||||
uint8_t Idx;
|
||||
uint8_t State;
|
||||
uint8_t HighNb;
|
||||
}DispSt_t;
|
||||
|
||||
static DispSt_t Disp;
|
||||
|
||||
volatile uint8_t IntRcSynch = 0;
|
||||
uint8_t VirtualPortIdx;
|
||||
/*
|
||||
RC Signal
|
||||
____ ____
|
||||
_| |____________________________| |_
|
||||
<---->
|
||||
Width_us
|
||||
<-------------------------------->
|
||||
Period_us
|
||||
*/
|
||||
void setup()
|
||||
{
|
||||
TinyPinChange_Init();
|
||||
|
||||
MySerial.begin(SERIAL_BAUD_RATE); /* Trick: use a "high" data rate (less time wasted in ISR and for transmitting each character) */
|
||||
|
||||
Disp.State = DISP_COMPUTE;
|
||||
|
||||
VirtualPortIdx = TinyPinChange_RegisterIsr(RC_CHANNEL_PIN, InterruptFunctionToCall); /* As all pins are on the same port, a single ISR is needed */
|
||||
pinMode(RC_CHANNEL_PIN, INPUT);
|
||||
digitalWrite(RC_CHANNEL_PIN, HIGH); /* Enable Pull-up to avoid floating inputs in case of nothing connected to them */
|
||||
TinyPinChange_EnablePin(RC_CHANNEL_PIN);
|
||||
|
||||
Ch.RcWidth_us = 0;
|
||||
Ch.FallingEdgeFound = 0;
|
||||
|
||||
MySerial.txMode();
|
||||
MySerial.println(F("\n -- Tiny RC Scope V1.0 (C) RC Navy 2014 --\n"));
|
||||
MySerial.rxMode(); /* Switch to Rx Mode */
|
||||
|
||||
pinMode(RC_GEN_PIN, OUTPUT);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
uint32_t RcGeneStartUs = micros();
|
||||
static uint32_t ProcessStartUs = micros();
|
||||
static uint32_t DisplayStartMs = millis();
|
||||
uint32_t ProcessDurationUs;
|
||||
uint32_t HalfRemaingLowUs;
|
||||
char RxChar;
|
||||
|
||||
/* Blink the built-in LED (Built-in RC Signal generator) */
|
||||
if(IsInternalRcSrc())
|
||||
{
|
||||
RcGeneStartUs = micros();
|
||||
digitalWrite(RC_GEN_PIN, HIGH);
|
||||
while(micros() - RcGeneStartUs < TestRcWidth_us);
|
||||
digitalWrite(RC_GEN_PIN, LOW);
|
||||
}
|
||||
/********************/
|
||||
/* Start of process */
|
||||
/********************/
|
||||
ProcessStartUs = micros();
|
||||
DisplayRcMeasurement(5000U);/* Gives 5000 us to display a part of the trace */
|
||||
/* Get command from single wire SoftSerial (to tune the built-in generator) */
|
||||
if(MySerial.available() > 0)
|
||||
{
|
||||
RxChar = MySerial.read();MySerial.txMode();MySerial.println("");MySerial.rxMode(); /* Carriage return after the echo */
|
||||
switch(RxChar)
|
||||
{
|
||||
case '-': /* Decrease Built-in RC Pulse */
|
||||
if((TestRcWidth_us - STEP_US) >= PULSE_MIN_US)
|
||||
{
|
||||
TestRcWidth_us -= STEP_US;
|
||||
}
|
||||
break;
|
||||
|
||||
case '+': /* Increase Built-in RC Pulse */
|
||||
if(TestRcWidth_us + STEP_US <= PULSE_MAX_US)
|
||||
{
|
||||
TestRcWidth_us += STEP_US;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'm': /* Set Built-in RC Pulse o min value: 500 */
|
||||
TestRcWidth_us = PULSE_MIN_US;
|
||||
break;
|
||||
|
||||
case 'N': /* Set Built-in RC Pulse to Neutral: 1500 */
|
||||
case 'n':
|
||||
TestRcWidth_us = DEF_TEST_RC_CH_WIDTH_US;
|
||||
break;
|
||||
|
||||
case 'M': /* Set Built-in RC Pulse to Max value: 2500 */
|
||||
TestRcWidth_us = PULSE_MAX_US;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Ignore */
|
||||
break;
|
||||
}
|
||||
}
|
||||
/********************/
|
||||
/* End of process */
|
||||
/********************/
|
||||
ProcessDurationUs = micros() - ProcessStartUs; //Compute how many us took the previous instructions
|
||||
if(IsInternalRcSrc())
|
||||
{
|
||||
HalfRemaingLowUs = TEST_RC_PERIOD_US - (ProcessDurationUs + TestRcWidth_us + 100UL);
|
||||
RcGeneStartUs = micros();
|
||||
while((micros() - RcGeneStartUs) < HalfRemaingLowUs);
|
||||
}
|
||||
}
|
||||
/*
|
||||
RC Signal
|
||||
____ ____
|
||||
_| |____________________________| |_
|
||||
<---->
|
||||
Width_us
|
||||
<-------------------------------->
|
||||
Period_us
|
||||
<-------------------->
|
||||
Display is processed here
|
||||
|
||||
Explanation: the display of the trace is performed just after the falling edge of the RC pulse
|
||||
As the duration between 2 pulses is too short to display the full trace, the trace is displayed part by part.
|
||||
A full trace is composed of around 100 characters:
|
||||
At 57600 bauds, one character takes (1/57600) * 10 = 174 us. As there are some overhead, it is closer than 200us.
|
||||
So, the full trace takes 100 x 200 = 20000 us = 20 ms. It's impossible to display the full trace between 2 consecutive pulses.
|
||||
DisplayRcMeasurement() function is the very tricky part of this sketch: it has as argument an amount of time and exits before
|
||||
it exceeds it. A state machine is used to memorize where the display was arrived.
|
||||
*/
|
||||
uint8_t DisplayRcMeasurement(uint16_t FreetimeUs)
|
||||
{
|
||||
static uint32_t LocalRcWidth_us;
|
||||
static uint32_t LocalRcPeriod_us;
|
||||
static uint32_t StartWaitMs;
|
||||
char *Ptr;
|
||||
|
||||
uint32_t ProcessStart_us;
|
||||
uint32_t Elapsed_us;
|
||||
uint8_t StartIdx, Idx;
|
||||
uint8_t Ret = 0;
|
||||
|
||||
switch(Disp.State)
|
||||
{
|
||||
case DISP_COMPUTE:
|
||||
DispCompute:
|
||||
if(Ch.FallingEdgeFound)
|
||||
{
|
||||
DispComputeNoSignal:
|
||||
ProcessStart_us = micros();
|
||||
Ch.FallingEdgeFound = 0;
|
||||
noInterrupts(); /* Mandatory since RcWidth_us and RcPeriod_us are 32 bits */
|
||||
LocalRcWidth_us = Ch.RcWidth_us;
|
||||
LocalRcPeriod_us = RcPeriod_us;
|
||||
interrupts();
|
||||
|
||||
if(LocalRcWidth_us < (PULSE_MIN_US - ERR_MARGIN_US) || LocalRcWidth_us > (PULSE_MAX_US + ERR_MARGIN_US)) LocalRcWidth_us = 0; /* Out of Range */
|
||||
Disp.HighNb = (LocalRcWidth_us + 50UL) / 100;
|
||||
strcpy_P(Disp.Line, PSTR("Ch(P0)__"));
|
||||
if(LocalRcWidth_us)
|
||||
{
|
||||
Ptr = Disp.Line + 8;
|
||||
for(Idx = 0; Idx < Disp.HighNb; Idx++) *Ptr++='_';*Ptr++='\n';*Ptr=0;
|
||||
}
|
||||
else Disp.Line[6] = 0;
|
||||
Elapsed_us = micros() - ProcessStart_us;
|
||||
FreetimeUs -= (uint16_t)Elapsed_us;
|
||||
Disp.Idx=0;
|
||||
Disp.State = DISP_FIRST_LINE;
|
||||
if(FreetimeUs >= ONE_CHAR_TX_TIME_US)
|
||||
{
|
||||
goto DispFirstLine;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(millis() - StartWaitMs >= 1000UL)
|
||||
{
|
||||
LocalRcWidth_us = 0;
|
||||
goto DispComputeNoSignal;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DISP_PREP_SEC_LINE:
|
||||
DispPrepSecLine:
|
||||
/* Prepare second line */
|
||||
ProcessStart_us = micros();
|
||||
if(LocalRcWidth_us)
|
||||
{
|
||||
strcpy_P(Disp.Line, PSTR("_____/"));
|
||||
for(Idx = 0; Idx < (2 + Disp.HighNb); Idx++) Disp.Line[6 + Idx] = ' ';
|
||||
itoa(LocalRcWidth_us, Disp.Line + 6, 10);StartIdx = 9; if(LocalRcWidth_us >= 1000) StartIdx++;Disp.Line[StartIdx++] = 'u';Disp.Line[StartIdx++] = 's';
|
||||
StartIdx = 6 + 2 + Disp.HighNb;Disp.Line[StartIdx++] = '\\';
|
||||
}
|
||||
else StartIdx = 0;
|
||||
for(Idx = 0; (StartIdx + Idx ) < (LINE_LEN - 2); Idx++) Disp.Line[StartIdx + Idx] = '_';Disp.Line[StartIdx + Idx] = '\n';Disp.Line[++StartIdx + Idx] = 0;
|
||||
Elapsed_us = micros() - ProcessStart_us;
|
||||
FreetimeUs -= (uint16_t)Elapsed_us;
|
||||
Disp.Idx=0;
|
||||
Disp.State = DISP_SECOND_LINE;
|
||||
if(FreetimeUs >= ONE_CHAR_TX_TIME_US)
|
||||
{
|
||||
goto DispSecondLine;
|
||||
}
|
||||
break;
|
||||
|
||||
case DISP_PREP_THIRD_LINE:
|
||||
DispPrepThirdLine:
|
||||
/* Prepare third line */
|
||||
ProcessStart_us = micros();
|
||||
strcpy_P(Disp.Line, PSTR(" RC Period: "));
|
||||
if(LocalRcWidth_us)
|
||||
{
|
||||
itoa(LocalRcPeriod_us, Disp.Line + 20, 10);
|
||||
strcat_P(Disp.Line, PSTR("us"));
|
||||
}
|
||||
else strcat_P(Disp.Line, PSTR("???"));
|
||||
Elapsed_us = micros() - ProcessStart_us;
|
||||
FreetimeUs -= (uint16_t)Elapsed_us;
|
||||
Disp.Idx=0;
|
||||
Disp.State = DISP_THIRD_LINE;
|
||||
if(FreetimeUs >= ONE_CHAR_TX_TIME_US)
|
||||
{
|
||||
goto DispThirdLine;
|
||||
}
|
||||
break;
|
||||
|
||||
case DISP_FIRST_LINE:
|
||||
case DISP_SECOND_LINE:
|
||||
case DISP_THIRD_LINE:
|
||||
DispFirstLine:
|
||||
DispSecondLine:
|
||||
DispThirdLine:
|
||||
ProcessStart_us = micros();
|
||||
MySerial.txMode();
|
||||
while(1)
|
||||
{
|
||||
if(Disp.Line[Disp.Idx])
|
||||
{
|
||||
MySerial.print(Disp.Line[Disp.Idx++]);
|
||||
if (micros() - ProcessStart_us >= (FreetimeUs - ONE_CHAR_TX_TIME_US))
|
||||
{
|
||||
MySerial.rxMode();
|
||||
break; /* exit while(1) and stay in the current state */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(Disp.State)
|
||||
{
|
||||
case DISP_FIRST_LINE:
|
||||
/* First line is fully displayed */
|
||||
Disp.State = DISP_PREP_SEC_LINE;
|
||||
if(FreetimeUs - Elapsed_us >= 200)
|
||||
{
|
||||
FreetimeUs -= (uint16_t)Elapsed_us;
|
||||
goto DispPrepSecLine;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Not enough time: just change state */
|
||||
MySerial.rxMode();
|
||||
}
|
||||
break;
|
||||
|
||||
case DISP_SECOND_LINE:
|
||||
/* Second line is fully displayed */
|
||||
Disp.State = DISP_PREP_THIRD_LINE;
|
||||
if(FreetimeUs - Elapsed_us >= 200)
|
||||
{
|
||||
FreetimeUs -= (uint16_t)Elapsed_us;
|
||||
goto DispPrepThirdLine;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Not enough time: just change state */
|
||||
MySerial.rxMode();
|
||||
}
|
||||
break;
|
||||
|
||||
case DISP_THIRD_LINE:
|
||||
/* Third line is fully displayed */
|
||||
MySerial.print('\n');
|
||||
StartWaitMs = millis();
|
||||
Disp.State = DISP_WAIT;
|
||||
MySerial.rxMode();
|
||||
break;
|
||||
}
|
||||
break; /* exit while(1) */
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DISP_WAIT:
|
||||
if(millis() - StartWaitMs >= 500UL) Disp.State = DISP_COMPUTE; /* Give some time to enter commands via the terminal (in internal source mode) */
|
||||
else Ch.FallingEdgeFound = false;
|
||||
break;
|
||||
}
|
||||
return(Ret);
|
||||
}
|
||||
|
||||
/* The following function checks if the received signal is the image of the one of the built-in RC generator */
|
||||
uint8_t IsInternalRcSrc()
|
||||
{
|
||||
uint8_t Ret;
|
||||
static uint32_t SampleStartMs = millis();
|
||||
if(millis() - Ch.LastRxPulseMs >= 300UL) IntRcSynch = 100; /* Kick off Internal RC generator */
|
||||
Ret = (IntRcSynch >= 100);
|
||||
if(millis() - SampleStartMs >= 10UL)
|
||||
{
|
||||
SampleStartMs = millis();
|
||||
IntRcSynch = 99;
|
||||
}
|
||||
return(Ret);
|
||||
}
|
||||
|
||||
/* Function called in interruption in case of change on RC pins: pulse width and RC period measurement */
|
||||
void InterruptFunctionToCall(void)
|
||||
{
|
||||
if(TinyPinChange_RisingEdge(VirtualPortIdx, RC_CHANNEL_PIN)) /* Check for RC Channel rising edge */
|
||||
{
|
||||
RcPeriod_us = micros() - Ch.RisingStartUs;
|
||||
Ch.RisingStartUs = micros();
|
||||
}
|
||||
else
|
||||
{
|
||||
Ch.RcWidth_us = micros() - Ch.RisingStartUs;
|
||||
Ch.FallingEdgeFound = true;
|
||||
Ch.LastRxPulseMs = millis();
|
||||
if(!(PINB & RC_PINS_MSK)) /* Check if RC_CHANNEL_PIN and RC_GEN_PIN are both to 0 */
|
||||
{
|
||||
if(IntRcSynch < 100) IntRcSynch++; /* if IntRcSynch reaches 100, it means the RC source is internal (synchronized) */
|
||||
}else IntRcSynch = 0; /* Not synchronized */
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user