Initial commit
This is just the 2018 code configured for PlatformIO
This commit is contained in:
commit
4faddf9248
|
@ -0,0 +1,3 @@
|
||||||
|
.pio
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||||
|
// for the documentation about the extensions.json format
|
||||||
|
"recommendations": [
|
||||||
|
"platformio.platformio-ide"
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
|
||||||
|
This directory is intended for project header files.
|
||||||
|
|
||||||
|
A header file is a file containing C declarations and macro definitions
|
||||||
|
to be shared between several project source files. You request the use of a
|
||||||
|
header file in your project source file (C, C++, etc) located in `src` folder
|
||||||
|
by including it, with the C preprocessing directive `#include'.
|
||||||
|
|
||||||
|
```src/main.c
|
||||||
|
|
||||||
|
#include "header.h"
|
||||||
|
|
||||||
|
int main (void)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Including a header file produces the same results as copying the header file
|
||||||
|
into each source file that needs it. Such copying would be time-consuming
|
||||||
|
and error-prone. With a header file, the related declarations appear
|
||||||
|
in only one place. If they need to be changed, they can be changed in one
|
||||||
|
place, and programs that include the header file will automatically use the
|
||||||
|
new version when next recompiled. The header file eliminates the labor of
|
||||||
|
finding and changing all the copies as well as the risk that a failure to
|
||||||
|
find one copy will result in inconsistencies within a program.
|
||||||
|
|
||||||
|
In C, the usual convention is to give header files names that end with `.h'.
|
||||||
|
It is most portable to use only letters, digits, dashes, and underscores in
|
||||||
|
header file names, and at most one dot.
|
||||||
|
|
||||||
|
Read more about using header files in official GCC documentation:
|
||||||
|
|
||||||
|
* Include Syntax
|
||||||
|
* Include Operation
|
||||||
|
* Once-Only Headers
|
||||||
|
* Computed Includes
|
||||||
|
|
||||||
|
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
|
|
@ -0,0 +1 @@
|
||||||
|
*.db
|
Binary file not shown.
|
@ -0,0 +1,125 @@
|
||||||
|
// Please read Bounce2.h for information about the liscence and authors
|
||||||
|
|
||||||
|
|
||||||
|
#include "Bounce2.h"
|
||||||
|
|
||||||
|
static const uint8_t DEBOUNCED_STATE = 0b00000001;
|
||||||
|
static const uint8_t UNSTABLE_STATE = 0b00000010;
|
||||||
|
static const uint8_t CHANGED_STATE = 0b00000100;
|
||||||
|
|
||||||
|
|
||||||
|
Bounce::Bounce()
|
||||||
|
: previous_millis(0)
|
||||||
|
, interval_millis(10)
|
||||||
|
, state(0)
|
||||||
|
, pin(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void Bounce::attach(int pin) {
|
||||||
|
this->pin = pin;
|
||||||
|
state = 0;
|
||||||
|
if (readCurrentState()) {
|
||||||
|
setStateFlag(DEBOUNCED_STATE | UNSTABLE_STATE);
|
||||||
|
}
|
||||||
|
#ifdef BOUNCE_LOCK_OUT
|
||||||
|
previous_millis = 0;
|
||||||
|
#else
|
||||||
|
previous_millis = millis();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Bounce::attach(int pin, int mode){
|
||||||
|
setPinMode(pin, mode);
|
||||||
|
this->attach(pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Bounce::interval(uint16_t interval_millis)
|
||||||
|
{
|
||||||
|
this->interval_millis = interval_millis;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bounce::update()
|
||||||
|
{
|
||||||
|
|
||||||
|
unsetStateFlag(CHANGED_STATE);
|
||||||
|
#ifdef BOUNCE_LOCK_OUT
|
||||||
|
|
||||||
|
// Ignore everything if we are locked out
|
||||||
|
if (millis() - previous_millis >= interval_millis) {
|
||||||
|
bool currentState = readCurrentState();
|
||||||
|
if ( currentState != getStateFlag(DEBOUNCED_STATE) ) {
|
||||||
|
previous_millis = millis();
|
||||||
|
toggleStateFlag(DEBOUNCED_STATE);
|
||||||
|
setStateFlag(CHANGED_STATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#elif defined BOUNCE_WITH_PROMPT_DETECTION
|
||||||
|
// Read the state of the switch port into a temporary variable.
|
||||||
|
bool readState = readCurrentState();
|
||||||
|
|
||||||
|
|
||||||
|
if ( readState != getStateFlag(DEBOUNCED_STATE) ) {
|
||||||
|
// We have seen a change from the current button state.
|
||||||
|
|
||||||
|
if ( millis() - previous_millis >= interval_millis ) {
|
||||||
|
// We have passed the time threshold, so a new change of state is allowed.
|
||||||
|
// set the STATE_CHANGED flag and the new DEBOUNCED_STATE.
|
||||||
|
// This will be prompt as long as there has been greater than interval_misllis ms since last change of input.
|
||||||
|
// Otherwise debounced state will not change again until bouncing is stable for the timeout period.
|
||||||
|
toggleStateFlag(DEBOUNCED_STATE);
|
||||||
|
setStateFlag(CHANGED_STATE );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the readState is different from previous readState, reset the debounce timer - as input is still unstable
|
||||||
|
// and we want to prevent new button state changes until the previous one has remained stable for the timeout.
|
||||||
|
if ( readState != getStateFlag(UNSTABLE_STATE) ) {
|
||||||
|
// Update Unstable Bit to macth readState
|
||||||
|
toggleStateFlag(UNSTABLE_STATE);
|
||||||
|
previous_millis = millis();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#else
|
||||||
|
// Read the state of the switch in a temporary variable.
|
||||||
|
bool currentState = readCurrentState();
|
||||||
|
|
||||||
|
|
||||||
|
// If the reading is different from last reading, reset the debounce counter
|
||||||
|
if ( currentState != getStateFlag(UNSTABLE_STATE) ) {
|
||||||
|
previous_millis = millis();
|
||||||
|
toggleStateFlag(UNSTABLE_STATE);
|
||||||
|
} else
|
||||||
|
if ( millis() - previous_millis >= interval_millis ) {
|
||||||
|
// We have passed the threshold time, so the input is now stable
|
||||||
|
// If it is different from last state, set the STATE_CHANGED flag
|
||||||
|
if (currentState != getStateFlag(DEBOUNCED_STATE) ) {
|
||||||
|
previous_millis = millis();
|
||||||
|
toggleStateFlag(DEBOUNCED_STATE);
|
||||||
|
setStateFlag(CHANGED_STATE) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return getStateFlag(CHANGED_STATE);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bounce::read()
|
||||||
|
{
|
||||||
|
return getStateFlag(DEBOUNCED_STATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bounce::rose()
|
||||||
|
{
|
||||||
|
return getStateFlag(DEBOUNCED_STATE) && getStateFlag(CHANGED_STATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bounce::fell()
|
||||||
|
{
|
||||||
|
return !getStateFlag(DEBOUNCED_STATE) && getStateFlag(CHANGED_STATE);
|
||||||
|
}
|
|
@ -0,0 +1,110 @@
|
||||||
|
/*
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2013 thomasfredericks
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
Main code by Thomas O Fredericks (tof@t-o-f.info)
|
||||||
|
Previous contributions by Eric Lowry, Jim Schimpf and Tom Harkaway
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#ifndef Bounce2_h
|
||||||
|
#define Bounce2_h
|
||||||
|
|
||||||
|
#if defined(ARDUINO) && ARDUINO >= 100
|
||||||
|
#include "Arduino.h"
|
||||||
|
#else
|
||||||
|
#include "WProgram.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Uncomment the following line for "LOCK-OUT" debounce method
|
||||||
|
//#define BOUNCE_LOCK_OUT
|
||||||
|
|
||||||
|
// Uncomment the following line for "BOUNCE_WITH_PROMPT_DETECTION" debounce method
|
||||||
|
//#define BOUNCE_WITH_PROMPT_DETECTION
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
#ifndef _BV
|
||||||
|
#define _BV(n) (1<<(n))
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Bounce
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Create an instance of the bounce library
|
||||||
|
Bounce();
|
||||||
|
|
||||||
|
// Attach to a pin (and also sets initial state)
|
||||||
|
void attach(int pin);
|
||||||
|
|
||||||
|
// Attach to a pin (and also sets initial state) and sets pin to mode (INPUT/INPUT_PULLUP/OUTPUT)
|
||||||
|
void attach(int pin, int mode);
|
||||||
|
|
||||||
|
// Sets the debounce interval
|
||||||
|
void interval(uint16_t interval_millis);
|
||||||
|
|
||||||
|
// Updates the pin
|
||||||
|
// Returns 1 if the state changed
|
||||||
|
// Returns 0 if the state did not change
|
||||||
|
bool update();
|
||||||
|
|
||||||
|
// Returns the updated pin state
|
||||||
|
bool read();
|
||||||
|
|
||||||
|
// Returns the falling pin state
|
||||||
|
bool fell();
|
||||||
|
|
||||||
|
// Returns the rising pin state
|
||||||
|
bool rose();
|
||||||
|
|
||||||
|
// Partial compatibility for programs written with Bounce version 1
|
||||||
|
bool risingEdge() { return rose(); }
|
||||||
|
bool fallingEdge() { return fell(); }
|
||||||
|
Bounce(uint8_t pin, unsigned long interval_millis ) : Bounce() {
|
||||||
|
attach(pin);
|
||||||
|
interval(interval_millis);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
unsigned long previous_millis;
|
||||||
|
uint16_t interval_millis;
|
||||||
|
uint8_t state;
|
||||||
|
uint8_t pin;
|
||||||
|
virtual bool readCurrentState() { return digitalRead(pin); }
|
||||||
|
virtual void setPinMode(int pin, int mode) {
|
||||||
|
#if defined(ARDUINO_STM_NUCLEO_F103RB) || defined(ARDUINO_GENERIC_STM32F103C)
|
||||||
|
pinMode(pin, (WiringPinMode)mode);
|
||||||
|
#else
|
||||||
|
pinMode(pin, mode);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline void setStateFlag(const uint8_t flag) {state |= flag;}
|
||||||
|
inline void unsetStateFlag(const uint8_t flag) {state &= ~flag;}
|
||||||
|
inline void toggleStateFlag(const uint8_t flag) {state ^= flag;}
|
||||||
|
inline bool getStateFlag(const uint8_t flag) {return((state & flag) != 0);}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
Binary file not shown.
After Width: | Height: | Size: 9.1 KiB |
|
@ -0,0 +1 @@
|
||||||
|
Put the "Bounce2" folder in your Arduino or Wiring "libraries" folder.
|
|
@ -0,0 +1,20 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2013 thomasfredericks
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,37 @@
|
||||||
|
BOUNCE 2
|
||||||
|
=====================
|
||||||
|
|
||||||
|
Debouncing library for Arduino or Wiring
|
||||||
|
|
||||||
|
by Thomas Ouellet Fredericks
|
||||||
|
|
||||||
|
with contributions from:
|
||||||
|
|
||||||
|
Eric Lowry, Jim Schimpf, Tom Harkaway and Joachim Krüger.
|
||||||
|
|
||||||
|
|
||||||
|
HAVE A QUESTION?
|
||||||
|
=====================
|
||||||
|
Please post your questions here :
|
||||||
|
http://forum.arduino.cc/index.php?topic=266132.0
|
||||||
|
|
||||||
|
DOWNLOAD
|
||||||
|
=====================
|
||||||
|
|
||||||
|
Download the latest version (version 2) here :
|
||||||
|
|
||||||
|
https://github.com/thomasfredericks/Bounce2/archive/master.zip
|
||||||
|
|
||||||
|
|
||||||
|
DOCUMENTATION
|
||||||
|
=====================
|
||||||
|
|
||||||
|
The latest version (version 2) documentation can be found here :
|
||||||
|
|
||||||
|
https://github.com/thomasfredericks/Bounce2/wiki
|
||||||
|
|
||||||
|
|
||||||
|
ABOUT BOUNCE 1 (ORIGINAL VERSION)
|
||||||
|
=====================
|
||||||
|
|
||||||
|
The original version of Bounce (Bounce 1) is included but not supported anymore.
|
|
@ -0,0 +1,48 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
DESCRIPTION
|
||||||
|
====================
|
||||||
|
Simple example of the Bounce library that switches the debug LED when a button is pressed.
|
||||||
|
*/
|
||||||
|
// Include the Bounce2 library found here :
|
||||||
|
// https://github.com/thomasfredericks/Bounce2
|
||||||
|
#include <Bounce2.h>
|
||||||
|
|
||||||
|
#define BUTTON_PIN 2
|
||||||
|
#define LED_PIN 13
|
||||||
|
|
||||||
|
// Instantiate a Bounce object
|
||||||
|
Bounce debouncer = Bounce();
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
|
||||||
|
// Setup the button with an internal pull-up :
|
||||||
|
pinMode(BUTTON_PIN,INPUT_PULLUP);
|
||||||
|
|
||||||
|
// After setting up the button, setup the Bounce instance :
|
||||||
|
debouncer.attach(BUTTON_PIN);
|
||||||
|
debouncer.interval(5); // interval in ms
|
||||||
|
|
||||||
|
//Setup the LED :
|
||||||
|
pinMode(LED_PIN,OUTPUT);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// Update the Bounce instance :
|
||||||
|
debouncer.update();
|
||||||
|
|
||||||
|
// Get the updated value :
|
||||||
|
int value = debouncer.read();
|
||||||
|
|
||||||
|
// Turn on or off the LED as determined by the state :
|
||||||
|
if ( value == LOW ) {
|
||||||
|
digitalWrite(LED_PIN, HIGH );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
digitalWrite(LED_PIN, LOW );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
DESCRIPTION
|
||||||
|
====================
|
||||||
|
Simple example of the Bounce library that switches the debug LED when
|
||||||
|
either of 2 buttons are pressed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Include the Bounce2 library found here :
|
||||||
|
// https://github.com/thomasfredericks/Bounce2
|
||||||
|
#include <Bounce2.h>
|
||||||
|
|
||||||
|
#define BUTTON_PIN_1 2
|
||||||
|
#define BUTTON_PIN_2 3
|
||||||
|
|
||||||
|
|
||||||
|
#define LED_PIN 13
|
||||||
|
|
||||||
|
// Instantiate a Bounce object
|
||||||
|
Bounce debouncer1 = Bounce();
|
||||||
|
|
||||||
|
// Instantiate another Bounce object
|
||||||
|
Bounce debouncer2 = Bounce();
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
|
||||||
|
// Setup the first button with an internal pull-up :
|
||||||
|
pinMode(BUTTON_PIN_1,INPUT_PULLUP);
|
||||||
|
// After setting up the button, setup the Bounce instance :
|
||||||
|
debouncer1.attach(BUTTON_PIN_1);
|
||||||
|
debouncer1.interval(5); // interval in ms
|
||||||
|
|
||||||
|
// Setup the second button with an internal pull-up :
|
||||||
|
pinMode(BUTTON_PIN_2,INPUT_PULLUP);
|
||||||
|
// After setting up the button, setup the Bounce instance :
|
||||||
|
debouncer2.attach(BUTTON_PIN_2);
|
||||||
|
debouncer2.interval(5); // interval in ms
|
||||||
|
|
||||||
|
|
||||||
|
//Setup the LED :
|
||||||
|
pinMode(LED_PIN,OUTPUT);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// Update the Bounce instances :
|
||||||
|
debouncer1.update();
|
||||||
|
debouncer2.update();
|
||||||
|
|
||||||
|
// Get the updated value :
|
||||||
|
int value1 = debouncer1.read();
|
||||||
|
int value2 = debouncer2.read();
|
||||||
|
|
||||||
|
// Turn on the LED if either button is pressed :
|
||||||
|
if ( value1 == LOW || value2 == LOW ) {
|
||||||
|
digitalWrite(LED_PIN, HIGH );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
digitalWrite(LED_PIN, LOW );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
// Detect the falling edge of multiple buttons.
|
||||||
|
// Eight buttons with internal pullups.
|
||||||
|
// Toggles a LED when any button is pressed.
|
||||||
|
// Buttons on pins 2,3,4,5,6,7,8,9
|
||||||
|
|
||||||
|
// Include the Bounce2 library found here :
|
||||||
|
// https://github.com/thomasfredericks/Bounce2
|
||||||
|
#include <Bounce2.h>
|
||||||
|
|
||||||
|
#define LED_PIN 13
|
||||||
|
|
||||||
|
#define NUM_BUTTONS 8
|
||||||
|
const uint8_t BUTTON_PINS[NUM_BUTTONS] = {2, 3, 4, 5, 6, 7, 8, 9};
|
||||||
|
|
||||||
|
int ledState = LOW;
|
||||||
|
|
||||||
|
Bounce * buttons = new Bounce[NUM_BUTTONS];
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
|
||||||
|
for (int i = 0; i < NUM_BUTTONS; i++) {
|
||||||
|
buttons[i].attach( BUTTON_PINS[i] , INPUT_PULLUP ); //setup the bounce instance for the current button
|
||||||
|
buttons[i].interval(25); // interval in ms
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup the LED :
|
||||||
|
pinMode(LED_PIN, OUTPUT);
|
||||||
|
digitalWrite(LED_PIN, ledState);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
|
||||||
|
bool needToToggleLed = false;
|
||||||
|
|
||||||
|
|
||||||
|
for (int i = 0; i < NUM_BUTTONS; i++) {
|
||||||
|
// Update the Bounce instance :
|
||||||
|
buttons[i].update();
|
||||||
|
// If it fell, flag the need to toggle the LED
|
||||||
|
if ( buttons[i].fell() ) {
|
||||||
|
needToToggleLed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if a LED toggle has been flagged :
|
||||||
|
if ( needToToggleLed ) {
|
||||||
|
// Toggle LED state :
|
||||||
|
ledState = !ledState;
|
||||||
|
digitalWrite(LED_PIN, ledState);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
|
||||||
|
// Detect the falling edge
|
||||||
|
|
||||||
|
// Include the Bounce2 library found here :
|
||||||
|
// https://github.com/thomasfredericks/Bounce2
|
||||||
|
#include <Bounce2.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define BUTTON_PIN 2
|
||||||
|
#define LED_PIN 13
|
||||||
|
|
||||||
|
int ledState = LOW;
|
||||||
|
|
||||||
|
|
||||||
|
// Instantiate a Bounce object :
|
||||||
|
Bounce debouncer = Bounce();
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
|
||||||
|
// Setup the button with an internal pull-up :
|
||||||
|
pinMode(BUTTON_PIN,INPUT_PULLUP);
|
||||||
|
|
||||||
|
// After setting up the button, setup the Bounce instance :
|
||||||
|
debouncer.attach(BUTTON_PIN);
|
||||||
|
debouncer.interval(500);
|
||||||
|
|
||||||
|
// Setup the LED :
|
||||||
|
pinMode(LED_PIN,OUTPUT);
|
||||||
|
digitalWrite(LED_PIN,ledState);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
|
||||||
|
// Update the Bounce instance :
|
||||||
|
debouncer.update();
|
||||||
|
|
||||||
|
// Call code if Bounce fell (transition from HIGH to LOW) :
|
||||||
|
if ( debouncer.fell() ) {
|
||||||
|
|
||||||
|
// Toggle LED state :
|
||||||
|
ledState = !ledState;
|
||||||
|
digitalWrite(LED_PIN,ledState);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 47 KiB |
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
DESCRIPTION
|
||||||
|
====================
|
||||||
|
Reports through serial (57600 baud) the time since
|
||||||
|
a button press (transition from HIGH to LOW).
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Include the Bounce2 library found here :
|
||||||
|
// https://github.com/thomasfredericks/Bounce2
|
||||||
|
#include <Bounce2.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define BUTTON_PIN 2
|
||||||
|
#define LED_PIN 13
|
||||||
|
|
||||||
|
// Instantiate a Bounce object :
|
||||||
|
Bounce debouncer = Bounce();
|
||||||
|
|
||||||
|
unsigned long buttonPressTimeStamp;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
|
||||||
|
Serial.begin(57600);
|
||||||
|
|
||||||
|
// Setup the button with an internal pull-up :
|
||||||
|
pinMode(BUTTON_PIN,INPUT_PULLUP);
|
||||||
|
|
||||||
|
// After setting up the button, setup the Bounce instance :
|
||||||
|
debouncer.attach(BUTTON_PIN);
|
||||||
|
debouncer.interval(5);
|
||||||
|
|
||||||
|
// Setup the LED :
|
||||||
|
pinMode(LED_PIN,OUTPUT);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
|
||||||
|
// Update the Bounce instance :
|
||||||
|
debouncer.update();
|
||||||
|
|
||||||
|
// Call code if Bounce fell (transition from HIGH to LOW) :
|
||||||
|
if ( debouncer.fell() ) {;
|
||||||
|
|
||||||
|
Serial.println( millis()-buttonPressTimeStamp );
|
||||||
|
buttonPressTimeStamp = millis();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
DESCRIPTION
|
||||||
|
====================
|
||||||
|
Example of the bounce library that shows how to retrigger an event when a button is held down.
|
||||||
|
In this case, the debug LED will blink every 500 ms as long as the button is held down.
|
||||||
|
Open the Serial Monitor (57600 baud) for debug messages.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Include the Bounce2 library found here :
|
||||||
|
// https://github.com/thomasfredericks/Bounce2
|
||||||
|
#include <Bounce2.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define BUTTON_PIN 2
|
||||||
|
#define LED_PIN 13
|
||||||
|
|
||||||
|
// Instantiate a Bounce object
|
||||||
|
Bounce debouncer = Bounce();
|
||||||
|
|
||||||
|
int buttonState;
|
||||||
|
unsigned long buttonPressTimeStamp;
|
||||||
|
|
||||||
|
int ledState;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
|
||||||
|
Serial.begin(57600);
|
||||||
|
|
||||||
|
// Setup the button
|
||||||
|
pinMode(BUTTON_PIN,INPUT);
|
||||||
|
// Activate internal pull-up
|
||||||
|
digitalWrite(BUTTON_PIN,HIGH);
|
||||||
|
|
||||||
|
// After setting up the button, setup debouncer
|
||||||
|
debouncer.attach(BUTTON_PIN);
|
||||||
|
debouncer.interval(5);
|
||||||
|
|
||||||
|
//Setup the LED
|
||||||
|
pinMode(LED_PIN,OUTPUT);
|
||||||
|
digitalWrite(LED_PIN,ledState);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// Update the debouncer and get the changed state
|
||||||
|
boolean changed = debouncer.update();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if ( changed ) {
|
||||||
|
// Get the update value
|
||||||
|
int value = debouncer.read();
|
||||||
|
if ( value == HIGH) {
|
||||||
|
ledState = LOW;
|
||||||
|
digitalWrite(LED_PIN, ledState );
|
||||||
|
|
||||||
|
buttonState = 0;
|
||||||
|
Serial.println("Button released (state 0)");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ledState = HIGH;
|
||||||
|
digitalWrite(LED_PIN, ledState );
|
||||||
|
|
||||||
|
buttonState = 1;
|
||||||
|
Serial.println("Button pressed (state 1)");
|
||||||
|
buttonPressTimeStamp = millis();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( buttonState == 1 ) {
|
||||||
|
if ( millis() - buttonPressTimeStamp >= 500 ) {
|
||||||
|
buttonPressTimeStamp = millis();
|
||||||
|
if ( ledState == HIGH ) ledState = LOW;
|
||||||
|
else if ( ledState == LOW ) ledState = HIGH;
|
||||||
|
digitalWrite(LED_PIN, ledState );
|
||||||
|
Serial.println("Retriggering button");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
#######################################
|
||||||
|
# Syntax Coloring Map For Bounce2
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Datatypes (KEYWORD1)
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
Bounce KEYWORD1
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Methods and Functions (KEYWORD2)
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
update KEYWORD2
|
||||||
|
interval KEYWORD2
|
||||||
|
read KEYWORD2
|
||||||
|
attach KEYWORD2
|
||||||
|
rose KEYWORD2
|
||||||
|
fell KEYWORD2
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Instances (KEYWORD2)
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Constants (LITERAL1)
|
||||||
|
#######################################
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"name": "Bounce2",
|
||||||
|
"keywords": "bounce, signal, input, ouput",
|
||||||
|
"description": "Debouncing library for Arduino or Wiring",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/thomasfredericks/Bounce2.git"
|
||||||
|
},
|
||||||
|
"version": "2.41",
|
||||||
|
"exclude": [
|
||||||
|
"*.png",
|
||||||
|
"*.zip"
|
||||||
|
],
|
||||||
|
"frameworks": "arduino",
|
||||||
|
"platforms": "*"
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
name=Bounce2
|
||||||
|
version=2.41
|
||||||
|
author=Thomas O Fredericks <tof@t-o-f.info> with contributions fromEric Lowry, Jim Schimpf and Tom Harkaway
|
||||||
|
maintainer=Thomas O Fredericks <tof@t-o-f.info>
|
||||||
|
sentence=Debouncing library for Arduino and Wiring.
|
||||||
|
paragraph=Deboucing switches and toggles is important.
|
||||||
|
category=Signal Input/Output
|
||||||
|
url=https://github.com/thomasfredericks/Bounce2
|
||||||
|
architectures=*
|
|
@ -0,0 +1,308 @@
|
||||||
|
/*
|
||||||
|
DueTimer.cpp - Implementation of Timers defined on DueTimer.h
|
||||||
|
For instructions, go to https://github.com/ivanseidel/DueTimer
|
||||||
|
|
||||||
|
Created by Ivan Seidel Gomes, March, 2013.
|
||||||
|
Modified by Philipp Klaus, June 2013.
|
||||||
|
Thanks to stimmer (from Arduino forum), for coding the "timer soul" (Register stuff)
|
||||||
|
Released into the public domain.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#if defined(_SAM3XA_)
|
||||||
|
#include "DueTimer.h"
|
||||||
|
|
||||||
|
const DueTimer::Timer DueTimer::Timers[NUM_TIMERS] = {
|
||||||
|
{TC0,0,TC0_IRQn},
|
||||||
|
{TC0,1,TC1_IRQn},
|
||||||
|
{TC0,2,TC2_IRQn},
|
||||||
|
{TC1,0,TC3_IRQn},
|
||||||
|
{TC1,1,TC4_IRQn},
|
||||||
|
{TC1,2,TC5_IRQn},
|
||||||
|
{TC2,0,TC6_IRQn},
|
||||||
|
{TC2,1,TC7_IRQn},
|
||||||
|
{TC2,2,TC8_IRQn},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Fix for compatibility with Servo library
|
||||||
|
#ifdef USING_SERVO_LIB
|
||||||
|
// Set callbacks as used, allowing DueTimer::getAvailable() to work
|
||||||
|
void (*DueTimer::callbacks[NUM_TIMERS])() = {
|
||||||
|
(void (*)()) 1, // Timer 0 - Occupied
|
||||||
|
(void (*)()) 0, // Timer 1
|
||||||
|
(void (*)()) 1, // Timer 2 - Occupied
|
||||||
|
(void (*)()) 1, // Timer 3 - Occupied
|
||||||
|
(void (*)()) 1, // Timer 4 - Occupied
|
||||||
|
(void (*)()) 1, // Timer 5 - Occupied
|
||||||
|
(void (*)()) 0, // Timer 6
|
||||||
|
(void (*)()) 0, // Timer 7
|
||||||
|
(void (*)()) 0 // Timer 8
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
void (*DueTimer::callbacks[NUM_TIMERS])() = {};
|
||||||
|
#endif
|
||||||
|
double DueTimer::_frequency[NUM_TIMERS] = {-1,-1,-1,-1,-1,-1,-1,-1,-1};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Initializing all timers, so you can use them like this: Timer0.start();
|
||||||
|
*/
|
||||||
|
DueTimer Timer(0);
|
||||||
|
|
||||||
|
DueTimer Timer1(1);
|
||||||
|
// Fix for compatibility with Servo library
|
||||||
|
#ifndef USING_SERVO_LIB
|
||||||
|
DueTimer Timer0(0);
|
||||||
|
DueTimer Timer2(2);
|
||||||
|
DueTimer Timer3(3);
|
||||||
|
DueTimer Timer4(4);
|
||||||
|
DueTimer Timer5(5);
|
||||||
|
#endif
|
||||||
|
DueTimer Timer6(6);
|
||||||
|
DueTimer Timer7(7);
|
||||||
|
DueTimer Timer8(8);
|
||||||
|
|
||||||
|
DueTimer::DueTimer(unsigned short _timer) : timer(_timer){
|
||||||
|
/*
|
||||||
|
The constructor of the class DueTimer
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
DueTimer DueTimer::getAvailable(void){
|
||||||
|
/*
|
||||||
|
Return the first timer with no callback set
|
||||||
|
*/
|
||||||
|
|
||||||
|
for(int i = 0; i < NUM_TIMERS; i++){
|
||||||
|
if(!callbacks[i])
|
||||||
|
return DueTimer(i);
|
||||||
|
}
|
||||||
|
// Default, return Timer0;
|
||||||
|
return DueTimer(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
DueTimer& DueTimer::attachInterrupt(void (*isr)()){
|
||||||
|
/*
|
||||||
|
Links the function passed as argument to the timer of the object
|
||||||
|
*/
|
||||||
|
|
||||||
|
callbacks[timer] = isr;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
DueTimer& DueTimer::detachInterrupt(void){
|
||||||
|
/*
|
||||||
|
Links the function passed as argument to the timer of the object
|
||||||
|
*/
|
||||||
|
|
||||||
|
stop(); // Stop the currently running timer
|
||||||
|
|
||||||
|
callbacks[timer] = NULL;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
DueTimer& DueTimer::start(long microseconds){
|
||||||
|
/*
|
||||||
|
Start the timer
|
||||||
|
If a period is set, then sets the period and start the timer
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(microseconds > 0)
|
||||||
|
setPeriod(microseconds);
|
||||||
|
|
||||||
|
if(_frequency[timer] <= 0)
|
||||||
|
setFrequency(1);
|
||||||
|
|
||||||
|
NVIC_ClearPendingIRQ(Timers[timer].irq);
|
||||||
|
NVIC_EnableIRQ(Timers[timer].irq);
|
||||||
|
|
||||||
|
TC_Start(Timers[timer].tc, Timers[timer].channel);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
DueTimer& DueTimer::stop(void){
|
||||||
|
/*
|
||||||
|
Stop the timer
|
||||||
|
*/
|
||||||
|
|
||||||
|
NVIC_DisableIRQ(Timers[timer].irq);
|
||||||
|
|
||||||
|
TC_Stop(Timers[timer].tc, Timers[timer].channel);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t DueTimer::bestClock(double frequency, uint32_t& retRC){
|
||||||
|
/*
|
||||||
|
Pick the best Clock, thanks to Ogle Basil Hall!
|
||||||
|
|
||||||
|
Timer Definition
|
||||||
|
TIMER_CLOCK1 MCK / 2
|
||||||
|
TIMER_CLOCK2 MCK / 8
|
||||||
|
TIMER_CLOCK3 MCK / 32
|
||||||
|
TIMER_CLOCK4 MCK /128
|
||||||
|
*/
|
||||||
|
const struct {
|
||||||
|
uint8_t flag;
|
||||||
|
uint8_t divisor;
|
||||||
|
} clockConfig[] = {
|
||||||
|
{ TC_CMR_TCCLKS_TIMER_CLOCK1, 2 },
|
||||||
|
{ TC_CMR_TCCLKS_TIMER_CLOCK2, 8 },
|
||||||
|
{ TC_CMR_TCCLKS_TIMER_CLOCK3, 32 },
|
||||||
|
{ TC_CMR_TCCLKS_TIMER_CLOCK4, 128 }
|
||||||
|
};
|
||||||
|
float ticks;
|
||||||
|
float error;
|
||||||
|
int clkId = 3;
|
||||||
|
int bestClock = 3;
|
||||||
|
float bestError = 9.999e99;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ticks = (float) VARIANT_MCK / frequency / (float) clockConfig[clkId].divisor;
|
||||||
|
// error = abs(ticks - round(ticks));
|
||||||
|
error = clockConfig[clkId].divisor * abs(ticks - round(ticks)); // Error comparison needs scaling
|
||||||
|
if (error < bestError)
|
||||||
|
{
|
||||||
|
bestClock = clkId;
|
||||||
|
bestError = error;
|
||||||
|
}
|
||||||
|
} while (clkId-- > 0);
|
||||||
|
ticks = (float) VARIANT_MCK / frequency / (float) clockConfig[bestClock].divisor;
|
||||||
|
retRC = (uint32_t) round(ticks);
|
||||||
|
return clockConfig[bestClock].flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DueTimer& DueTimer::setFrequency(double frequency){
|
||||||
|
/*
|
||||||
|
Set the timer frequency (in Hz)
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Prevent negative frequencies
|
||||||
|
if(frequency <= 0) { frequency = 1; }
|
||||||
|
|
||||||
|
// Remember the frequency — see below how the exact frequency is reported instead
|
||||||
|
//_frequency[timer] = frequency;
|
||||||
|
|
||||||
|
// Get current timer configuration
|
||||||
|
Timer t = Timers[timer];
|
||||||
|
|
||||||
|
uint32_t rc = 0;
|
||||||
|
uint8_t clock;
|
||||||
|
|
||||||
|
// Tell the Power Management Controller to disable
|
||||||
|
// the write protection of the (Timer/Counter) registers:
|
||||||
|
pmc_set_writeprotect(false);
|
||||||
|
|
||||||
|
// Enable clock for the timer
|
||||||
|
pmc_enable_periph_clk((uint32_t)t.irq);
|
||||||
|
|
||||||
|
// Find the best clock for the wanted frequency
|
||||||
|
clock = bestClock(frequency, rc);
|
||||||
|
|
||||||
|
switch (clock) {
|
||||||
|
case TC_CMR_TCCLKS_TIMER_CLOCK1:
|
||||||
|
_frequency[timer] = (double)VARIANT_MCK / 2.0 / (double)rc;
|
||||||
|
break;
|
||||||
|
case TC_CMR_TCCLKS_TIMER_CLOCK2:
|
||||||
|
_frequency[timer] = (double)VARIANT_MCK / 8.0 / (double)rc;
|
||||||
|
break;
|
||||||
|
case TC_CMR_TCCLKS_TIMER_CLOCK3:
|
||||||
|
_frequency[timer] = (double)VARIANT_MCK / 32.0 / (double)rc;
|
||||||
|
break;
|
||||||
|
default: // TC_CMR_TCCLKS_TIMER_CLOCK4
|
||||||
|
_frequency[timer] = (double)VARIANT_MCK / 128.0 / (double)rc;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up the Timer in waveform mode which creates a PWM
|
||||||
|
// in UP mode with automatic trigger on RC Compare
|
||||||
|
// and sets it up with the determined internal clock as clock input.
|
||||||
|
TC_Configure(t.tc, t.channel, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | clock);
|
||||||
|
// Reset counter and fire interrupt when RC value is matched:
|
||||||
|
TC_SetRC(t.tc, t.channel, rc);
|
||||||
|
// Enable the RC Compare Interrupt...
|
||||||
|
t.tc->TC_CHANNEL[t.channel].TC_IER=TC_IER_CPCS;
|
||||||
|
// ... and disable all others.
|
||||||
|
t.tc->TC_CHANNEL[t.channel].TC_IDR=~TC_IER_CPCS;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
DueTimer& DueTimer::setPeriod(unsigned long microseconds){
|
||||||
|
/*
|
||||||
|
Set the period of the timer (in microseconds)
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Convert period in microseconds to frequency in Hz
|
||||||
|
double frequency = 1000000.0 / microseconds;
|
||||||
|
setFrequency(frequency);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
double DueTimer::getFrequency(void) const {
|
||||||
|
/*
|
||||||
|
Get current time frequency
|
||||||
|
*/
|
||||||
|
|
||||||
|
return _frequency[timer];
|
||||||
|
}
|
||||||
|
|
||||||
|
long DueTimer::getPeriod(void) const {
|
||||||
|
/*
|
||||||
|
Get current time period
|
||||||
|
*/
|
||||||
|
|
||||||
|
return 1.0/getFrequency()*1000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Implementation of the timer callbacks defined in
|
||||||
|
arduino-1.5.2/hardware/arduino/sam/system/CMSIS/Device/ATMEL/sam3xa/include/sam3x8e.h
|
||||||
|
*/
|
||||||
|
// Fix for compatibility with Servo library
|
||||||
|
#ifndef USING_SERVO_LIB
|
||||||
|
void TC0_Handler(void){
|
||||||
|
TC_GetStatus(TC0, 0);
|
||||||
|
DueTimer::callbacks[0]();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
void TC1_Handler(void){
|
||||||
|
TC_GetStatus(TC0, 1);
|
||||||
|
DueTimer::callbacks[1]();
|
||||||
|
}
|
||||||
|
// Fix for compatibility with Servo library
|
||||||
|
#ifndef USING_SERVO_LIB
|
||||||
|
void TC2_Handler(void){
|
||||||
|
TC_GetStatus(TC0, 2);
|
||||||
|
DueTimer::callbacks[2]();
|
||||||
|
}
|
||||||
|
void TC3_Handler(void){
|
||||||
|
TC_GetStatus(TC1, 0);
|
||||||
|
DueTimer::callbacks[3]();
|
||||||
|
}
|
||||||
|
void TC4_Handler(void){
|
||||||
|
TC_GetStatus(TC1, 1);
|
||||||
|
DueTimer::callbacks[4]();
|
||||||
|
}
|
||||||
|
void TC5_Handler(void){
|
||||||
|
TC_GetStatus(TC1, 2);
|
||||||
|
DueTimer::callbacks[5]();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
void TC6_Handler(void){
|
||||||
|
TC_GetStatus(TC2, 0);
|
||||||
|
DueTimer::callbacks[6]();
|
||||||
|
}
|
||||||
|
void TC7_Handler(void){
|
||||||
|
TC_GetStatus(TC2, 1);
|
||||||
|
DueTimer::callbacks[7]();
|
||||||
|
}
|
||||||
|
void TC8_Handler(void){
|
||||||
|
TC_GetStatus(TC2, 2);
|
||||||
|
DueTimer::callbacks[8]();
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,109 @@
|
||||||
|
/*
|
||||||
|
DueTimer.h - DueTimer header file, definition of methods and attributes...
|
||||||
|
For instructions, go to https://github.com/ivanseidel/DueTimer
|
||||||
|
|
||||||
|
Created by Ivan Seidel Gomes, March, 2013.
|
||||||
|
Modified by Philipp Klaus, June 2013.
|
||||||
|
Released into the public domain.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __arm__
|
||||||
|
|
||||||
|
#ifndef DueTimer_h
|
||||||
|
#define DueTimer_h
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
This fixes compatibility for Arduono Servo Library.
|
||||||
|
Uncomment to make it compatible.
|
||||||
|
|
||||||
|
Note that:
|
||||||
|
+ Timers: 0,2,3,4,5 WILL NOT WORK, and will
|
||||||
|
neither be accessible by Timer0,...
|
||||||
|
*/
|
||||||
|
// #define USING_SERVO_LIB true
|
||||||
|
|
||||||
|
#ifdef USING_SERVO_LIB
|
||||||
|
#warning "HEY! You have set flag USING_SERVO_LIB. Timer0, 2,3,4 and 5 are not available"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#define NUM_TIMERS 9
|
||||||
|
|
||||||
|
class DueTimer
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// Represents the timer id (index for the array of Timer structs)
|
||||||
|
const unsigned short timer;
|
||||||
|
|
||||||
|
// Stores the object timer frequency
|
||||||
|
// (allows to access current timer period and frequency):
|
||||||
|
static double _frequency[NUM_TIMERS];
|
||||||
|
|
||||||
|
// Picks the best clock to lower the error
|
||||||
|
static uint8_t bestClock(double frequency, uint32_t& retRC);
|
||||||
|
|
||||||
|
// Make Interrupt handlers friends, so they can use callbacks
|
||||||
|
friend void TC0_Handler(void);
|
||||||
|
friend void TC1_Handler(void);
|
||||||
|
friend void TC2_Handler(void);
|
||||||
|
friend void TC3_Handler(void);
|
||||||
|
friend void TC4_Handler(void);
|
||||||
|
friend void TC5_Handler(void);
|
||||||
|
friend void TC6_Handler(void);
|
||||||
|
friend void TC7_Handler(void);
|
||||||
|
friend void TC8_Handler(void);
|
||||||
|
|
||||||
|
static void (*callbacks[NUM_TIMERS])();
|
||||||
|
|
||||||
|
struct Timer
|
||||||
|
{
|
||||||
|
Tc *tc;
|
||||||
|
uint32_t channel;
|
||||||
|
IRQn_Type irq;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Store timer configuration (static, as it's fixed for every object)
|
||||||
|
static const Timer Timers[NUM_TIMERS];
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
static DueTimer getAvailable(void);
|
||||||
|
|
||||||
|
DueTimer(unsigned short _timer);
|
||||||
|
DueTimer& attachInterrupt(void (*isr)());
|
||||||
|
DueTimer& detachInterrupt(void);
|
||||||
|
DueTimer& start(long microseconds = -1);
|
||||||
|
DueTimer& stop(void);
|
||||||
|
DueTimer& setFrequency(double frequency);
|
||||||
|
DueTimer& setPeriod(unsigned long microseconds);
|
||||||
|
|
||||||
|
double getFrequency(void) const;
|
||||||
|
long getPeriod(void) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Just to call Timer.getAvailable instead of Timer::getAvailable() :
|
||||||
|
extern DueTimer Timer;
|
||||||
|
|
||||||
|
extern DueTimer Timer1;
|
||||||
|
// Fix for compatibility with Servo library
|
||||||
|
#ifndef USING_SERVO_LIB
|
||||||
|
extern DueTimer Timer0;
|
||||||
|
extern DueTimer Timer2;
|
||||||
|
extern DueTimer Timer3;
|
||||||
|
extern DueTimer Timer4;
|
||||||
|
extern DueTimer Timer5;
|
||||||
|
#endif
|
||||||
|
extern DueTimer Timer6;
|
||||||
|
extern DueTimer Timer7;
|
||||||
|
extern DueTimer Timer8;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error Oops! Trying to include DueTimer on another device?
|
||||||
|
#endif
|
|
@ -0,0 +1,21 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2015 Ivan Seidel
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
|
@ -0,0 +1,119 @@
|
||||||
|
# DueTimer
|
||||||
|
|
||||||
|
Timer Library to work with Arduino DUE
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
1. [Download](https://github.com/ivanseidel/DueTimer/releases) the Latest release from GitHub.
|
||||||
|
2. Unzip and modify the Folder name to "DueTimer" (Remove the '-version')
|
||||||
|
3. Paste the modified folder on your Library folder (On your `Libraries` folder inside Sketchbooks or Arduino software).
|
||||||
|
4. Re-open Arduino Software
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
To call a function `handler` every `1000` microseconds:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
Timer3.attachInterrupt(handler).start(1000);
|
||||||
|
// or:
|
||||||
|
Timer3.attachInterrupt(handler).setPeriod(1000).start();
|
||||||
|
// or, to select whichever available timer:
|
||||||
|
Timer.getAvailable().attachInterrupt(handler).start(1000);
|
||||||
|
```
|
||||||
|
|
||||||
|
To call a function `handler` `10` times a second:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
Timer3.attachInterrupt(handler).setFrequency(10).start();
|
||||||
|
```
|
||||||
|
|
||||||
|
In case you need to stop a timer, just do like this:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
Timer3.stop();
|
||||||
|
```
|
||||||
|
|
||||||
|
And to continue running:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
Timer3.start();
|
||||||
|
```
|
||||||
|
|
||||||
|
There are `9` Timer objects already instantiated for you:
|
||||||
|
`Timer0`, `Timer1`, `Timer2`, `Timer3`, `Timer4`, `Timer5`, `Timer6`, `Timer7` and `Timer8`.
|
||||||
|
|
||||||
|
### TIPs and Warnings
|
||||||
|
|
||||||
|
```c++
|
||||||
|
Timer4.attachInterrupt(handler).setFrequency(10).start();
|
||||||
|
// Is the same as:
|
||||||
|
Timer4.attachInterrupt(handler);
|
||||||
|
Timer4.setFrequency(10);
|
||||||
|
Timer4.start();
|
||||||
|
|
||||||
|
// To create a custom timer, refer to:
|
||||||
|
DueTimer myTimer = DueTimer(0); // Creates a Timer 0 object.
|
||||||
|
DueTimer myTimer = DueTimer(3); // Creates a Timer 3 object.
|
||||||
|
DueTimer myTimer = DueTimer(t); // Creates a Timer t object.
|
||||||
|
// Note: Maximum t allowed is 8, as there is only 9 timers [0..8];
|
||||||
|
|
||||||
|
Timer1.attachInterrupt(handler1).start(10);
|
||||||
|
Timer1.attachInterrupt(handler2).start(10);
|
||||||
|
DueTimer myTimer = DueTimer(1);
|
||||||
|
myTimer.attachInterrupt(handler3).start(20);
|
||||||
|
// Will run only handle3, on Timer 1 (You are just overriding the callback)
|
||||||
|
|
||||||
|
Timer.getAvailable().attachInterrupt(callback1).start(10);
|
||||||
|
// Start timer on first available timer
|
||||||
|
DueTimer::getAvailable().attachInterrupt(callback2).start(10);
|
||||||
|
// Start timer on second available timer
|
||||||
|
// And so on...
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compatibility with Servo.h
|
||||||
|
|
||||||
|
Because Servo Library uses the same callbacks of DueTimer, we provides a custom solution for working with both of them. However, Timers 0,2,3,4 and 5 will not Work anymore.
|
||||||
|
|
||||||
|
You will need uncommend the line in `DueTimer.h` in `DueTimer` folder inside the `Libraries` folder. Uncomment the following line in `DueTimer.h`:
|
||||||
|
|
||||||
|
```
|
||||||
|
#define USING_SERVO_LIB true
|
||||||
|
```
|
||||||
|
|
||||||
|
## Library Reference
|
||||||
|
|
||||||
|
### You should know:
|
||||||
|
|
||||||
|
- `getAvailable()` - Get the first available Timer.
|
||||||
|
|
||||||
|
- `attachInterrupt(void (*isr)())` - Attach a interrupt (callback function) for the timer of the object.
|
||||||
|
|
||||||
|
- `detachInterrupt()` - Detach current callback of timer.
|
||||||
|
|
||||||
|
- `start(long microseconds = -1)` - Start the timer with an optional period parameter.
|
||||||
|
|
||||||
|
- `stop()` - Stop the timer
|
||||||
|
|
||||||
|
- `setFrequency(long frequency)` - Set the timer frequency
|
||||||
|
|
||||||
|
- `long getFrequency()` - Get the timer frequency
|
||||||
|
|
||||||
|
- `setPeriod(long microseconds)` - Set the timer period (in microseconds)
|
||||||
|
|
||||||
|
- `long getPeriod()` - Get the timer period (in microseconds)
|
||||||
|
|
||||||
|
### You don't need to know:
|
||||||
|
|
||||||
|
- `unsigned short timer` - Stores the object timer id (to access Timers struct array).
|
||||||
|
|
||||||
|
- `DueTimer(unsigned short _timer)` - Instantiate a new DueTimer object for Timer _timer (NOTE: All objects are already instantiated!).
|
||||||
|
|
||||||
|
- `static const Timer Timers[]` - Stores all timers information
|
||||||
|
|
||||||
|
- `static void (*callbacks[])()` - Stores all callbacks for all timers
|
||||||
|
|
||||||
|
|
||||||
|
### Hardware Information
|
||||||
|
|
||||||
|
More information on the Timer Counter module of the µC on the Arduino Due
|
||||||
|
can be found in the documentation file [TimerCounter](TimerCounter.md).
|
|
@ -0,0 +1,106 @@
|
||||||
|
# The Timer Counter blocks of Arduino Due's AT91SAM3X8E
|
||||||
|
|
||||||
|
The AT91SAM3X8E embedds nine general-purpose 32-bit timers/counters. They are organized in three blocks (`TC0`, `TC1`, `TC2`) each containing three channels (`0`, `1`, `2`).
|
||||||
|
Each block and channel has input lines for their clock and input/output lines which can be used in different ways, such as PWM pins etc.
|
||||||
|
|
||||||
|
|
||||||
|
### Resources
|
||||||
|
|
||||||
|
Information on the Timer Counter and its I/O signals pins can be found here:
|
||||||
|
|
||||||
|
* Section **37 Timer Counter (TC)** in the [Atmel SAM3X Datasheet][]
|
||||||
|
You find this chapter on the pages 869 through 920. It explains in detail how to operate the counter in different modes and has nice diagrams that show you how the clock input works and how to set up interrupts based on counter values etc.
|
||||||
|
* [Arduino Due's SAM3X Pin Mapping][] and the
|
||||||
|
* [Arduino Due pinout diagram][].
|
||||||
|
|
||||||
|
### The Timer Counter Signals / Pins
|
||||||
|
|
||||||
|
Many of the I/O lines of the Timer Counter are directly accessible on pin headers of the Arduino Due board. This section helps you to find out which of them are and which are not.
|
||||||
|
|
||||||
|
In order to actually connect those signals (`TCLKx`, `TIOAx` and `TIOBx`) to the pins on the Arduino Due, you must tell the Parallel I/O Controllers (`PIOA`, `PIOB`, `PIOC` or `PIOD`) to set up their mux (multiplexer) accordingly.<br />
|
||||||
|
A useful resource to find out how to set the PIOs is
|
||||||
|
[Arduino's const array of PinDescriptions](https://github.com/arduino/Arduino/blob/ide-1.5.x/hardware/arduino/sam/variants/arduino_due_x/variant.cpp#L117) and the
|
||||||
|
[definition of PinDescription](https://github.com/arduino/Arduino/blob/ide-1.5.x/hardware/arduino/sam/cores/arduino/Arduino.h#L166), the data type of its entries.
|
||||||
|
|
||||||
|
#### Overview of the I/O lines of the Timer Counter
|
||||||
|
|
||||||
|
Here is a table of the Timer Counter channels and their `TCLKx` (external clock input), `TIOAx` (I/O Line _A_) and `TIOBx` (I/O Line _B_) signals:
|
||||||
|
|
||||||
|
Instance | TC | Channel| External Clock Input | I/O Line A | I/O Line B
|
||||||
|
---------|-----|--------|----------------------|------------|-----------
|
||||||
|
T0 | TC0 | 0 | TCLK0 | TIOA0 | TIOB0
|
||||||
|
T1 | TC0 | 1 | TCLK1 | TIOA1 | TIOB1
|
||||||
|
T2 | TC0 | 2 | TCLK2 | TIOA2 | TIOB2
|
||||||
|
T3 | TC1 | 0 | TCLK3 | TIOA3 | TIOB3
|
||||||
|
T4 | TC1 | 1 | TCLK4 | TIOA4 | TIOB4
|
||||||
|
T5 | TC1 | 2 | TCLK5 | TIOA5 | TIOB5
|
||||||
|
T6 | TC2 | 0 | TCLK6 | TIOA6 | TIOB6
|
||||||
|
T7 | TC2 | 1 | TCLK7 | TIOA7 | TIOB7
|
||||||
|
T8 | TC2 | 2 | TCLK8 | TIOA8 | TIOB8
|
||||||
|
|
||||||
|
##### TCLKx
|
||||||
|
|
||||||
|
Here is how the **external clock inputs** are routed to pins on the Arduino Due board:
|
||||||
|
|
||||||
|
Clock Input | Port Pin of µC | Pin on Arduino Due Board
|
||||||
|
------------|------------|-----------------------------
|
||||||
|
TCLK0 | PB 26 | Digital Pin 22
|
||||||
|
TCLK1 | PA 4 | Analog In 5
|
||||||
|
TCLK2 | PA 7 | Digital Pin 31
|
||||||
|
TCLK3 | PA 22 | Analog In 3
|
||||||
|
TCLK4 | PA 23 | Analog In 2
|
||||||
|
TCLK5 | PB 16 | DAC1
|
||||||
|
TCLK6 | PC 27 | /
|
||||||
|
TCLK7 | PC 30 | LED "RX"
|
||||||
|
TCLK8 | PD 9 | Digital Pin 30
|
||||||
|
|
||||||
|
##### TIOAx
|
||||||
|
|
||||||
|
Here is how the **I/O Lines _A_** are routed to pins on the Arduino Due board:
|
||||||
|
|
||||||
|
I/O Line A | Port Pin of µC | Pin on Arduino Due Board
|
||||||
|
-----------|----------------|-----------------------------
|
||||||
|
TIOA0 | PB 25 | Digital Pin 2
|
||||||
|
TIOA1 | PA 2 | Analog In 7
|
||||||
|
TIOA2 | PA 5 | /
|
||||||
|
TIOA3 | PE 9 | /
|
||||||
|
TIOA4 | PE 11 | /
|
||||||
|
TIOA5 | PE 13 | /
|
||||||
|
TIOA6 | PC 25 | Digital Pin 5
|
||||||
|
TIOA7 | PC 28 | Digital Pin 3
|
||||||
|
TIOA8 | PD 7 | Digital Pin 11
|
||||||
|
|
||||||
|
##### TIOBx
|
||||||
|
|
||||||
|
Here is how the **I/O Lines _B_** are routed to pins on the Arduino Due board:
|
||||||
|
|
||||||
|
I/O Line B|Port Pin of µC| Pin on Arduino Due Board
|
||||||
|
----------|--------------|------------------------------------------
|
||||||
|
TIOB0 | PB 27 | Digital Pin 13 / Amber LED "L"
|
||||||
|
TIOB1 | PA 3 | Analog In 6
|
||||||
|
TIOB2 | PA 6 | Analog In 4
|
||||||
|
TIOB3 | PE 10 | /
|
||||||
|
TIOB4 | PE 12 | /
|
||||||
|
TIOB5 | PE 14 | /
|
||||||
|
TIOB6 | PC 26 | Digital Pin 4 (also connected to PA29)
|
||||||
|
TIOB7 | PC 29 | Digital Pin 10 (also connected to PA28)
|
||||||
|
TIOB8 | PD 8 | Digital Pin 12
|
||||||
|
|
||||||
|
#### TC Clock Source Selection
|
||||||
|
|
||||||
|
The *clock of the counters* can be set very flexibly to internal or external signals. To *use the channel as a timer*, it makes sense to connect its clock input to an internal timer clock. Here are the options:
|
||||||
|
|
||||||
|
Name | Definition
|
||||||
|
-------------|-----------
|
||||||
|
TIMER_CLOCK1 | `MCK / 2`
|
||||||
|
TIMER_CLOCK2 | `MCK / 8`
|
||||||
|
TIMER_CLOCK3 | `MCK / 32`
|
||||||
|
TIMER_CLOCK4 | `MCK / 128`
|
||||||
|
TIMER_CLOCK5 | `SLCK`
|
||||||
|
|
||||||
|
|
||||||
|
Where `MCK` is the master clock (84 MHz for the Arduino Due) and SLCK is the slow clock (which can be clocked at 32.768 kHz by Y2 on the Arduino Due).
|
||||||
|
|
||||||
|
[Atmel SAM3X Datasheet]: http://www.atmel.com/Images/Atmel-11057-32-bit-Cortex-M3-Microcontroller-SAM3X-SAM3A_Datasheet.pdf
|
||||||
|
[Arduino Due's SAM3X Pin Mapping]: http://arduino.cc/en/Hacking/PinMappingSAM3X
|
||||||
|
[Arduino Due pinout diagram]: http://www.robgray.com/temp/Due-pinout.pdf
|
|
@ -0,0 +1,60 @@
|
||||||
|
#include <DueTimer.h>
|
||||||
|
|
||||||
|
void playVideogame(){
|
||||||
|
Serial.println("[- ] I'm playing Videogame!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void drinkWater(){
|
||||||
|
Serial.println("[ - ] I'm driking water!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void makeSushi(){
|
||||||
|
Serial.println("[ - ] Slicing Salmon...");
|
||||||
|
}
|
||||||
|
|
||||||
|
void singOnShower(){
|
||||||
|
Serial.println("[ - ] Hello World! Hello world!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void studyMath(){
|
||||||
|
int x = random(1, 40), y = random(1,40);
|
||||||
|
Serial.print("[ - ] ");
|
||||||
|
Serial.print(x); Serial.print(" x "); Serial.print(y); Serial.print(" = ");
|
||||||
|
Serial.println(x*y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void watchStarTrek(){
|
||||||
|
Serial.println("[ - ] Long live and prosper \\\\//_");
|
||||||
|
}
|
||||||
|
|
||||||
|
void eatSushi(){
|
||||||
|
Serial.println("[ - ] ...");
|
||||||
|
}
|
||||||
|
|
||||||
|
void readTextMessage(){
|
||||||
|
Serial.println("[ - ] [Unlock ---->>]");
|
||||||
|
}
|
||||||
|
|
||||||
|
void goToSleep(){
|
||||||
|
Serial.println("[ -] zzzzzz");
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup(){
|
||||||
|
Serial.begin(9600);
|
||||||
|
|
||||||
|
Timer.getAvailable().attachInterrupt(playVideogame).start(); delay(50);
|
||||||
|
Timer.getAvailable().attachInterrupt(drinkWater).start(); delay(50);
|
||||||
|
Timer.getAvailable().attachInterrupt(makeSushi).start(); delay(50);
|
||||||
|
Timer.getAvailable().attachInterrupt(singOnShower).start(); delay(50);
|
||||||
|
Timer.getAvailable().attachInterrupt(studyMath).start(); delay(50);
|
||||||
|
Timer.getAvailable().attachInterrupt(watchStarTrek).start(); delay(50);
|
||||||
|
Timer.getAvailable().attachInterrupt(eatSushi).start(); delay(50);
|
||||||
|
Timer.getAvailable().attachInterrupt(readTextMessage).start(); delay(50);
|
||||||
|
Timer.getAvailable().attachInterrupt(goToSleep).start(); delay(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop(){
|
||||||
|
while(1){
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
#include <DueTimer.h>
|
||||||
|
|
||||||
|
void firstHandler(){
|
||||||
|
Serial.println("[- ] First Handler!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void secondHandler(){
|
||||||
|
Serial.println("[ - ] Second Handler!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void thirdHandler(){
|
||||||
|
Serial.println("[ -] Third Handler!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup(){
|
||||||
|
Serial.begin(9600);
|
||||||
|
|
||||||
|
Timer3.attachInterrupt(firstHandler).start(500000); // Every 500ms
|
||||||
|
Timer4.attachInterrupt(secondHandler).setFrequency(1).start();
|
||||||
|
Timer5.attachInterrupt(thirdHandler).setFrequency(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop(){
|
||||||
|
delay(2000);
|
||||||
|
Timer5.start();
|
||||||
|
|
||||||
|
delay(2000);
|
||||||
|
Timer5.stop();
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
#include <DueTimer.h>
|
||||||
|
|
||||||
|
int myLed = 13;
|
||||||
|
|
||||||
|
bool ledOn = false;
|
||||||
|
void myHandler(){
|
||||||
|
ledOn = !ledOn;
|
||||||
|
|
||||||
|
digitalWrite(myLed, ledOn); // Led on, off, on, off...
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup(){
|
||||||
|
pinMode(myLed, OUTPUT);
|
||||||
|
|
||||||
|
Timer3.attachInterrupt(myHandler);
|
||||||
|
Timer3.start(50000); // Calls every 50ms
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop(){
|
||||||
|
|
||||||
|
while(1){
|
||||||
|
// I'm stuck in here! help me...
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
DueTimer KEYWORD2
|
||||||
|
start KEYWORD2
|
||||||
|
stop KEYWORD2
|
||||||
|
attachInterrupt KEYWORD2
|
||||||
|
detachInterrupt KEYWORD2
|
||||||
|
setPeriod KEYWORD2
|
||||||
|
setFrequency KEYWORD2
|
||||||
|
getFrequency KEYWORD2
|
||||||
|
getPeriod KEYWORD2
|
||||||
|
|
||||||
|
Timer KEYWORD1
|
||||||
|
Timer0 KEYWORD1
|
||||||
|
Timer1 KEYWORD1
|
||||||
|
Timer2 KEYWORD1
|
||||||
|
Timer3 KEYWORD1
|
||||||
|
Timer4 KEYWORD1
|
||||||
|
Timer5 KEYWORD1
|
||||||
|
Timer6 KEYWORD1
|
||||||
|
Timer7 KEYWORD1
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"name": "DueTimer",
|
||||||
|
"keywords": "timer",
|
||||||
|
"description": "Timer Library fully implemented for Arduino DUE",
|
||||||
|
"repository":
|
||||||
|
{
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/ivanseidel/DueTimer.git"
|
||||||
|
},
|
||||||
|
"frameworks": "arduino",
|
||||||
|
"platforms": "atmelsam"
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
name=DueTimer
|
||||||
|
version=1.4.7
|
||||||
|
author=Ivan Seidel <ivanseidel@gmail.com>
|
||||||
|
maintainer=Ivan Seidel <ivanseidel@gmail.com>
|
||||||
|
sentence=Timer Library fully implemented for Arduino DUE
|
||||||
|
paragraph=There are 9 Timer objects already instantiated for you: Timer0, Timer1, Timer2, Timer3, Timer4, Timer5, Timer6, Timer7 and Timer8.
|
||||||
|
category=Timing
|
||||||
|
url=https://github.com/ivanseidel/DueTimer
|
||||||
|
architectures=sam
|
|
@ -0,0 +1,406 @@
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "EDIPTFT.h"
|
||||||
|
#include "FT_2018_STW_CAN.h"
|
||||||
|
#include "FT18_STW_INIT.h"
|
||||||
|
#include "FT18_STW_DISPLAY.h"
|
||||||
|
|
||||||
|
EDIPTFT tft(true,false);
|
||||||
|
String bezeichnungen[]={"T_mot","T_oil","P_oil","% fa","U_batt","P_wat","T_air",
|
||||||
|
"P_b_front","P_b_rear","Error Type","Speed_fl","Speed_fr","Speed"};
|
||||||
|
//"Drehzahl","P_fuel","Index"
|
||||||
|
int vergleichsindex;
|
||||||
|
int sizeaalt;
|
||||||
|
int sizeaneu;
|
||||||
|
int sizebalt;
|
||||||
|
int sizebneu;
|
||||||
|
int sizecalt;
|
||||||
|
int sizecneu;
|
||||||
|
int sizedalt;
|
||||||
|
int sizedneu;
|
||||||
|
int sizeealt;
|
||||||
|
int sizeeneu;
|
||||||
|
uint8_t clearcounter = 56;
|
||||||
|
uint8_t trcalt = Stw_data.trc;
|
||||||
|
uint8_t modealt = Stw_data.mode;
|
||||||
|
uint8_t trccounter;// = Stw_data.trc;
|
||||||
|
uint8_t modecounter;// = Stw_data.mode;
|
||||||
|
bool trctimer;
|
||||||
|
bool modetimer;
|
||||||
|
int led_s[] = {led1,led2,led3,led4,led5,led6,led7,led8,led9,led10,led11,led12,led13,led14,led15,led16};
|
||||||
|
unsigned long poiltimer;
|
||||||
|
unsigned long tmottimer;
|
||||||
|
unsigned long toiltimer;
|
||||||
|
bool poilbool = true;
|
||||||
|
bool tmotbool = true;
|
||||||
|
bool toilbool = true;
|
||||||
|
|
||||||
|
void init_display() {
|
||||||
|
pinMode(writeprotect, OUTPUT);
|
||||||
|
digitalWrite(writeprotect, HIGH);
|
||||||
|
pinMode(reset, OUTPUT);
|
||||||
|
pinMode(disp_cs, OUTPUT);
|
||||||
|
pinMode(MOSI, OUTPUT);
|
||||||
|
pinMode(MISO, OUTPUT);
|
||||||
|
//pinMode(CLK, INPUT);
|
||||||
|
digitalWrite(disp_cs, HIGH);
|
||||||
|
digitalWrite(MOSI, HIGH);
|
||||||
|
digitalWrite(MISO, HIGH);
|
||||||
|
digitalWrite(reset, LOW);
|
||||||
|
//edip.smallProtoSelect(7);
|
||||||
|
//edip.setNewColor(EA_GREY, 0xe3, 0xe3,0xe3); // redefine r-g-b-values of EA_GREY
|
||||||
|
//edip.drawImage(0,50,FASTTUBE_LOGO_PNG);
|
||||||
|
digitalWrite(reset,HIGH);
|
||||||
|
tft.begin(115200); // start display communication
|
||||||
|
/*int h = 20;
|
||||||
|
char charh[2];
|
||||||
|
String strh = String(h);
|
||||||
|
strh.toCharArray(charh,2);
|
||||||
|
tft.DisplayLight(charh);*/
|
||||||
|
tft.cursorOn(false);
|
||||||
|
tft.terminalOn(false);
|
||||||
|
tft.setDisplayColor(EA_WHITE,EA_BLACK);
|
||||||
|
tft.setTextColor(EA_WHITE,EA_BLACK);
|
||||||
|
//tft.setTextFont('4');
|
||||||
|
tft.setTextSize(5,8);
|
||||||
|
tft.clear();
|
||||||
|
//tft.displayLight('30');
|
||||||
|
tft.drawText(0, 14, 'C', "FaSTTUBe"); //draw some text
|
||||||
|
//tft.loadImage(0,0,1);
|
||||||
|
//delay(2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
double get_value(int a){
|
||||||
|
double value;
|
||||||
|
if (a == 0){
|
||||||
|
value = Vehicle_data.gear;
|
||||||
|
//}else if (a == 11){
|
||||||
|
// value = Stw_data.i;
|
||||||
|
//}else if (a == 1){
|
||||||
|
// value = Vehicle_data.revol/2;
|
||||||
|
}else if (a == 1){
|
||||||
|
value = Vehicle_data.t_mot-40;
|
||||||
|
}else if (a == 5){
|
||||||
|
value = 0.0706949*Vehicle_data.u_batt;
|
||||||
|
}else if (a == 7){
|
||||||
|
value = Vehicle_data.t_air-40;
|
||||||
|
}else if(a == 10){
|
||||||
|
value = Stw_data.error_type;
|
||||||
|
}else if (a == 2){
|
||||||
|
value = Vehicle_data.t_oil-40;
|
||||||
|
}else if (a == 6){
|
||||||
|
value = 0.0514*Vehicle_data.p_wat;
|
||||||
|
//}else if (a == 7){
|
||||||
|
// value = 0.0514*Vehicle_data.p_fuel;
|
||||||
|
}else if (a == 3){
|
||||||
|
value = 0.0514*Vehicle_data.p_oil;
|
||||||
|
}else if (a == 8){
|
||||||
|
value = Vehicle_data.p_brake_front;
|
||||||
|
}else if (a == 9){
|
||||||
|
value = Vehicle_data.p_brake_rear;
|
||||||
|
}else if(a == 4){
|
||||||
|
value = 200*Vehicle_data.p_brake_front/(Vehicle_data.p_brake_rear+(2*Vehicle_data.p_brake_front));
|
||||||
|
}else if (a == 11){
|
||||||
|
value = Vehicle_data.speed_fl;
|
||||||
|
}else if (a == 12){
|
||||||
|
value = Vehicle_data.speed_fr;
|
||||||
|
}else if(a == 13){
|
||||||
|
value = Vehicle_data.speed;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_display(){
|
||||||
|
if(((millis()-poiltimer)>=20000) and poilbool){
|
||||||
|
poilbool = false;
|
||||||
|
alarm("P_oil");
|
||||||
|
}
|
||||||
|
if(((millis()-tmottimer)>=20000) and tmotbool){
|
||||||
|
tmotbool = false;
|
||||||
|
alarm("T_mot");
|
||||||
|
}
|
||||||
|
if(((millis()-toiltimer)>=10000) and toilbool){
|
||||||
|
toilbool = false;
|
||||||
|
alarm("T_oil");
|
||||||
|
}
|
||||||
|
if((0.0514*Vehicle_data.p_oil)>=0,1 or Vehicle_data.speed == 0){
|
||||||
|
poiltimer = millis();
|
||||||
|
}
|
||||||
|
if(((Vehicle_data.t_mot - 40) <= 0x69) or ((Vehicle_data.t_mot - 40)==0xC8)){
|
||||||
|
tmottimer = millis();
|
||||||
|
}
|
||||||
|
if((Vehicle_data.t_oil - 40) <= 0x96){
|
||||||
|
toiltimer = millis();
|
||||||
|
}
|
||||||
|
if(Stw_data.buttonState1 & Stw_data.buttonState4){
|
||||||
|
alarm("");
|
||||||
|
}
|
||||||
|
if(!tft._displaybool){
|
||||||
|
tft.cursorOn(false);
|
||||||
|
if(trcalt!=Stw_data.trc or trctimer == true or Stw_data.buttonStateEnc1 == HIGH){
|
||||||
|
display_trc();
|
||||||
|
}else if(modealt!=Stw_data.mode or modetimer == true or Stw_data.buttonStateEnc2 == HIGH){
|
||||||
|
display_mode();
|
||||||
|
}else{
|
||||||
|
if(clearcounter>=56){
|
||||||
|
tft.clear();
|
||||||
|
clearcounter = 0;
|
||||||
|
}
|
||||||
|
clearcounter+=1;
|
||||||
|
if(Stw_data.buttonState4){
|
||||||
|
if(Stw_data.displayindex>=sizeof(bezeichnungen)/sizeof(String)-3){
|
||||||
|
Stw_data.displayindex = 0;
|
||||||
|
delay(250);
|
||||||
|
}else{
|
||||||
|
Stw_data.displayindex+=1;
|
||||||
|
delay(250);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(Stw_data.buttonState1){
|
||||||
|
if(Stw_data.displayindex<=0){
|
||||||
|
Stw_data.displayindex = sizeof(bezeichnungen)/sizeof(String)-3;
|
||||||
|
delay(250);
|
||||||
|
}else{
|
||||||
|
Stw_data.displayindex-=1;
|
||||||
|
delay(250);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(vergleichsindex!=Stw_data.displayindex){
|
||||||
|
tft.clear();
|
||||||
|
vergleichsindex=Stw_data.displayindex;
|
||||||
|
}
|
||||||
|
int a = sizeof(bezeichnungen[Stw_data.displayindex]);
|
||||||
|
int g = sizeof(bezeichnungen[Stw_data.displayindex+1]);
|
||||||
|
int h = sizeof(bezeichnungen[Stw_data.displayindex+2]);
|
||||||
|
char d[a];
|
||||||
|
char e[g];
|
||||||
|
char f[h];
|
||||||
|
bezeichnungen[Stw_data.displayindex].toCharArray(d,a);
|
||||||
|
bezeichnungen[Stw_data.displayindex+1].toCharArray(e,g);
|
||||||
|
bezeichnungen[Stw_data.displayindex+2].toCharArray(f,h);
|
||||||
|
char b[2];
|
||||||
|
char c[5];
|
||||||
|
char i[5];
|
||||||
|
char j[5];
|
||||||
|
char k[5];
|
||||||
|
char m[5];
|
||||||
|
String str=String(int(get_value(0)));
|
||||||
|
if(str.equals(String(0))){
|
||||||
|
str = "N";
|
||||||
|
}
|
||||||
|
String str1;
|
||||||
|
String str2;
|
||||||
|
String str3;
|
||||||
|
if(Stw_data.displayindex+1==0 or Stw_data.displayindex+1==2 or Stw_data.displayindex+1==1 or Stw_data.displayindex+1==10 or Stw_data.displayindex+1==7 or Stw_data.displayindex+1==11 or Stw_data.displayindex+1==12 or Stw_data.displayindex+1==13){
|
||||||
|
str1=String(int(get_value(Stw_data.displayindex+1)));
|
||||||
|
}else{
|
||||||
|
str1=String(get_value(Stw_data.displayindex+1));
|
||||||
|
}
|
||||||
|
if(Stw_data.displayindex+1 == 10){
|
||||||
|
if(str1.equals(String(1))){
|
||||||
|
str1 = "PC";
|
||||||
|
}else if(str1.equals(String(2))){
|
||||||
|
str1 = "BSE";
|
||||||
|
}else if(str1.equals(String(3))){
|
||||||
|
str1 = "APS";
|
||||||
|
}else if(str1.equals(String(4))){
|
||||||
|
str1 = "ETB";
|
||||||
|
}else if(str1.equals(String(0))){
|
||||||
|
str1 = "None";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(Stw_data.displayindex+2==0 or Stw_data.displayindex+2==2 or Stw_data.displayindex+2==1 or Stw_data.displayindex+2==10 or Stw_data.displayindex+2==7 or Stw_data.displayindex+2==11 or Stw_data.displayindex+2==12 or Stw_data.displayindex+2==13){
|
||||||
|
str2=String(int(get_value(Stw_data.displayindex+2)));
|
||||||
|
}else{
|
||||||
|
str2=String(get_value(Stw_data.displayindex+2));
|
||||||
|
}
|
||||||
|
if(Stw_data.displayindex+2 == 10){
|
||||||
|
if(str2.equals(String(1))){
|
||||||
|
str2 = "PC";
|
||||||
|
}else if(str2.equals(String(2))){
|
||||||
|
str2 = "BSE";
|
||||||
|
}else if(str2.equals(String(3))){
|
||||||
|
str2 = "APS";
|
||||||
|
}else if(str2.equals(String(4))){
|
||||||
|
str2 = "ETB";
|
||||||
|
}else if(str2.equals(String(0))){
|
||||||
|
str2 = "None";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(Stw_data.displayindex+3==0 or Stw_data.displayindex+3==2 or Stw_data.displayindex+3==1 or Stw_data.displayindex+3==10 or Stw_data.displayindex+3==7 or Stw_data.displayindex+3==11 or Stw_data.displayindex+3==12 or Stw_data.displayindex+3==13){
|
||||||
|
str3=String(int(get_value(Stw_data.displayindex+3)));
|
||||||
|
}else{
|
||||||
|
str3=String(get_value(Stw_data.displayindex+3));
|
||||||
|
}
|
||||||
|
if(Stw_data.displayindex+3 == 10){
|
||||||
|
if(str3.equals(String(1))){
|
||||||
|
str3 = "PC";
|
||||||
|
}else if(str3.equals(String(2))){
|
||||||
|
str3 = "BSE";
|
||||||
|
}else if(str3.equals(String(3))){
|
||||||
|
str3 = "APS";
|
||||||
|
}else if(str3.equals(String(4))){
|
||||||
|
str3 = "ETB";
|
||||||
|
}else if(str3.equals(String(0))){
|
||||||
|
str3 = "None";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String str5=String(Vehicle_data.revol/2);
|
||||||
|
String str4=String(0.0514*Vehicle_data.p_fuel);
|
||||||
|
str.toCharArray(b,2);
|
||||||
|
str1.toCharArray(c,5);
|
||||||
|
str2.toCharArray(i,5);
|
||||||
|
str3.toCharArray(j,5);
|
||||||
|
str4.toCharArray(k,5);
|
||||||
|
str5.toCharArray(m,5);
|
||||||
|
sizeaneu = strlen(c);
|
||||||
|
sizebneu = strlen(i);
|
||||||
|
sizecneu = strlen(j);
|
||||||
|
sizedneu = strlen(k);
|
||||||
|
sizeeneu = strlen(m);
|
||||||
|
if(sizeaalt!=sizeaneu){
|
||||||
|
tft.clear();
|
||||||
|
sizeaalt=sizeaneu;
|
||||||
|
}
|
||||||
|
if(sizebalt!=sizebneu){
|
||||||
|
tft.clear();
|
||||||
|
sizebalt=sizebneu;
|
||||||
|
}
|
||||||
|
if(sizecalt!=sizecneu){
|
||||||
|
tft.clear();
|
||||||
|
sizecalt=sizecneu;
|
||||||
|
}
|
||||||
|
if(sizedalt!=sizedneu){
|
||||||
|
tft.clear();
|
||||||
|
sizedalt=sizedneu;
|
||||||
|
}
|
||||||
|
if(sizeealt!=sizeeneu){
|
||||||
|
tft.clear();
|
||||||
|
sizeealt=sizeeneu;
|
||||||
|
}
|
||||||
|
tft.setTextSize(6,8);
|
||||||
|
tft.drawText(132, 0, 'L', b);
|
||||||
|
tft.setTextSize(2,7);
|
||||||
|
tft.drawText(0, 20, 'L', k);
|
||||||
|
tft.drawText(240, 20, 'L', m);
|
||||||
|
tft.drawText(0,130, 'L', c);
|
||||||
|
tft.drawText(120, 130, 'L', i);
|
||||||
|
tft.drawText(240,130, 'L', j);
|
||||||
|
tft.setTextSize(1,1);
|
||||||
|
tft.drawText(136,116, 'L', "Gang");
|
||||||
|
tft.drawText(0,116, 'L', "P_fuel");
|
||||||
|
tft.drawText(240,116, 'L', "Drehzahl");
|
||||||
|
tft.drawText(0,226, 'L', d);
|
||||||
|
tft.drawText(120,226, 'L', e);
|
||||||
|
tft.drawText(240,226, 'L', f);
|
||||||
|
/*if (cleaner){
|
||||||
|
tft.setTextSize(5,8);
|
||||||
|
tft.drawText(0, 14, 'C', "FaSTTUBe"); // draw some text
|
||||||
|
tft.setTextSize(4,4);
|
||||||
|
tft.drawText(24, 120, 'C', "insert coin"); // draw some text
|
||||||
|
tft.drawText(0, 180, 'C', "to continue");
|
||||||
|
cleaner = false;
|
||||||
|
}else{
|
||||||
|
tft.setTextSize(5,8);
|
||||||
|
tft.drawText(0, 14, 'C', "FaSTTUBe"); // draw some text
|
||||||
|
tft.setTextSize(4,4);
|
||||||
|
tft.drawText(24, 120, 'C', " "); // draw some text
|
||||||
|
tft.drawText(0, 180, 'C', " ");
|
||||||
|
cleaner = true;
|
||||||
|
}
|
||||||
|
delay(80);*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_trc(){
|
||||||
|
if(trcalt!=Stw_data.trc or Stw_data.buttonStateEnc1 == HIGH){
|
||||||
|
tft.clear();
|
||||||
|
tft.setTextSize(7,8);
|
||||||
|
tft.setDisplayColor(EA_WHITE,EA_RED);
|
||||||
|
tft.setTextColor(EA_WHITE,EA_RED);
|
||||||
|
char trcanzeige[7];
|
||||||
|
String str = String("ARB:");
|
||||||
|
if(Stw_data.trc==11){
|
||||||
|
str+="ED";
|
||||||
|
}else{
|
||||||
|
str+=String(Stw_data.trc);
|
||||||
|
}
|
||||||
|
str.toCharArray(trcanzeige,7);
|
||||||
|
tft.drawText(0,0,'L'," ");
|
||||||
|
tft.drawText(0,60,'L'," ");
|
||||||
|
tft.drawText(0,120,'L'," ");
|
||||||
|
tft.drawText(0,180,'L'," ");
|
||||||
|
tft.drawText(15,68,'L',trcanzeige);
|
||||||
|
trccounter = 0;
|
||||||
|
trcalt = Stw_data.trc;
|
||||||
|
trctimer = true;
|
||||||
|
}else if(trccounter >= 255){
|
||||||
|
tft.setDisplayColor(EA_WHITE,EA_BLACK);
|
||||||
|
tft.setTextColor(EA_WHITE,EA_BLACK);
|
||||||
|
tft.clear();
|
||||||
|
trctimer = false;
|
||||||
|
}else{
|
||||||
|
trccounter+=1;
|
||||||
|
delay(5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_mode(){
|
||||||
|
if(modealt!=Stw_data.mode or Stw_data.buttonStateEnc2 == HIGH){
|
||||||
|
tft.clear();
|
||||||
|
tft.setTextSize(6,8);
|
||||||
|
tft.setDisplayColor(EA_WHITE,EA_RED);
|
||||||
|
tft.setTextColor(EA_WHITE,EA_RED);
|
||||||
|
char modeanzeige[7];
|
||||||
|
String str = String("MODE:");
|
||||||
|
str+=String(Stw_data.mode);
|
||||||
|
str.toCharArray(modeanzeige,7);
|
||||||
|
tft.drawText(0,0,'L'," ");
|
||||||
|
tft.drawText(0,60,'L'," ");
|
||||||
|
tft.drawText(0,120,'L'," ");
|
||||||
|
tft.drawText(0,180,'L'," ");
|
||||||
|
tft.drawText(15,68,'L',modeanzeige);
|
||||||
|
modecounter = 0;
|
||||||
|
modealt = Stw_data.mode;
|
||||||
|
modetimer = true;
|
||||||
|
}else if(modecounter >= 255){
|
||||||
|
tft.setDisplayColor(EA_WHITE,EA_BLACK);
|
||||||
|
tft.setTextColor(EA_WHITE,EA_BLACK);
|
||||||
|
tft.clear();
|
||||||
|
modetimer = false;
|
||||||
|
}else{
|
||||||
|
modecounter+=1;
|
||||||
|
delay(5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void alarm(String textstr){
|
||||||
|
uint8_t x = 1;;
|
||||||
|
char text[7];
|
||||||
|
textstr.toCharArray(text,7);
|
||||||
|
tft.setTextSize(8,8);
|
||||||
|
while(x==1){
|
||||||
|
if(!tft._displaybool){
|
||||||
|
tft.setTextColor(EA_BLACK,EA_RED);
|
||||||
|
tft.fillDisplayColor(EA_RED);
|
||||||
|
tft.drawText(5,68,'L',text);
|
||||||
|
}
|
||||||
|
for (int j = 0; j < 16; j++){
|
||||||
|
digitalWrite(led_s[j], HIGH);
|
||||||
|
}
|
||||||
|
delay(100);
|
||||||
|
if(!tft._displaybool){
|
||||||
|
tft.setTextColor(EA_BLACK,EA_WHITE);
|
||||||
|
tft.fillDisplayColor(EA_WHITE);
|
||||||
|
tft.drawText(5,68,'L',text);
|
||||||
|
}
|
||||||
|
for (int j = 0; j < 16; j++){
|
||||||
|
digitalWrite(led_s[j], LOW);
|
||||||
|
}
|
||||||
|
delay(100);
|
||||||
|
if(Stw_data.buttonState1 & Stw_data.buttonState4){
|
||||||
|
x=0;
|
||||||
|
tft.setTextColor(EA_WHITE,EA_BLACK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "EDIPTFT.h"
|
||||||
|
#include "FT_2018_STW_CAN.h"
|
||||||
|
#include "FT18_STW_INIT.h"
|
||||||
|
#ifndef FT18_STW_DISPLAY_h
|
||||||
|
#define FT18_STW_DISPLAY_h
|
||||||
|
|
||||||
|
#define EA_BLACK 1
|
||||||
|
#define EA_RED 3
|
||||||
|
#define EA_GREY 10
|
||||||
|
#define EA_WHITE 8
|
||||||
|
|
||||||
|
#define MOSI 75
|
||||||
|
#define MISO 74
|
||||||
|
#define CLK 76
|
||||||
|
#define disp_cs 42
|
||||||
|
#define reset 43
|
||||||
|
#define writeprotect 52
|
||||||
|
|
||||||
|
|
||||||
|
void init_display(void);
|
||||||
|
void update_display(void);
|
||||||
|
double get_value(int a);
|
||||||
|
void display_trc(void);
|
||||||
|
void display_mode(void);
|
||||||
|
void alarm(String text);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,200 @@
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "FT18_STW_INIT.h"
|
||||||
|
#include "Bounce2.h"
|
||||||
|
#include "RotaryEncoder.h"
|
||||||
|
|
||||||
|
volatile stw_data_type Stw_data = {0}; //alles mit 0 initialisieren
|
||||||
|
volatile vehicle_data_type Vehicle_data = {0}; //alles mit 0 initialisieren
|
||||||
|
bool enc1PinALast,enc1PinANow,enc2PinALast,enc2PinANow;
|
||||||
|
int led[] = {led1,led2,led3,led4,led5,led6,led7,led8,led9,led10,led11,led12,led13,led14,led15,led16};
|
||||||
|
bool entprell;
|
||||||
|
int buttons[] = {button1,button2,button3,button4,button5,button6,enc1PinS,enc2PinS};
|
||||||
|
Bounce debouncer[8];
|
||||||
|
double val = 0;
|
||||||
|
double val2 = 0;
|
||||||
|
RotaryEncoder encoder(enc1PinA,enc1PinB,1,1,50);
|
||||||
|
RotaryEncoder encoder2(enc2PinA,enc2PinB,1,1,50);
|
||||||
|
///////////////////////////////////////////////////
|
||||||
|
// functions
|
||||||
|
///////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void set_pins(){
|
||||||
|
pinMode (l,OUTPUT);
|
||||||
|
for (int thisLed = 0; thisLed < sizeof(led)/sizeof(int); thisLed++) {
|
||||||
|
pinMode(led[thisLed], OUTPUT);
|
||||||
|
}
|
||||||
|
/*pinMode(button1, INPUT);
|
||||||
|
pinMode(button2, INPUT);
|
||||||
|
pinMode(button3, INPUT);
|
||||||
|
pinMode(button4, INPUT);
|
||||||
|
pinMode(button5, INPUT);
|
||||||
|
pinMode(button6, INPUT);*/
|
||||||
|
pinMode(enc1PinA, INPUT);
|
||||||
|
pinMode(enc1PinB, INPUT);
|
||||||
|
//pinMode(enc1PinS, INPUT);
|
||||||
|
pinMode(enc2PinA, INPUT);
|
||||||
|
pinMode(enc2PinB, INPUT);
|
||||||
|
//pinMode(enc2PinS, INPUT);
|
||||||
|
//Stw_data.i=0;
|
||||||
|
enc1PinALast=LOW;
|
||||||
|
enc1PinANow=LOW;
|
||||||
|
enc2PinALast=LOW;
|
||||||
|
enc2PinANow=LOW;
|
||||||
|
for(int i = 0; i < 8; i++){
|
||||||
|
pinMode(buttons[i], INPUT);
|
||||||
|
debouncer[i].attach(buttons[i]);
|
||||||
|
debouncer[i].interval(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void read_buttons(){
|
||||||
|
/*entprell = digitalRead(button3);
|
||||||
|
delay(10);
|
||||||
|
if(digitalRead(button3)){
|
||||||
|
Stw_data.Stw_auto_shift = entprell;
|
||||||
|
}
|
||||||
|
entprell = digitalRead(button2);
|
||||||
|
delay(10);
|
||||||
|
if(digitalRead(button2)){
|
||||||
|
Stw_data.Stw_neutral = entprell;
|
||||||
|
}
|
||||||
|
entprell = digitalRead(button1);
|
||||||
|
delay(10);
|
||||||
|
if(digitalRead(button1)){
|
||||||
|
Stw_data.buttonState1 = entprell;
|
||||||
|
}
|
||||||
|
entprell = digitalRead(button6);
|
||||||
|
delay(10);
|
||||||
|
if(digitalRead(button6)){
|
||||||
|
Stw_data.Stw_shift_up = entprell;
|
||||||
|
}
|
||||||
|
entprell = digitalRead(button5);
|
||||||
|
delay(10);
|
||||||
|
if(digitalRead(button5)){
|
||||||
|
Stw_data.Stw_shift_down = entprell;
|
||||||
|
}
|
||||||
|
entprell = digitalRead(button4);
|
||||||
|
delay(10);
|
||||||
|
if(digitalRead(button4)){
|
||||||
|
Stw_data.buttonState4 = entprell;
|
||||||
|
}
|
||||||
|
entprell = digitalRead(enc1PinS);
|
||||||
|
delay(10);
|
||||||
|
if(digitalRead(enc1PinS)){
|
||||||
|
Stw_data.buttonStateEnc1 = entprell;
|
||||||
|
}
|
||||||
|
entprell = digitalRead(enc2PinS);
|
||||||
|
delay(10);
|
||||||
|
if(digitalRead(enc2PinS)){
|
||||||
|
Stw_data.buttonStateEnc2 = entprell;
|
||||||
|
}*/
|
||||||
|
Stw_data.Stw_auto_shift = digitalRead(button3);
|
||||||
|
Stw_data.Stw_neutral = digitalRead(button2);
|
||||||
|
Stw_data.buttonState1 = digitalRead(button1);
|
||||||
|
Stw_data.Stw_shift_up = digitalRead(button6);
|
||||||
|
Stw_data.Stw_shift_down = digitalRead(button5);
|
||||||
|
Stw_data.buttonState4 = digitalRead(button4);
|
||||||
|
Stw_data.buttonStateEnc1 = digitalRead(enc1PinS);
|
||||||
|
Stw_data.buttonStateEnc2 = digitalRead(enc2PinS);
|
||||||
|
|
||||||
|
/*for(int i = 0;i < 8; i++){
|
||||||
|
debouncer[i].update();
|
||||||
|
}
|
||||||
|
debouncer[2].update();
|
||||||
|
if(debouncer[2].fell()){
|
||||||
|
Stw_data.Stw_auto_shift = HIGH;
|
||||||
|
}
|
||||||
|
if(debouncer[1].fell()){
|
||||||
|
Stw_data.Stw_neutral = digitalRead(button2);
|
||||||
|
}
|
||||||
|
if(debouncer[0].fell()){
|
||||||
|
Stw_data.buttonState1 = digitalRead(button1);
|
||||||
|
}
|
||||||
|
if(debouncer[5].fell()){
|
||||||
|
Stw_data.Stw_shift_up = digitalRead(button6);
|
||||||
|
}
|
||||||
|
if(debouncer[4].fell()){
|
||||||
|
Stw_data.Stw_shift_down = digitalRead(button5);
|
||||||
|
}
|
||||||
|
if(debouncer[3].fell()){
|
||||||
|
Stw_data.buttonState4 = digitalRead(button4);
|
||||||
|
}
|
||||||
|
if(debouncer[6].fell()){
|
||||||
|
Stw_data.buttonStateEnc1 = digitalRead(enc1PinS);
|
||||||
|
}
|
||||||
|
if(debouncer[7].fell()){
|
||||||
|
Stw_data.buttonStateEnc2 = digitalRead(enc2PinS);
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void read_rotary(){
|
||||||
|
int enc = encoder.readEncoder();
|
||||||
|
int enc2 = encoder2.readEncoder();
|
||||||
|
if(enc != 0){
|
||||||
|
val = val +0.5*enc;
|
||||||
|
if (val==1 or val ==-1){
|
||||||
|
if(Stw_data.trc==0 and enc<0){
|
||||||
|
Stw_data.trc = 11;
|
||||||
|
}else if(Stw_data.trc==11 and enc>0){
|
||||||
|
Stw_data.trc=0;
|
||||||
|
}else{
|
||||||
|
Stw_data.trc = Stw_data.trc + enc;
|
||||||
|
}
|
||||||
|
val = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*enc1PinANow = digitalRead(enc1PinA);
|
||||||
|
enc2PinANow = digitalRead(enc2PinA);
|
||||||
|
if ((enc1PinALast == LOW) && (enc1PinANow == HIGH)) {
|
||||||
|
if (digitalRead(enc1PinB) == HIGH) {
|
||||||
|
if(Stw_data.trc==0){
|
||||||
|
Stw_data.trc = 5;
|
||||||
|
}else{
|
||||||
|
Stw_data.trc--;
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
if(Stw_data.trc==5){
|
||||||
|
Stw_data.trc=0;
|
||||||
|
}else{
|
||||||
|
Stw_data.trc++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enc1PinALast = enc1PinANow;
|
||||||
|
/*if (Stw_data.buttonStateEnc1 == HIGH){
|
||||||
|
digitalWrite(led[Stw_data.i], HIGH);
|
||||||
|
}*/
|
||||||
|
if(enc2 != 0){
|
||||||
|
val2 = val2 +0.5*enc2;
|
||||||
|
if(val2==1 or val2==-1){
|
||||||
|
if((Stw_data.mode==1 or Stw_data.mode==0) and enc2<0){
|
||||||
|
Stw_data.mode = 5;
|
||||||
|
}else if(Stw_data.mode==5 and enc2>0){
|
||||||
|
Stw_data.mode=1;
|
||||||
|
}else{
|
||||||
|
Stw_data.mode = Stw_data.mode + enc2;
|
||||||
|
}
|
||||||
|
val2=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*if ((enc2PinALast == LOW) && (enc2PinANow == HIGH)) {
|
||||||
|
//if(enc2PinALast != enc2PinANow){
|
||||||
|
if (digitalRead(enc2PinB) == HIGH) {
|
||||||
|
if(Stw_data.i==0){
|
||||||
|
Stw_data.i = sizeof(led)/sizeof(int)-1;
|
||||||
|
}else{
|
||||||
|
Stw_data.i--;
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
if(Stw_data.i==sizeof(led)/sizeof(int)-1){
|
||||||
|
Stw_data.i=0;
|
||||||
|
}else{
|
||||||
|
Stw_data.i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enc2PinALast = enc2PinANow;*/
|
||||||
|
/*if (Stw_data.buttonStateEnc2 == HIGH){
|
||||||
|
digitalWrite(led[Stw_data.i], HIGH);
|
||||||
|
}*/
|
||||||
|
}
|
|
@ -0,0 +1,101 @@
|
||||||
|
#include "Arduino.h"
|
||||||
|
#ifndef FT18_STW_Init
|
||||||
|
#define FT18_STW_Init
|
||||||
|
|
||||||
|
#define l 78 //test_led
|
||||||
|
#define led1 12//PD8
|
||||||
|
#define led2 11//PD7
|
||||||
|
#define led3 9//PC21
|
||||||
|
#define led4 8//PC22
|
||||||
|
#define led5 7//PC23
|
||||||
|
#define led6 6//PC24
|
||||||
|
#define led7 5//PC25
|
||||||
|
#define led8 4//PC26 und PA29
|
||||||
|
#define led9 3//PC28
|
||||||
|
#define led10 2//PB25
|
||||||
|
#define led11 10//PC29 und PA28
|
||||||
|
#define led12 22//PB26
|
||||||
|
#define led13 19//PA10
|
||||||
|
#define led14 13//PB27
|
||||||
|
#define led15 17//PA12
|
||||||
|
#define led16 18//PA11
|
||||||
|
#define button1 48//bl
|
||||||
|
#define button2 47//gl
|
||||||
|
#define button3 44//gr
|
||||||
|
#define button4 46//br
|
||||||
|
#define button5 45//sl
|
||||||
|
#define button6 49//sr
|
||||||
|
#define enc1PinA 37
|
||||||
|
#define enc1PinB 38
|
||||||
|
#define enc1PinS 35
|
||||||
|
#define enc2PinA 40
|
||||||
|
#define enc2PinB 41
|
||||||
|
#define enc2PinS 39
|
||||||
|
|
||||||
|
|
||||||
|
// define Drehzahlgrenzen TODOOOO
|
||||||
|
#define RPM_THRES_1 1000
|
||||||
|
#define RPM_THRES_2 6000
|
||||||
|
#define RPM_THRES_3 7000
|
||||||
|
#define RPM_THRES_4 8000
|
||||||
|
#define RPM_THRES_5 10000
|
||||||
|
#define RPM_THRES_6 14000
|
||||||
|
#define RPM_THRES_7 17000
|
||||||
|
#define RPM_THRES_8 18000
|
||||||
|
#define RPM_THRES_9 20000
|
||||||
|
#define RPM_THRES_10 20000
|
||||||
|
|
||||||
|
|
||||||
|
void set_pins(void);
|
||||||
|
void read_buttons(void);
|
||||||
|
void read_rotary(void); // read rotary switches
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t Stw_shift_up; // 1 Bit 0
|
||||||
|
uint8_t Stw_shift_down; // 1 Bit 1
|
||||||
|
uint8_t Stw_neutral; // 1 Bit 2
|
||||||
|
uint8_t Stw_auto_shift; // 1 Bit 3
|
||||||
|
uint8_t buttonState1; // 1 Bit 4
|
||||||
|
uint8_t buttonState4; // 1 Bit 5
|
||||||
|
//bool CAN_toggle;
|
||||||
|
//bool CAN_check;
|
||||||
|
//uint8_t i; //Index linker Drehschalter
|
||||||
|
uint8_t buttonStateEnc1; // button
|
||||||
|
//uint8_t br; //test mode : mittlere Drehschalter position
|
||||||
|
uint8_t buttonStateEnc2; //button
|
||||||
|
uint8_t displayindex; //index für Displayanzeige
|
||||||
|
uint8_t error_type; //Extrainfos über Error-LED
|
||||||
|
uint8_t trc;
|
||||||
|
uint8_t mode;
|
||||||
|
|
||||||
|
} stw_data_type;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t e_thro; // E-Drossel
|
||||||
|
uint8_t g_auto; // Auto-Shift
|
||||||
|
uint8_t gear; // Gang
|
||||||
|
uint16_t revol; // Drehzahl
|
||||||
|
uint8_t t_oil; // Öl-Motor-Temperatur
|
||||||
|
uint8_t t_mot; // Wasser-Motor-Temperatur
|
||||||
|
uint8_t t_air; // LLK-Temperatur
|
||||||
|
uint8_t u_batt; // Batteriespannung
|
||||||
|
uint8_t rev_lim; // Drehzahllimit Bit
|
||||||
|
uint8_t p_wat;
|
||||||
|
uint8_t p_fuel;
|
||||||
|
uint8_t p_oil;
|
||||||
|
uint8_t p_brake_front;
|
||||||
|
uint8_t p_brake_rear;
|
||||||
|
uint8_t speed_fl;
|
||||||
|
uint8_t speed_fr;
|
||||||
|
uint8_t speed;
|
||||||
|
|
||||||
|
} vehicle_data_type;
|
||||||
|
|
||||||
|
|
||||||
|
extern volatile stw_data_type Stw_data;
|
||||||
|
extern volatile vehicle_data_type Vehicle_data;
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,407 @@
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "EDIPTFT.h"
|
||||||
|
#include "FT_2018e_STW_CAN.h"
|
||||||
|
#include "FT18e_STW_INIT.h"
|
||||||
|
#include "FT18e_STW_DISPLAY.h"
|
||||||
|
|
||||||
|
EDIPTFT tft(true,false);
|
||||||
|
String bezeichnungen[]={"Batterieleistung","Moment","Batterietemp"};
|
||||||
|
//"T_mot","T_oil","P_oil","% fa","U_batt","P_wat","T_air",
|
||||||
|
//"P_b_front","P_b_rear","Error Type","Speed_fl","Speed_fr","Speed"};
|
||||||
|
//"Drehzahl","P_fuel","Index"
|
||||||
|
int vergleichsindex;
|
||||||
|
int sizeaalt;
|
||||||
|
int sizeaneu;
|
||||||
|
int sizebalt;
|
||||||
|
int sizebneu;
|
||||||
|
int sizecalt;
|
||||||
|
int sizecneu;
|
||||||
|
int sizedalt;
|
||||||
|
int sizedneu;
|
||||||
|
int sizeealt;
|
||||||
|
int sizeeneu;
|
||||||
|
uint8_t clearcounter = 56;
|
||||||
|
uint8_t trcalt = Stw_data.trc;
|
||||||
|
uint8_t modealt = Stw_data.mode;
|
||||||
|
uint8_t trccounter;// = Stw_data.trc;
|
||||||
|
uint8_t modecounter;// = Stw_data.mode;
|
||||||
|
bool trctimer;
|
||||||
|
bool modetimer;
|
||||||
|
int led_s[] = {led1,led2,led3,led4,led5,led6,led7,led8,led9,led10,led11,led12,led13,led14,led15,led16};
|
||||||
|
unsigned long poiltimer;
|
||||||
|
unsigned long tmottimer;
|
||||||
|
unsigned long toiltimer;
|
||||||
|
bool poilbool = true;
|
||||||
|
bool tmotbool = true;
|
||||||
|
bool toilbool = true;
|
||||||
|
|
||||||
|
void init_display() {
|
||||||
|
pinMode(writeprotect, OUTPUT);
|
||||||
|
digitalWrite(writeprotect, HIGH);
|
||||||
|
pinMode(reset, OUTPUT);
|
||||||
|
pinMode(disp_cs, OUTPUT);
|
||||||
|
pinMode(MOSI, OUTPUT);
|
||||||
|
pinMode(MISO, OUTPUT);
|
||||||
|
//pinMode(CLK, INPUT);
|
||||||
|
digitalWrite(disp_cs, HIGH);
|
||||||
|
digitalWrite(MOSI, HIGH);
|
||||||
|
digitalWrite(MISO, HIGH);
|
||||||
|
digitalWrite(reset, LOW);
|
||||||
|
//edip.smallProtoSelect(7);
|
||||||
|
//edip.setNewColor(EA_GREY, 0xe3, 0xe3,0xe3); // redefine r-g-b-values of EA_GREY
|
||||||
|
//edip.drawImage(0,50,FASTTUBE_LOGO_PNG);
|
||||||
|
digitalWrite(reset,HIGH);
|
||||||
|
tft.begin(115200); // start display communication
|
||||||
|
/*int h = 20;
|
||||||
|
char charh[2];
|
||||||
|
String strh = String(h);
|
||||||
|
strh.toCharArray(charh,2);
|
||||||
|
tft.DisplayLight(charh);*/
|
||||||
|
tft.cursorOn(false);
|
||||||
|
tft.terminalOn(false);
|
||||||
|
tft.setDisplayColor(EA_WHITE,EA_BLACK);
|
||||||
|
tft.setTextColor(EA_WHITE,EA_BLACK);
|
||||||
|
//tft.setTextFont('4');
|
||||||
|
tft.setTextSize(5,8);
|
||||||
|
tft.clear();
|
||||||
|
//tft.displayLight('30');
|
||||||
|
tft.drawText(0, 14, 'C', "FaSTTUBe"); //draw some text
|
||||||
|
//tft.loadImage(0,0,1);
|
||||||
|
//delay(2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
double get_value(int a){
|
||||||
|
double value;
|
||||||
|
if (a == 0){
|
||||||
|
value = Vehicle_data.gear;
|
||||||
|
//}else if (a == 11){
|
||||||
|
// value = Stw_data.i;
|
||||||
|
//}else if (a == 1){
|
||||||
|
// value = Vehicle_data.revol/2;
|
||||||
|
}else if (a == 1){
|
||||||
|
value = Vehicle_data.t_mot;//-40;
|
||||||
|
}else if (a == 5){
|
||||||
|
value = 0.0706949*Vehicle_data.u_batt;
|
||||||
|
}else if (a == 7){
|
||||||
|
value = Vehicle_data.t_air;//-40;
|
||||||
|
}else if(a == 10){
|
||||||
|
value = Stw_data.error_type;
|
||||||
|
}else if (a == 2){
|
||||||
|
value = Vehicle_data.t_oil;//-40;
|
||||||
|
}else if (a == 6){
|
||||||
|
value = 0.0514*Vehicle_data.p_wat;
|
||||||
|
//}else if (a == 7){
|
||||||
|
// value = 0.0514*Vehicle_data.p_fuel;
|
||||||
|
}else if (a == 3){
|
||||||
|
value = 0.0514*Vehicle_data.p_oil;
|
||||||
|
}else if (a == 8){
|
||||||
|
value = Vehicle_data.p_brake_front;
|
||||||
|
}else if (a == 9){
|
||||||
|
value = Vehicle_data.p_brake_rear;
|
||||||
|
}else if(a == 4){
|
||||||
|
value = 200*Vehicle_data.p_brake_front/(Vehicle_data.p_brake_rear+(2*Vehicle_data.p_brake_front));
|
||||||
|
}else if (a == 11){
|
||||||
|
value = Vehicle_data.speed_fl;
|
||||||
|
}else if (a == 12){
|
||||||
|
value = Vehicle_data.speed_fr;
|
||||||
|
}else if(a == 13){
|
||||||
|
value = Vehicle_data.speed;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_display(){
|
||||||
|
/*if(((millis()-poiltimer)>=20000) and poilbool){
|
||||||
|
poilbool = false;
|
||||||
|
alarm("P_oil");
|
||||||
|
}
|
||||||
|
if(((millis()-tmottimer)>=20000) and tmotbool){
|
||||||
|
tmotbool = false;
|
||||||
|
alarm("T_mot");
|
||||||
|
}
|
||||||
|
if(((millis()-toiltimer)>=10000) and toilbool){
|
||||||
|
toilbool = false;
|
||||||
|
alarm("T_oil");
|
||||||
|
}
|
||||||
|
if((0.0514*Vehicle_data.p_oil)>=0,1 or Vehicle_data.speed == 0){
|
||||||
|
poiltimer = millis();
|
||||||
|
}
|
||||||
|
if(((Vehicle_data.t_mot - 40) <= 0x69) or ((Vehicle_data.t_mot - 40)==0xC8)){
|
||||||
|
tmottimer = millis();
|
||||||
|
}
|
||||||
|
if((Vehicle_data.t_oil - 40) <= 0x96){
|
||||||
|
toiltimer = millis();
|
||||||
|
}*/
|
||||||
|
if(Stw_data.buttonState1 & Stw_data.buttonState4){
|
||||||
|
alarm("");
|
||||||
|
}
|
||||||
|
if(!tft._displaybool){
|
||||||
|
tft.cursorOn(false);
|
||||||
|
if(trcalt!=Stw_data.trc or trctimer == true or Stw_data.buttonStateEnc1 == HIGH){
|
||||||
|
display_trc();
|
||||||
|
}else if(modealt!=Stw_data.mode or modetimer == true or Stw_data.buttonStateEnc2 == HIGH){
|
||||||
|
display_mode();
|
||||||
|
}else{
|
||||||
|
if(clearcounter>=56){
|
||||||
|
tft.clear();
|
||||||
|
clearcounter = 0;
|
||||||
|
}
|
||||||
|
clearcounter+=1;
|
||||||
|
if(Stw_data.buttonState4){
|
||||||
|
if(Stw_data.displayindex>=sizeof(bezeichnungen)/sizeof(String)-3){
|
||||||
|
Stw_data.displayindex = 0;
|
||||||
|
delay(250);
|
||||||
|
}else{
|
||||||
|
Stw_data.displayindex+=1;
|
||||||
|
delay(250);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(Stw_data.buttonState1){
|
||||||
|
if(Stw_data.displayindex<=0){
|
||||||
|
Stw_data.displayindex = sizeof(bezeichnungen)/sizeof(String)-3;
|
||||||
|
delay(250);
|
||||||
|
}else{
|
||||||
|
Stw_data.displayindex-=1;
|
||||||
|
delay(250);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(vergleichsindex!=Stw_data.displayindex){
|
||||||
|
tft.clear();
|
||||||
|
vergleichsindex=Stw_data.displayindex;
|
||||||
|
}
|
||||||
|
int a = sizeof(bezeichnungen[Stw_data.displayindex]);
|
||||||
|
int g = sizeof(bezeichnungen[Stw_data.displayindex+1]);
|
||||||
|
int h = sizeof(bezeichnungen[Stw_data.displayindex+2]);
|
||||||
|
char d[a];
|
||||||
|
char e[g];
|
||||||
|
char f[h];
|
||||||
|
bezeichnungen[Stw_data.displayindex].toCharArray(d,a);
|
||||||
|
bezeichnungen[Stw_data.displayindex+1].toCharArray(e,g);
|
||||||
|
bezeichnungen[Stw_data.displayindex+2].toCharArray(f,h);
|
||||||
|
char b[2];
|
||||||
|
char c[5];
|
||||||
|
char i[5];
|
||||||
|
char j[5];
|
||||||
|
char k[5];
|
||||||
|
char m[5];
|
||||||
|
String str=String(int(get_value(0)));
|
||||||
|
/*if(str.equals(String(0))){
|
||||||
|
str = "N";
|
||||||
|
}*/
|
||||||
|
String str1;
|
||||||
|
String str2;
|
||||||
|
String str3;
|
||||||
|
if(Stw_data.displayindex+1==0 or Stw_data.displayindex+1==2 or Stw_data.displayindex+1==1 or Stw_data.displayindex+1==10 or Stw_data.displayindex+1==7 or Stw_data.displayindex+1==11 or Stw_data.displayindex+1==12 or Stw_data.displayindex+1==13){
|
||||||
|
str1=String(int(get_value(Stw_data.displayindex+1)));
|
||||||
|
}else{
|
||||||
|
str1=String(get_value(Stw_data.displayindex+1));
|
||||||
|
}
|
||||||
|
/*if(Stw_data.displayindex+1 == 10){
|
||||||
|
if(str1.equals(String(1))){
|
||||||
|
str1 = "PC";
|
||||||
|
}else if(str1.equals(String(2))){
|
||||||
|
str1 = "BSE";
|
||||||
|
}else if(str1.equals(String(3))){
|
||||||
|
str1 = "APS";
|
||||||
|
}else if(str1.equals(String(4))){
|
||||||
|
str1 = "ETB";
|
||||||
|
}else if(str1.equals(String(0))){
|
||||||
|
str1 = "None";
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
if(Stw_data.displayindex+2==0 or Stw_data.displayindex+2==2 or Stw_data.displayindex+2==1 or Stw_data.displayindex+2==10 or Stw_data.displayindex+2==7 or Stw_data.displayindex+2==11 or Stw_data.displayindex+2==12 or Stw_data.displayindex+2==13){
|
||||||
|
str2=String(int(get_value(Stw_data.displayindex+2)));
|
||||||
|
}else{
|
||||||
|
str2=String(get_value(Stw_data.displayindex+2));
|
||||||
|
}
|
||||||
|
/*if(Stw_data.displayindex+2 == 10){
|
||||||
|
if(str2.equals(String(1))){
|
||||||
|
str2 = "PC";
|
||||||
|
}else if(str2.equals(String(2))){
|
||||||
|
str2 = "BSE";
|
||||||
|
}else if(str2.equals(String(3))){
|
||||||
|
str2 = "APS";
|
||||||
|
}else if(str2.equals(String(4))){
|
||||||
|
str2 = "ETB";
|
||||||
|
}else if(str2.equals(String(0))){
|
||||||
|
str2 = "None";
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
if(Stw_data.displayindex+3==0 or Stw_data.displayindex+3==2 or Stw_data.displayindex+3==1 or Stw_data.displayindex+3==10 or Stw_data.displayindex+3==7 or Stw_data.displayindex+3==11 or Stw_data.displayindex+3==12 or Stw_data.displayindex+3==13){
|
||||||
|
str3=String(int(get_value(Stw_data.displayindex+3)));
|
||||||
|
}else{
|
||||||
|
str3=String(get_value(Stw_data.displayindex+3));
|
||||||
|
}
|
||||||
|
/*if(Stw_data.displayindex+3 == 10){
|
||||||
|
if(str3.equals(String(1))){
|
||||||
|
str3 = "PC";
|
||||||
|
}else if(str3.equals(String(2))){
|
||||||
|
str3 = "BSE";
|
||||||
|
}else if(str3.equals(String(3))){
|
||||||
|
str3 = "APS";
|
||||||
|
}else if(str3.equals(String(4))){
|
||||||
|
str3 = "ETB";
|
||||||
|
}else if(str3.equals(String(0))){
|
||||||
|
str3 = "None";
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
String str5=String(Vehicle_data.revol/2);
|
||||||
|
String str4=String(0.0514*Vehicle_data.p_fuel);
|
||||||
|
str.toCharArray(b,2);
|
||||||
|
str1.toCharArray(c,5);
|
||||||
|
str2.toCharArray(i,5);
|
||||||
|
str3.toCharArray(j,5);
|
||||||
|
str4.toCharArray(k,5);
|
||||||
|
str5.toCharArray(m,5);
|
||||||
|
sizeaneu = strlen(c);
|
||||||
|
sizebneu = strlen(i);
|
||||||
|
sizecneu = strlen(j);
|
||||||
|
sizedneu = strlen(k);
|
||||||
|
sizeeneu = strlen(m);
|
||||||
|
if(sizeaalt!=sizeaneu){
|
||||||
|
tft.clear();
|
||||||
|
sizeaalt=sizeaneu;
|
||||||
|
}
|
||||||
|
if(sizebalt!=sizebneu){
|
||||||
|
tft.clear();
|
||||||
|
sizebalt=sizebneu;
|
||||||
|
}
|
||||||
|
if(sizecalt!=sizecneu){
|
||||||
|
tft.clear();
|
||||||
|
sizecalt=sizecneu;
|
||||||
|
}
|
||||||
|
if(sizedalt!=sizedneu){
|
||||||
|
tft.clear();
|
||||||
|
sizedalt=sizedneu;
|
||||||
|
}
|
||||||
|
if(sizeealt!=sizeeneu){
|
||||||
|
tft.clear();
|
||||||
|
sizeealt=sizeeneu;
|
||||||
|
}
|
||||||
|
tft.setTextSize(6,8);
|
||||||
|
tft.drawText(132, 0, 'L', b);
|
||||||
|
tft.setTextSize(2,7);
|
||||||
|
tft.drawText(0, 20, 'L', k);
|
||||||
|
tft.drawText(240, 20, 'L', m);
|
||||||
|
tft.drawText(0,130, 'L', c);
|
||||||
|
tft.drawText(120, 130, 'L', i);
|
||||||
|
tft.drawText(240,130, 'L', j);
|
||||||
|
tft.setTextSize(1,1);
|
||||||
|
tft.drawText(136,116, 'L', "Energiemodus");
|
||||||
|
tft.drawText(0,116, 'L', "U_Batt");
|
||||||
|
tft.drawText(240,116, 'L', "Drehzahl");
|
||||||
|
tft.drawText(0,226, 'L', d);
|
||||||
|
tft.drawText(120,226, 'L', e);
|
||||||
|
tft.drawText(240,226, 'L', f);
|
||||||
|
/*if (cleaner){
|
||||||
|
tft.setTextSize(5,8);
|
||||||
|
tft.drawText(0, 14, 'C', "FaSTTUBe"); // draw some text
|
||||||
|
tft.setTextSize(4,4);
|
||||||
|
tft.drawText(24, 120, 'C', "insert coin"); // draw some text
|
||||||
|
tft.drawText(0, 180, 'C', "to continue");
|
||||||
|
cleaner = false;
|
||||||
|
}else{
|
||||||
|
tft.setTextSize(5,8);
|
||||||
|
tft.drawText(0, 14, 'C', "FaSTTUBe"); // draw some text
|
||||||
|
tft.setTextSize(4,4);
|
||||||
|
tft.drawText(24, 120, 'C', " "); // draw some text
|
||||||
|
tft.drawText(0, 180, 'C', " ");
|
||||||
|
cleaner = true;
|
||||||
|
}
|
||||||
|
delay(80);*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_trc(){
|
||||||
|
if(trcalt!=Stw_data.trc or Stw_data.buttonStateEnc1 == HIGH){
|
||||||
|
tft.clear();
|
||||||
|
tft.setTextSize(7,8);
|
||||||
|
tft.setDisplayColor(EA_WHITE,EA_RED);
|
||||||
|
tft.setTextColor(EA_WHITE,EA_RED);
|
||||||
|
char trcanzeige[7];
|
||||||
|
String str = String("ARB:");
|
||||||
|
if(Stw_data.trc==11){
|
||||||
|
str+="ED";
|
||||||
|
}else{
|
||||||
|
str+=String(Stw_data.trc);
|
||||||
|
}
|
||||||
|
str.toCharArray(trcanzeige,7);
|
||||||
|
tft.drawText(0,0,'L'," ");
|
||||||
|
tft.drawText(0,60,'L'," ");
|
||||||
|
tft.drawText(0,120,'L'," ");
|
||||||
|
tft.drawText(0,180,'L'," ");
|
||||||
|
tft.drawText(15,68,'L',trcanzeige);
|
||||||
|
trccounter = 0;
|
||||||
|
trcalt = Stw_data.trc;
|
||||||
|
trctimer = true;
|
||||||
|
}else if(trccounter >= 255){
|
||||||
|
tft.setDisplayColor(EA_WHITE,EA_BLACK);
|
||||||
|
tft.setTextColor(EA_WHITE,EA_BLACK);
|
||||||
|
tft.clear();
|
||||||
|
trctimer = false;
|
||||||
|
}else{
|
||||||
|
trccounter+=1;
|
||||||
|
delay(5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_mode(){
|
||||||
|
if(modealt!=Stw_data.mode or Stw_data.buttonStateEnc2 == HIGH){
|
||||||
|
tft.clear();
|
||||||
|
tft.setTextSize(6,8);
|
||||||
|
tft.setDisplayColor(EA_WHITE,EA_RED);
|
||||||
|
tft.setTextColor(EA_WHITE,EA_RED);
|
||||||
|
char modeanzeige[7];
|
||||||
|
String str = String("MODE:");
|
||||||
|
str+=String(Stw_data.mode);
|
||||||
|
str.toCharArray(modeanzeige,7);
|
||||||
|
tft.drawText(0,0,'L'," ");
|
||||||
|
tft.drawText(0,60,'L'," ");
|
||||||
|
tft.drawText(0,120,'L'," ");
|
||||||
|
tft.drawText(0,180,'L'," ");
|
||||||
|
tft.drawText(15,68,'L',modeanzeige);
|
||||||
|
modecounter = 0;
|
||||||
|
modealt = Stw_data.mode;
|
||||||
|
modetimer = true;
|
||||||
|
}else if(modecounter >= 255){
|
||||||
|
tft.setDisplayColor(EA_WHITE,EA_BLACK);
|
||||||
|
tft.setTextColor(EA_WHITE,EA_BLACK);
|
||||||
|
tft.clear();
|
||||||
|
modetimer = false;
|
||||||
|
}else{
|
||||||
|
modecounter+=1;
|
||||||
|
delay(5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void alarm(String textstr){
|
||||||
|
uint8_t x = 1;;
|
||||||
|
char text[7];
|
||||||
|
textstr.toCharArray(text,7);
|
||||||
|
tft.setTextSize(8,8);
|
||||||
|
while(x==1){
|
||||||
|
if(!tft._displaybool){
|
||||||
|
tft.setTextColor(EA_BLACK,EA_RED);
|
||||||
|
tft.fillDisplayColor(EA_RED);
|
||||||
|
tft.drawText(5,68,'L',text);
|
||||||
|
}
|
||||||
|
for (int j = 0; j < 16; j++){
|
||||||
|
digitalWrite(led_s[j], HIGH);
|
||||||
|
}
|
||||||
|
delay(100);
|
||||||
|
if(!tft._displaybool){
|
||||||
|
tft.setTextColor(EA_BLACK,EA_WHITE);
|
||||||
|
tft.fillDisplayColor(EA_WHITE);
|
||||||
|
tft.drawText(5,68,'L',text);
|
||||||
|
}
|
||||||
|
for (int j = 0; j < 16; j++){
|
||||||
|
digitalWrite(led_s[j], LOW);
|
||||||
|
}
|
||||||
|
delay(100);
|
||||||
|
if(Stw_data.buttonState1 & Stw_data.buttonState4){
|
||||||
|
x=0;
|
||||||
|
tft.setTextColor(EA_WHITE,EA_BLACK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "EDIPTFT.h"
|
||||||
|
#include "FT_2018e_STW_CAN.h"
|
||||||
|
#include "FT18e_STW_INIT.h"
|
||||||
|
#ifndef FT18e_STW_DISPLAY_h
|
||||||
|
#define FT18e_STW_DISPLAY_h
|
||||||
|
|
||||||
|
#define EA_BLACK 1
|
||||||
|
#define EA_RED 3
|
||||||
|
#define EA_GREY 10
|
||||||
|
#define EA_WHITE 8
|
||||||
|
|
||||||
|
#define MOSI 75
|
||||||
|
#define MISO 74
|
||||||
|
#define CLK 76
|
||||||
|
#define disp_cs 42
|
||||||
|
#define reset 43
|
||||||
|
#define writeprotect 52
|
||||||
|
|
||||||
|
|
||||||
|
void init_display(void);
|
||||||
|
void update_display(void);
|
||||||
|
double get_value(int a);
|
||||||
|
void display_trc(void);
|
||||||
|
void display_mode(void);
|
||||||
|
void alarm(String text);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,200 @@
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "FT18e_STW_INIT.h"
|
||||||
|
#include "Bounce2.h"
|
||||||
|
#include "RotaryEncoder.h"
|
||||||
|
|
||||||
|
volatile stw_data_type Stw_data = {0}; //alles mit 0 initialisieren
|
||||||
|
volatile vehicle_data_type Vehicle_data = {0}; //alles mit 0 initialisieren
|
||||||
|
bool enc1PinALast,enc1PinANow,enc2PinALast,enc2PinANow;
|
||||||
|
int led[] = {led1,led2,led3,led4,led5,led6,led7,led8,led9,led10,led11,led12,led13,led14,led15,led16};
|
||||||
|
bool entprell;
|
||||||
|
int buttons[] = {button1,button2,button3,button4,button5,button6,enc1PinS,enc2PinS};
|
||||||
|
Bounce debouncer[8];
|
||||||
|
double val = 0;
|
||||||
|
double val2 = 0;
|
||||||
|
RotaryEncoder encoder(enc1PinA,enc1PinB,1,1,50);
|
||||||
|
RotaryEncoder encoder2(enc2PinA,enc2PinB,1,1,50);
|
||||||
|
///////////////////////////////////////////////////
|
||||||
|
// functions
|
||||||
|
///////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void set_pins(){
|
||||||
|
pinMode (l,OUTPUT);
|
||||||
|
for (int thisLed = 0; thisLed < sizeof(led)/sizeof(int); thisLed++) {
|
||||||
|
pinMode(led[thisLed], OUTPUT);
|
||||||
|
}
|
||||||
|
/*pinMode(button1, INPUT);
|
||||||
|
pinMode(button2, INPUT);
|
||||||
|
pinMode(button3, INPUT);
|
||||||
|
pinMode(button4, INPUT);
|
||||||
|
pinMode(button5, INPUT);
|
||||||
|
pinMode(button6, INPUT);*/
|
||||||
|
pinMode(enc1PinA, INPUT);
|
||||||
|
pinMode(enc1PinB, INPUT);
|
||||||
|
//pinMode(enc1PinS, INPUT);
|
||||||
|
pinMode(enc2PinA, INPUT);
|
||||||
|
pinMode(enc2PinB, INPUT);
|
||||||
|
//pinMode(enc2PinS, INPUT);
|
||||||
|
//Stw_data.i=0;
|
||||||
|
enc1PinALast=LOW;
|
||||||
|
enc1PinANow=LOW;
|
||||||
|
enc2PinALast=LOW;
|
||||||
|
enc2PinANow=LOW;
|
||||||
|
for(int i = 0; i < 8; i++){
|
||||||
|
pinMode(buttons[i], INPUT);
|
||||||
|
debouncer[i].attach(buttons[i]);
|
||||||
|
debouncer[i].interval(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void read_buttons(){
|
||||||
|
/*entprell = digitalRead(button3);
|
||||||
|
delay(10);
|
||||||
|
if(digitalRead(button3)){
|
||||||
|
Stw_data.Stw_auto_shift = entprell;
|
||||||
|
}
|
||||||
|
entprell = digitalRead(button2);
|
||||||
|
delay(10);
|
||||||
|
if(digitalRead(button2)){
|
||||||
|
Stw_data.Stw_neutral = entprell;
|
||||||
|
}
|
||||||
|
entprell = digitalRead(button1);
|
||||||
|
delay(10);
|
||||||
|
if(digitalRead(button1)){
|
||||||
|
Stw_data.buttonState1 = entprell;
|
||||||
|
}
|
||||||
|
entprell = digitalRead(button6);
|
||||||
|
delay(10);
|
||||||
|
if(digitalRead(button6)){
|
||||||
|
Stw_data.Stw_shift_up = entprell;
|
||||||
|
}
|
||||||
|
entprell = digitalRead(button5);
|
||||||
|
delay(10);
|
||||||
|
if(digitalRead(button5)){
|
||||||
|
Stw_data.Stw_shift_down = entprell;
|
||||||
|
}
|
||||||
|
entprell = digitalRead(button4);
|
||||||
|
delay(10);
|
||||||
|
if(digitalRead(button4)){
|
||||||
|
Stw_data.buttonState4 = entprell;
|
||||||
|
}
|
||||||
|
entprell = digitalRead(enc1PinS);
|
||||||
|
delay(10);
|
||||||
|
if(digitalRead(enc1PinS)){
|
||||||
|
Stw_data.buttonStateEnc1 = entprell;
|
||||||
|
}
|
||||||
|
entprell = digitalRead(enc2PinS);
|
||||||
|
delay(10);
|
||||||
|
if(digitalRead(enc2PinS)){
|
||||||
|
Stw_data.buttonStateEnc2 = entprell;
|
||||||
|
}*/
|
||||||
|
Stw_data.Stw_auto_shift = digitalRead(button3);
|
||||||
|
Stw_data.Stw_neutral = digitalRead(button2);
|
||||||
|
Stw_data.buttonState1 = digitalRead(button1);
|
||||||
|
Stw_data.Stw_shift_up = digitalRead(button6);
|
||||||
|
Stw_data.Stw_shift_down = digitalRead(button5);
|
||||||
|
Stw_data.buttonState4 = digitalRead(button4);
|
||||||
|
Stw_data.buttonStateEnc1 = digitalRead(enc1PinS);
|
||||||
|
Stw_data.buttonStateEnc2 = digitalRead(enc2PinS);
|
||||||
|
|
||||||
|
/*for(int i = 0;i < 8; i++){
|
||||||
|
debouncer[i].update();
|
||||||
|
}
|
||||||
|
debouncer[2].update();
|
||||||
|
if(debouncer[2].fell()){
|
||||||
|
Stw_data.Stw_auto_shift = HIGH;
|
||||||
|
}
|
||||||
|
if(debouncer[1].fell()){
|
||||||
|
Stw_data.Stw_neutral = digitalRead(button2);
|
||||||
|
}
|
||||||
|
if(debouncer[0].fell()){
|
||||||
|
Stw_data.buttonState1 = digitalRead(button1);
|
||||||
|
}
|
||||||
|
if(debouncer[5].fell()){
|
||||||
|
Stw_data.Stw_shift_up = digitalRead(button6);
|
||||||
|
}
|
||||||
|
if(debouncer[4].fell()){
|
||||||
|
Stw_data.Stw_shift_down = digitalRead(button5);
|
||||||
|
}
|
||||||
|
if(debouncer[3].fell()){
|
||||||
|
Stw_data.buttonState4 = digitalRead(button4);
|
||||||
|
}
|
||||||
|
if(debouncer[6].fell()){
|
||||||
|
Stw_data.buttonStateEnc1 = digitalRead(enc1PinS);
|
||||||
|
}
|
||||||
|
if(debouncer[7].fell()){
|
||||||
|
Stw_data.buttonStateEnc2 = digitalRead(enc2PinS);
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void read_rotary(){
|
||||||
|
int enc = encoder.readEncoder();
|
||||||
|
int enc2 = encoder2.readEncoder();
|
||||||
|
if(enc != 0){
|
||||||
|
val = val +0.5*enc;
|
||||||
|
if (val==1 or val ==-1){
|
||||||
|
if(Stw_data.trc==0 and enc<0){
|
||||||
|
Stw_data.trc = 11;
|
||||||
|
}else if(Stw_data.trc==11 and enc>0){
|
||||||
|
Stw_data.trc=0;
|
||||||
|
}else{
|
||||||
|
Stw_data.trc = Stw_data.trc + enc;
|
||||||
|
}
|
||||||
|
val = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*enc1PinANow = digitalRead(enc1PinA);
|
||||||
|
enc2PinANow = digitalRead(enc2PinA);
|
||||||
|
if ((enc1PinALast == LOW) && (enc1PinANow == HIGH)) {
|
||||||
|
if (digitalRead(enc1PinB) == HIGH) {
|
||||||
|
if(Stw_data.trc==0){
|
||||||
|
Stw_data.trc = 5;
|
||||||
|
}else{
|
||||||
|
Stw_data.trc--;
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
if(Stw_data.trc==5){
|
||||||
|
Stw_data.trc=0;
|
||||||
|
}else{
|
||||||
|
Stw_data.trc++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enc1PinALast = enc1PinANow;
|
||||||
|
/*if (Stw_data.buttonStateEnc1 == HIGH){
|
||||||
|
digitalWrite(led[Stw_data.i], HIGH);
|
||||||
|
}*/
|
||||||
|
if(enc2 != 0){
|
||||||
|
val2 = val2 +0.5*enc2;
|
||||||
|
if(val2==1 or val2==-1){
|
||||||
|
if((Stw_data.mode==1 or Stw_data.mode==0) and enc2<0){
|
||||||
|
Stw_data.mode = 5;
|
||||||
|
}else if(Stw_data.mode==5 and enc2>0){
|
||||||
|
Stw_data.mode=1;
|
||||||
|
}else{
|
||||||
|
Stw_data.mode = Stw_data.mode + enc2;
|
||||||
|
}
|
||||||
|
val2=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*if ((enc2PinALast == LOW) && (enc2PinANow == HIGH)) {
|
||||||
|
//if(enc2PinALast != enc2PinANow){
|
||||||
|
if (digitalRead(enc2PinB) == HIGH) {
|
||||||
|
if(Stw_data.i==0){
|
||||||
|
Stw_data.i = sizeof(led)/sizeof(int)-1;
|
||||||
|
}else{
|
||||||
|
Stw_data.i--;
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
if(Stw_data.i==sizeof(led)/sizeof(int)-1){
|
||||||
|
Stw_data.i=0;
|
||||||
|
}else{
|
||||||
|
Stw_data.i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enc2PinALast = enc2PinANow;*/
|
||||||
|
/*if (Stw_data.buttonStateEnc2 == HIGH){
|
||||||
|
digitalWrite(led[Stw_data.i], HIGH);
|
||||||
|
}*/
|
||||||
|
}
|
|
@ -0,0 +1,101 @@
|
||||||
|
#include "Arduino.h"
|
||||||
|
#ifndef FT18e_STW_Init
|
||||||
|
#define FT18e_STW_Init
|
||||||
|
|
||||||
|
#define l 78 //test_led
|
||||||
|
#define led1 12//PD8
|
||||||
|
#define led2 11//PD7
|
||||||
|
#define led3 9//PC21
|
||||||
|
#define led4 8//PC22
|
||||||
|
#define led5 7//PC23
|
||||||
|
#define led6 6//PC24
|
||||||
|
#define led7 5//PC25
|
||||||
|
#define led8 4//PC26 und PA29
|
||||||
|
#define led9 3//PC28
|
||||||
|
#define led10 2//PB25
|
||||||
|
#define led11 10//PC29 und PA28
|
||||||
|
#define led12 22//PB26
|
||||||
|
#define led13 19//PA10
|
||||||
|
#define led14 13//PB27
|
||||||
|
#define led15 17//PA12
|
||||||
|
#define led16 18//PA11
|
||||||
|
#define button1 48//bl
|
||||||
|
#define button2 47//gl
|
||||||
|
#define button3 44//gr
|
||||||
|
#define button4 46//br
|
||||||
|
#define button5 45//sl
|
||||||
|
#define button6 49//sr
|
||||||
|
#define enc1PinA 37
|
||||||
|
#define enc1PinB 38
|
||||||
|
#define enc1PinS 35
|
||||||
|
#define enc2PinA 40
|
||||||
|
#define enc2PinB 41
|
||||||
|
#define enc2PinS 39
|
||||||
|
|
||||||
|
|
||||||
|
// define Drehzahlgrenzen TODOOOO
|
||||||
|
#define RPM_THRES_1 1000
|
||||||
|
#define RPM_THRES_2 6000
|
||||||
|
#define RPM_THRES_3 7000
|
||||||
|
#define RPM_THRES_4 8000
|
||||||
|
#define RPM_THRES_5 10000
|
||||||
|
#define RPM_THRES_6 14000
|
||||||
|
#define RPM_THRES_7 17000
|
||||||
|
#define RPM_THRES_8 18000
|
||||||
|
#define RPM_THRES_9 20000
|
||||||
|
#define RPM_THRES_10 20000
|
||||||
|
|
||||||
|
|
||||||
|
void set_pins(void);
|
||||||
|
void read_buttons(void);
|
||||||
|
void read_rotary(void); // read rotary switches
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t Stw_shift_up; // 1 Bit 0
|
||||||
|
uint8_t Stw_shift_down; // 1 Bit 1
|
||||||
|
uint8_t Stw_neutral; // 1 Bit 2
|
||||||
|
uint8_t Stw_auto_shift; // 1 Bit 3
|
||||||
|
uint8_t buttonState1; // 1 Bit 4
|
||||||
|
uint8_t buttonState4; // 1 Bit 5
|
||||||
|
//bool CAN_toggle;
|
||||||
|
//bool CAN_check;
|
||||||
|
//uint8_t i; //Index linker Drehschalter
|
||||||
|
uint8_t buttonStateEnc1; // button
|
||||||
|
//uint8_t br; //test mode : mittlere Drehschalter position
|
||||||
|
uint8_t buttonStateEnc2; //button
|
||||||
|
uint8_t displayindex; //index für Displayanzeige
|
||||||
|
uint8_t error_type; //Extrainfos über Error-LED
|
||||||
|
uint8_t trc;
|
||||||
|
uint8_t mode;
|
||||||
|
|
||||||
|
} stw_data_type;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t e_thro; // E-Drossel
|
||||||
|
uint8_t g_auto; // Auto-Shift
|
||||||
|
uint8_t gear; // Gang
|
||||||
|
uint16_t revol; // Drehzahl
|
||||||
|
uint8_t t_oil; // Öl-Motor-Temperatur
|
||||||
|
uint8_t t_mot; // Wasser-Motor-Temperatur
|
||||||
|
uint8_t t_air; // LLK-Temperatur
|
||||||
|
uint8_t u_batt; // Batteriespannung
|
||||||
|
uint8_t rev_lim; // Drehzahllimit Bit
|
||||||
|
uint8_t p_wat;
|
||||||
|
uint8_t p_fuel;
|
||||||
|
uint8_t p_oil;
|
||||||
|
uint8_t p_brake_front;
|
||||||
|
uint8_t p_brake_rear;
|
||||||
|
uint8_t speed_fl;
|
||||||
|
uint8_t speed_fr;
|
||||||
|
uint8_t speed;
|
||||||
|
|
||||||
|
} vehicle_data_type;
|
||||||
|
|
||||||
|
|
||||||
|
extern volatile stw_data_type Stw_data;
|
||||||
|
extern volatile vehicle_data_type Vehicle_data;
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,262 @@
|
||||||
|
/*
|
||||||
|
FT_2018_STW_CAN.cpp
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "DueTimer.h"
|
||||||
|
#include "due_can.h"
|
||||||
|
#include "FT_2018_STW_CAN.h"
|
||||||
|
#include "FT18_STW_INIT.h"
|
||||||
|
|
||||||
|
CAN_FRAME can_0_msg;
|
||||||
|
//can_1_msg.id = 0x110;
|
||||||
|
int can_0_temp_data = 0;
|
||||||
|
int leds[] = {led1,led2,led3,led4,led5,led6,led7,led8,led9,led10,led11,led12,led13,led14,led15,led16};
|
||||||
|
|
||||||
|
|
||||||
|
void Init_Can_0(){
|
||||||
|
Can0.begin(1000000); // set CAN0 baud to 1kbit/s and don`t use enable pin!
|
||||||
|
Can0.setNumTXBoxes(1); // reserves mailbox 0 for tx only 8 mailboxes are available (the other 7 mailboxes are for rx)
|
||||||
|
Can0.watchFor(0x502); // set CAN RX filter for ID 0x502 and reserves mailbox 1 for rx
|
||||||
|
Can0.watchFor(0x504);
|
||||||
|
Can0.watchFor(0x500);
|
||||||
|
Can0.watchFor(0x773); // set CAN RX filter for ID 0x773 and reserves mailbox 3 for rx
|
||||||
|
Can0.watchFor(0x775);
|
||||||
|
// Can0.watchFor(0x777); // set CAN RX filter for ID 0x777 and reserves mailbox 5 for rx
|
||||||
|
Can0.watchFor(0x779); // set CAN RX filter for ID 0x779 and reserves mailbox 6 for rx
|
||||||
|
Can0.watchFor(0x77A);
|
||||||
|
Can0.setGeneralCallback(Receive_Can_0);
|
||||||
|
Timer3.attachInterrupt(Send_0x110); // set send interrupt
|
||||||
|
Timer3.start(10000); // Calls every 10ms
|
||||||
|
}
|
||||||
|
|
||||||
|
void Send_0x110(){
|
||||||
|
read_buttons();
|
||||||
|
read_rotary();
|
||||||
|
can_0_msg.id = 0x110;
|
||||||
|
can_0_msg.fid = 0;
|
||||||
|
can_0_msg.rtr = 0;
|
||||||
|
can_0_msg.priority = 0;
|
||||||
|
can_0_msg.length = 2;
|
||||||
|
can_0_msg.extended = 0;
|
||||||
|
can_0_temp_data = 0;
|
||||||
|
can_0_temp_data |= Stw_data.Stw_shift_up & 0b00000001;
|
||||||
|
can_0_temp_data |= Stw_data.Stw_shift_down << 1 & 0b00000010;
|
||||||
|
can_0_temp_data |= Stw_data.Stw_neutral << 2 & 0b00000100;
|
||||||
|
can_0_temp_data |= Stw_data.Stw_auto_shift << 3 & 0b00001000;
|
||||||
|
can_0_temp_data |= Stw_data.buttonStateEnc1 << 5 & 0b00100000; //pitlane
|
||||||
|
can_0_msg.data.byte[0] = can_0_temp_data;
|
||||||
|
can_0_msg.data.byte[1] = Stw_data.trc & 0b00001111;
|
||||||
|
can_0_msg.data.byte[2] = Stw_data.mode & 0b00000111;
|
||||||
|
if ((Stw_data.Stw_auto_shift << 3 & 0b00001000)){
|
||||||
|
if(Vehicle_data.g_auto){
|
||||||
|
Vehicle_data.g_auto = false;
|
||||||
|
}else{
|
||||||
|
Vehicle_data.g_auto = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Can0.sendFrame(can_0_msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Receive_Can_0(CAN_FRAME *temp_message){
|
||||||
|
switch (temp_message->id) {
|
||||||
|
//g_auto
|
||||||
|
case 0x502:{ // eDrossel error bit
|
||||||
|
Vehicle_data.e_thro = (temp_message->data.byte[0] & 0x80) | (temp_message->data.byte[0] & 0x40) | (temp_message->data.byte[0] & 0x20) | (temp_message->data.byte[0] & 0x10); // bit 4-7
|
||||||
|
|
||||||
|
if(temp_message->data.byte[0] & 0x80){
|
||||||
|
Stw_data.error_type = 1;//"pc_error";
|
||||||
|
}
|
||||||
|
if(temp_message->data.byte[0] & 0x40){
|
||||||
|
Stw_data.error_type = 2;//"bse_error";
|
||||||
|
}
|
||||||
|
if(temp_message->data.byte[0] & 0x20){
|
||||||
|
Stw_data.error_type = 3;//"aps_error";
|
||||||
|
}
|
||||||
|
if(temp_message->data.byte[0] & 0x10){
|
||||||
|
Stw_data.error_type = 4;//"etb_error";
|
||||||
|
}
|
||||||
|
//can_1_temp_data |= g_etb_e << 4;
|
||||||
|
//can_1_temp_data |= g_aps_e << 5;
|
||||||
|
//can_1_temp_data |= g_bse_e << 6;
|
||||||
|
//can_1_temp_data |= g_pc_e << 7;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x504:{ //autoshift+gear
|
||||||
|
//Vehicle_data.g_auto = (temp_message->data.byte[1]) >> 4;
|
||||||
|
Vehicle_data.gear = (temp_message->data.byte[1]) >> 5;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x773:{ // rpm
|
||||||
|
Vehicle_data.revol = (temp_message->data.byte[4] | temp_message->data.byte[3] << 8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x779:{ // battery voltage
|
||||||
|
Vehicle_data.u_batt = temp_message->data.byte[6];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*case 0x77A: // revolution limit bit
|
||||||
|
Vehicle_data.rev_lim = (temp_message->data.byte[3] & 0x20) >> 4;
|
||||||
|
switch(temp_message->data.byte[0]) {
|
||||||
|
case 0x02: // temp. intercooler
|
||||||
|
Vehicle_data.t_air = temp_message->data.byte[7];
|
||||||
|
break;
|
||||||
|
case 0x05: // temp. water
|
||||||
|
Vehicle_data.t_mot = temp_message->data.byte[4];
|
||||||
|
break;
|
||||||
|
case 0x04: // temp. oil
|
||||||
|
Vehicle_data.t_oil = temp_message->data.byte[5];
|
||||||
|
case 0x01: {
|
||||||
|
Vehicle_data.p_wat = temp_message->data.byte[6];
|
||||||
|
Vehicle_data.p_fuel = temp_message->data.byte[7];
|
||||||
|
Vehicle_data.p_oil = temp_message->data.byte[5];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;*/
|
||||||
|
case 0x77A:{//temp und p
|
||||||
|
//g_ms4_idle_b = (temp_message->data.byte[2] & 0b10000000) >> 7;
|
||||||
|
//g_ms4_engine_status = (temp_message->data.byte[3] & 0b01000000) >> 6;
|
||||||
|
//g_ms4_ignoff_b = (temp_message->data.byte[3] & 0b10000000) >> 7;
|
||||||
|
|
||||||
|
if ( temp_message->data.byte[0] == 1){
|
||||||
|
Vehicle_data.p_oil = temp_message->data.byte[5];
|
||||||
|
Vehicle_data.p_fuel = temp_message->data.byte[7];
|
||||||
|
}
|
||||||
|
else if ( temp_message->data.byte[0] == 2){
|
||||||
|
Vehicle_data.t_air = temp_message->data.byte[7];
|
||||||
|
}
|
||||||
|
else if ( temp_message->data.byte[0] == 4){
|
||||||
|
Vehicle_data.t_oil = temp_message->data.byte[5];
|
||||||
|
}
|
||||||
|
else if ( temp_message->data.byte[0] == 5){
|
||||||
|
Vehicle_data.t_mot = temp_message->data.byte[4];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x775:{//speed
|
||||||
|
Vehicle_data.speed_fl = 2*(temp_message->data.byte[2]);
|
||||||
|
Vehicle_data.speed_fr = 2*(temp_message->data.byte[3]);
|
||||||
|
Vehicle_data.speed = (Vehicle_data.speed_fl+Vehicle_data.speed_fr)/2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*case 0x777:{//m4_gear
|
||||||
|
Vehicle_data.gear = temp_message->data.byte[0];
|
||||||
|
break;
|
||||||
|
}*/
|
||||||
|
case 0x500:{
|
||||||
|
Vehicle_data.p_brake_front = temp_message->data.byte[1];
|
||||||
|
Vehicle_data.p_brake_rear = temp_message->data.byte[2];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_LED(){
|
||||||
|
//Copyright Michael Dietzel
|
||||||
|
//m.dietzel@fasttube.de
|
||||||
|
//Edit Michael Witt 05-2015
|
||||||
|
//m.witt@fasttube.de
|
||||||
|
|
||||||
|
//EDIT BAHA ZARROUKI 05-2107
|
||||||
|
//z.baha@fasttube.de
|
||||||
|
|
||||||
|
// alle Werte als Hex-Werte angegeben
|
||||||
|
bool t_oil = (Vehicle_data.t_oil - 40) >= 0x96; // 150°C temp.oil
|
||||||
|
bool t_air = (Vehicle_data.t_air - 40) >= 0x3C; // 60°C temp.llk
|
||||||
|
bool t_mot = ((Vehicle_data.t_mot - 40) >= 0x69) and ((Vehicle_data.t_mot - 40)!=0xC8); // 105°C temp.water und !=200
|
||||||
|
|
||||||
|
bool g_auto = Vehicle_data.g_auto;
|
||||||
|
bool u_batt = Vehicle_data.u_batt <= 0xB1; // 12.5V batt.spann.
|
||||||
|
bool e_dros = Vehicle_data.e_thro; // error-bit
|
||||||
|
|
||||||
|
bool rev_lim = Vehicle_data.rev_lim;
|
||||||
|
|
||||||
|
uint16_t rev = Vehicle_data.revol;
|
||||||
|
|
||||||
|
/*if(Vehicle_data.rev_lim){
|
||||||
|
for (int j = 0; j < 10; j++){
|
||||||
|
digitalWrite(leds[j], HIGH);
|
||||||
|
//analogWrite(leds[j], STW_data.br); //nur eine der zwei zeilen
|
||||||
|
}
|
||||||
|
delay(100);
|
||||||
|
for (int j = 0; j < 10; j++){
|
||||||
|
digitalWrite(leds[j], LOW);
|
||||||
|
}
|
||||||
|
delay(100);
|
||||||
|
}else{*/
|
||||||
|
/*uint8_t helligkeit = 20;
|
||||||
|
if(RPM_THRES_1 <= rev){
|
||||||
|
analogWrite(led1, helligkeit);
|
||||||
|
}else{
|
||||||
|
analogWrite(led1, 0);
|
||||||
|
}
|
||||||
|
if(RPM_THRES_2 <= rev){
|
||||||
|
analogWrite(led2, helligkeit);
|
||||||
|
}else{
|
||||||
|
analogWrite(led2, 0);
|
||||||
|
}
|
||||||
|
if(RPM_THRES_3 <= rev){
|
||||||
|
analogWrite(led3, helligkeit);
|
||||||
|
}else{
|
||||||
|
analogWrite(led3, 0);
|
||||||
|
}
|
||||||
|
if(RPM_THRES_4 <= rev){
|
||||||
|
analogWrite(led4, helligkeit);
|
||||||
|
}else{
|
||||||
|
analogWrite(led4, 0);
|
||||||
|
}
|
||||||
|
if(RPM_THRES_5 <= rev){
|
||||||
|
analogWrite(led5, helligkeit);
|
||||||
|
}else{
|
||||||
|
analogWrite(led5, 0);
|
||||||
|
}
|
||||||
|
if(RPM_THRES_6 <= rev){
|
||||||
|
analogWrite(led6, helligkeit);
|
||||||
|
}else{
|
||||||
|
analogWrite(led6, 0);
|
||||||
|
}
|
||||||
|
if(RPM_THRES_7 <= rev){
|
||||||
|
analogWrite(led7, helligkeit);
|
||||||
|
}else{
|
||||||
|
analogWrite(led7, 0);
|
||||||
|
}
|
||||||
|
if(RPM_THRES_8 <= rev){
|
||||||
|
analogWrite(led8, helligkeit);
|
||||||
|
}else{
|
||||||
|
analogWrite(led8, 0);
|
||||||
|
}
|
||||||
|
if(RPM_THRES_9 <= rev){
|
||||||
|
analogWrite(led9, helligkeit);
|
||||||
|
}else{
|
||||||
|
analogWrite(led9, 0);
|
||||||
|
}
|
||||||
|
if(RPM_THRES_10 <= rev){
|
||||||
|
analogWrite(led10, helligkeit);
|
||||||
|
}else{
|
||||||
|
analogWrite(led10, 0);
|
||||||
|
}*/
|
||||||
|
digitalWrite(led1, RPM_THRES_1 <= rev);
|
||||||
|
digitalWrite(led2, RPM_THRES_2 <= rev);
|
||||||
|
digitalWrite(led3, RPM_THRES_3 <= rev);
|
||||||
|
digitalWrite(led4, RPM_THRES_4 <= rev);
|
||||||
|
digitalWrite(led5, RPM_THRES_5 <= rev);
|
||||||
|
digitalWrite(led6, RPM_THRES_6 <= rev);
|
||||||
|
digitalWrite(led7, RPM_THRES_7 <= rev);
|
||||||
|
digitalWrite(led8, RPM_THRES_8 <= rev);
|
||||||
|
digitalWrite(led9, RPM_THRES_9 <= rev);
|
||||||
|
digitalWrite(led10, RPM_THRES_10 <= rev);
|
||||||
|
|
||||||
|
digitalWrite(led11, t_mot); // rot, links, oben
|
||||||
|
digitalWrite(led12, t_air); // rot, links, mitte
|
||||||
|
digitalWrite(led13, t_oil); // rot, links, unten
|
||||||
|
|
||||||
|
digitalWrite(led14, e_dros); // rot, rechts, oben
|
||||||
|
digitalWrite(led15, u_batt); // rot rechts, mitte
|
||||||
|
digitalWrite(led16, g_auto); // blau rechts, unten
|
||||||
|
/*if(Vehicle_data.g_auto){
|
||||||
|
digitalWrite(led16, HIGH);
|
||||||
|
}else{
|
||||||
|
digitalWrite(led16, LOW);
|
||||||
|
}*/
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
/*
|
||||||
|
FT_2018_STW_CAN.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "DueTimer.h"
|
||||||
|
#include "due_can.h"
|
||||||
|
|
||||||
|
void Init_Can_0();
|
||||||
|
void Send_0x110();
|
||||||
|
void Receive_Can_0(CAN_FRAME *frame);
|
||||||
|
void update_LED(void);
|
|
@ -0,0 +1,262 @@
|
||||||
|
/*
|
||||||
|
FT_2018_STW_CAN.cpp
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "DueTimer.h"
|
||||||
|
#include "due_can.h"
|
||||||
|
#include "FT_2018e_STW_CAN.h"
|
||||||
|
#include "FT18e_STW_INIT.h"
|
||||||
|
|
||||||
|
CAN_FRAME can_0_msg;
|
||||||
|
//can_1_msg.id = 0x110;
|
||||||
|
int can_0_temp_data = 0;
|
||||||
|
int leds[] = {led1,led2,led3,led4,led5,led6,led7,led8,led9,led10,led11,led12,led13,led14,led15,led16};
|
||||||
|
|
||||||
|
|
||||||
|
void Init_Can_0(){
|
||||||
|
Can0.begin(1000000); // set CAN0 baud to 1kbit/s and don`t use enable pin!
|
||||||
|
Can0.setNumTXBoxes(1); // reserves mailbox 0 for tx only 8 mailboxes are available (the other 7 mailboxes are for rx)
|
||||||
|
Can0.watchFor(0x502); // set CAN RX filter for ID 0x502 and reserves mailbox 1 for rx
|
||||||
|
Can0.watchFor(0x504);
|
||||||
|
Can0.watchFor(0x500);
|
||||||
|
Can0.watchFor(0x773); // set CAN RX filter for ID 0x773 and reserves mailbox 3 for rx
|
||||||
|
Can0.watchFor(0x775);
|
||||||
|
// Can0.watchFor(0x777); // set CAN RX filter for ID 0x777 and reserves mailbox 5 for rx
|
||||||
|
Can0.watchFor(0x779); // set CAN RX filter for ID 0x779 and reserves mailbox 6 for rx
|
||||||
|
Can0.watchFor(0x77A);
|
||||||
|
Can0.setGeneralCallback(Receive_Can_0);
|
||||||
|
Timer3.attachInterrupt(Send_0x110); // set send interrupt
|
||||||
|
Timer3.start(10000); // Calls every 10ms
|
||||||
|
}
|
||||||
|
|
||||||
|
void Send_0x110(){
|
||||||
|
read_buttons();
|
||||||
|
read_rotary();
|
||||||
|
can_0_msg.id = 0x110;
|
||||||
|
can_0_msg.fid = 0;
|
||||||
|
can_0_msg.rtr = 0;
|
||||||
|
can_0_msg.priority = 0;
|
||||||
|
can_0_msg.length = 2;
|
||||||
|
can_0_msg.extended = 0;
|
||||||
|
can_0_temp_data = 0;
|
||||||
|
can_0_temp_data |= Stw_data.Stw_shift_up & 0b00000001;
|
||||||
|
can_0_temp_data |= Stw_data.Stw_shift_down << 1 & 0b00000010;
|
||||||
|
can_0_temp_data |= Stw_data.Stw_neutral << 2 & 0b00000100;
|
||||||
|
can_0_temp_data |= Stw_data.Stw_auto_shift << 3 & 0b00001000;
|
||||||
|
can_0_temp_data |= Stw_data.buttonStateEnc1 << 5 & 0b00100000; //pitlane
|
||||||
|
can_0_msg.data.byte[0] = can_0_temp_data;
|
||||||
|
can_0_msg.data.byte[1] = Stw_data.trc & 0b00001111;
|
||||||
|
can_0_msg.data.byte[2] = Stw_data.mode & 0b00000111;
|
||||||
|
if ((Stw_data.Stw_auto_shift << 3 & 0b00001000)){
|
||||||
|
if(Vehicle_data.g_auto){
|
||||||
|
Vehicle_data.g_auto = false;
|
||||||
|
}else{
|
||||||
|
Vehicle_data.g_auto = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Can0.sendFrame(can_0_msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Receive_Can_0(CAN_FRAME *temp_message){
|
||||||
|
switch (temp_message->id) {
|
||||||
|
//g_auto
|
||||||
|
case 0x502:{ // eDrossel error bit
|
||||||
|
Vehicle_data.e_thro = (temp_message->data.byte[0] & 0x80) | (temp_message->data.byte[0] & 0x40) | (temp_message->data.byte[0] & 0x20) | (temp_message->data.byte[0] & 0x10); // bit 4-7
|
||||||
|
|
||||||
|
if(temp_message->data.byte[0] & 0x80){
|
||||||
|
Stw_data.error_type = 1;//"pc_error";
|
||||||
|
}
|
||||||
|
if(temp_message->data.byte[0] & 0x40){
|
||||||
|
Stw_data.error_type = 2;//"bse_error";
|
||||||
|
}
|
||||||
|
if(temp_message->data.byte[0] & 0x20){
|
||||||
|
Stw_data.error_type = 3;//"aps_error";
|
||||||
|
}
|
||||||
|
if(temp_message->data.byte[0] & 0x10){
|
||||||
|
Stw_data.error_type = 4;//"etb_error";
|
||||||
|
}
|
||||||
|
//can_1_temp_data |= g_etb_e << 4;
|
||||||
|
//can_1_temp_data |= g_aps_e << 5;
|
||||||
|
//can_1_temp_data |= g_bse_e << 6;
|
||||||
|
//can_1_temp_data |= g_pc_e << 7;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x504:{ //autoshift+gear
|
||||||
|
//Vehicle_data.g_auto = (temp_message->data.byte[1]) >> 4;
|
||||||
|
Vehicle_data.gear = (temp_message->data.byte[1]) >> 5;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x773:{ // rpm
|
||||||
|
Vehicle_data.revol = (temp_message->data.byte[4] | temp_message->data.byte[3] << 8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x779:{ // battery voltage
|
||||||
|
Vehicle_data.u_batt = temp_message->data.byte[6];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*case 0x77A: // revolution limit bit
|
||||||
|
Vehicle_data.rev_lim = (temp_message->data.byte[3] & 0x20) >> 4;
|
||||||
|
switch(temp_message->data.byte[0]) {
|
||||||
|
case 0x02: // temp. intercooler
|
||||||
|
Vehicle_data.t_air = temp_message->data.byte[7];
|
||||||
|
break;
|
||||||
|
case 0x05: // temp. water
|
||||||
|
Vehicle_data.t_mot = temp_message->data.byte[4];
|
||||||
|
break;
|
||||||
|
case 0x04: // temp. oil
|
||||||
|
Vehicle_data.t_oil = temp_message->data.byte[5];
|
||||||
|
case 0x01: {
|
||||||
|
Vehicle_data.p_wat = temp_message->data.byte[6];
|
||||||
|
Vehicle_data.p_fuel = temp_message->data.byte[7];
|
||||||
|
Vehicle_data.p_oil = temp_message->data.byte[5];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;*/
|
||||||
|
case 0x77A:{//temp und p
|
||||||
|
//g_ms4_idle_b = (temp_message->data.byte[2] & 0b10000000) >> 7;
|
||||||
|
//g_ms4_engine_status = (temp_message->data.byte[3] & 0b01000000) >> 6;
|
||||||
|
//g_ms4_ignoff_b = (temp_message->data.byte[3] & 0b10000000) >> 7;
|
||||||
|
|
||||||
|
if ( temp_message->data.byte[0] == 1){
|
||||||
|
Vehicle_data.p_oil = temp_message->data.byte[5];
|
||||||
|
Vehicle_data.p_fuel = temp_message->data.byte[7];
|
||||||
|
}
|
||||||
|
else if ( temp_message->data.byte[0] == 2){
|
||||||
|
Vehicle_data.t_air = temp_message->data.byte[7];
|
||||||
|
}
|
||||||
|
else if ( temp_message->data.byte[0] == 4){
|
||||||
|
Vehicle_data.t_oil = temp_message->data.byte[5];
|
||||||
|
}
|
||||||
|
else if ( temp_message->data.byte[0] == 5){
|
||||||
|
Vehicle_data.t_mot = temp_message->data.byte[4];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x775:{//speed
|
||||||
|
Vehicle_data.speed_fl = 2*(temp_message->data.byte[2]);
|
||||||
|
Vehicle_data.speed_fr = 2*(temp_message->data.byte[3]);
|
||||||
|
Vehicle_data.speed = (Vehicle_data.speed_fl+Vehicle_data.speed_fr)/2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*case 0x777:{//m4_gear
|
||||||
|
Vehicle_data.gear = temp_message->data.byte[0];
|
||||||
|
break;
|
||||||
|
}*/
|
||||||
|
case 0x500:{
|
||||||
|
Vehicle_data.p_brake_front = temp_message->data.byte[1];
|
||||||
|
Vehicle_data.p_brake_rear = temp_message->data.byte[2];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_LED(){
|
||||||
|
//Copyright Michael Dietzel
|
||||||
|
//m.dietzel@fasttube.de
|
||||||
|
//Edit Michael Witt 05-2015
|
||||||
|
//m.witt@fasttube.de
|
||||||
|
|
||||||
|
//EDIT BAHA ZARROUKI 05-2107
|
||||||
|
//z.baha@fasttube.de
|
||||||
|
|
||||||
|
// alle Werte als Hex-Werte angegeben
|
||||||
|
bool t_oil = (Vehicle_data.t_oil - 40) >= 0x96; // 150°C temp.oil
|
||||||
|
bool t_air = (Vehicle_data.t_air - 40) >= 0x3C; // 60°C temp.llk
|
||||||
|
bool t_mot = ((Vehicle_data.t_mot - 40) >= 0x69) and ((Vehicle_data.t_mot - 40)!=0xC8); // 105°C temp.water und !=200
|
||||||
|
|
||||||
|
bool g_auto = Vehicle_data.g_auto;
|
||||||
|
bool u_batt = Vehicle_data.u_batt <= 0xB1; // 12.5V batt.spann.
|
||||||
|
bool e_dros = Vehicle_data.e_thro; // error-bit
|
||||||
|
|
||||||
|
bool rev_lim = Vehicle_data.rev_lim;
|
||||||
|
|
||||||
|
uint16_t rev = Vehicle_data.revol;
|
||||||
|
|
||||||
|
/*if(Vehicle_data.rev_lim){
|
||||||
|
for (int j = 0; j < 10; j++){
|
||||||
|
digitalWrite(leds[j], HIGH);
|
||||||
|
//analogWrite(leds[j], STW_data.br); //nur eine der zwei zeilen
|
||||||
|
}
|
||||||
|
delay(100);
|
||||||
|
for (int j = 0; j < 10; j++){
|
||||||
|
digitalWrite(leds[j], LOW);
|
||||||
|
}
|
||||||
|
delay(100);
|
||||||
|
}else{*/
|
||||||
|
/*uint8_t helligkeit = 20;
|
||||||
|
if(RPM_THRES_1 <= rev){
|
||||||
|
analogWrite(led1, helligkeit);
|
||||||
|
}else{
|
||||||
|
analogWrite(led1, 0);
|
||||||
|
}
|
||||||
|
if(RPM_THRES_2 <= rev){
|
||||||
|
analogWrite(led2, helligkeit);
|
||||||
|
}else{
|
||||||
|
analogWrite(led2, 0);
|
||||||
|
}
|
||||||
|
if(RPM_THRES_3 <= rev){
|
||||||
|
analogWrite(led3, helligkeit);
|
||||||
|
}else{
|
||||||
|
analogWrite(led3, 0);
|
||||||
|
}
|
||||||
|
if(RPM_THRES_4 <= rev){
|
||||||
|
analogWrite(led4, helligkeit);
|
||||||
|
}else{
|
||||||
|
analogWrite(led4, 0);
|
||||||
|
}
|
||||||
|
if(RPM_THRES_5 <= rev){
|
||||||
|
analogWrite(led5, helligkeit);
|
||||||
|
}else{
|
||||||
|
analogWrite(led5, 0);
|
||||||
|
}
|
||||||
|
if(RPM_THRES_6 <= rev){
|
||||||
|
analogWrite(led6, helligkeit);
|
||||||
|
}else{
|
||||||
|
analogWrite(led6, 0);
|
||||||
|
}
|
||||||
|
if(RPM_THRES_7 <= rev){
|
||||||
|
analogWrite(led7, helligkeit);
|
||||||
|
}else{
|
||||||
|
analogWrite(led7, 0);
|
||||||
|
}
|
||||||
|
if(RPM_THRES_8 <= rev){
|
||||||
|
analogWrite(led8, helligkeit);
|
||||||
|
}else{
|
||||||
|
analogWrite(led8, 0);
|
||||||
|
}
|
||||||
|
if(RPM_THRES_9 <= rev){
|
||||||
|
analogWrite(led9, helligkeit);
|
||||||
|
}else{
|
||||||
|
analogWrite(led9, 0);
|
||||||
|
}
|
||||||
|
if(RPM_THRES_10 <= rev){
|
||||||
|
analogWrite(led10, helligkeit);
|
||||||
|
}else{
|
||||||
|
analogWrite(led10, 0);
|
||||||
|
}*/
|
||||||
|
digitalWrite(led1, RPM_THRES_1 <= rev);
|
||||||
|
digitalWrite(led2, RPM_THRES_2 <= rev);
|
||||||
|
digitalWrite(led3, RPM_THRES_3 <= rev);
|
||||||
|
digitalWrite(led4, RPM_THRES_4 <= rev);
|
||||||
|
digitalWrite(led5, RPM_THRES_5 <= rev);
|
||||||
|
digitalWrite(led6, RPM_THRES_6 <= rev);
|
||||||
|
digitalWrite(led7, RPM_THRES_7 <= rev);
|
||||||
|
digitalWrite(led8, RPM_THRES_8 <= rev);
|
||||||
|
digitalWrite(led9, RPM_THRES_9 <= rev);
|
||||||
|
digitalWrite(led10, RPM_THRES_10 <= rev);
|
||||||
|
|
||||||
|
digitalWrite(led11, t_mot); // rot, links, oben
|
||||||
|
digitalWrite(led12, t_air); // rot, links, mitte
|
||||||
|
digitalWrite(led13, t_oil); // rot, links, unten
|
||||||
|
|
||||||
|
digitalWrite(led14, e_dros); // rot, rechts, oben
|
||||||
|
digitalWrite(led15, u_batt); // rot rechts, mitte
|
||||||
|
digitalWrite(led16, g_auto); // blau rechts, unten
|
||||||
|
/*if(Vehicle_data.g_auto){
|
||||||
|
digitalWrite(led16, HIGH);
|
||||||
|
}else{
|
||||||
|
digitalWrite(led16, LOW);
|
||||||
|
}*/
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
/*
|
||||||
|
FT_2018e_STW_CAN.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "DueTimer.h"
|
||||||
|
#include "due_can.h"
|
||||||
|
|
||||||
|
void Init_Can_0();
|
||||||
|
void Send_0x110();
|
||||||
|
void Receive_Can_0(CAN_FRAME *frame);
|
||||||
|
void update_LED(void);
|
|
@ -0,0 +1,46 @@
|
||||||
|
|
||||||
|
This directory is intended for project specific (private) libraries.
|
||||||
|
PlatformIO will compile them to static libraries and link into executable file.
|
||||||
|
|
||||||
|
The source code of each library should be placed in a an own separate directory
|
||||||
|
("lib/your_library_name/[here are source files]").
|
||||||
|
|
||||||
|
For example, see a structure of the following two libraries `Foo` and `Bar`:
|
||||||
|
|
||||||
|
|--lib
|
||||||
|
| |
|
||||||
|
| |--Bar
|
||||||
|
| | |--docs
|
||||||
|
| | |--examples
|
||||||
|
| | |--src
|
||||||
|
| | |- Bar.c
|
||||||
|
| | |- Bar.h
|
||||||
|
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
|
||||||
|
| |
|
||||||
|
| |--Foo
|
||||||
|
| | |- Foo.c
|
||||||
|
| | |- Foo.h
|
||||||
|
| |
|
||||||
|
| |- README --> THIS FILE
|
||||||
|
|
|
||||||
|
|- platformio.ini
|
||||||
|
|--src
|
||||||
|
|- main.c
|
||||||
|
|
||||||
|
and a contents of `src/main.c`:
|
||||||
|
```
|
||||||
|
#include <Foo.h>
|
||||||
|
#include <Bar.h>
|
||||||
|
|
||||||
|
int main (void)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
PlatformIO Library Dependency Finder will find automatically dependent
|
||||||
|
libraries scanning project source files.
|
||||||
|
|
||||||
|
More information about PlatformIO Library Dependency Finder
|
||||||
|
- https://docs.platformio.org/page/librarymanager/ldf.html
|
|
@ -0,0 +1,51 @@
|
||||||
|
#include "RotaryEncoder.h"
|
||||||
|
|
||||||
|
RotaryEncoder::RotaryEncoder(int ENC_A, int ENC_B, int multiplier, int stepSize, int pauseLength) {
|
||||||
|
_ENC_A = ENC_A;
|
||||||
|
_ENC_B = ENC_B;
|
||||||
|
_multiplier = multiplier;
|
||||||
|
_stepSize = stepSize;
|
||||||
|
_pauseLength = pauseLength;
|
||||||
|
_oldENC_A = 0;
|
||||||
|
_oldENC_B = 0;
|
||||||
|
_lastENCread = 0;
|
||||||
|
_ENCcounter = 0;
|
||||||
|
_lastENCreadTime = micros();
|
||||||
|
//define pin modes
|
||||||
|
pinMode(_ENC_A, INPUT);
|
||||||
|
pinMode(_ENC_B, INPUT);
|
||||||
|
digitalWrite(_ENC_A,HIGH); //these pins do not have pull up resistors on an attiny...
|
||||||
|
digitalWrite(_ENC_B,HIGH); //you must pull them up on the board.
|
||||||
|
}
|
||||||
|
int RotaryEncoder::readEncoder() {
|
||||||
|
int a0Pin = digitalRead(_ENC_A);
|
||||||
|
int a1Pin = digitalRead(_ENC_B);
|
||||||
|
int changevalue = 1;
|
||||||
|
int returnVal = 0;
|
||||||
|
if(a0Pin != _oldENC_A || a1Pin != _oldENC_B) {
|
||||||
|
if(_oldENC_A == a1Pin && _oldENC_B != a0Pin) {
|
||||||
|
returnVal = 1;
|
||||||
|
} else if (_oldENC_B == a0Pin && _oldENC_A != a1Pin) {
|
||||||
|
returnVal = -1;
|
||||||
|
}
|
||||||
|
_oldENC_A = a0Pin;
|
||||||
|
_oldENC_B = a1Pin;
|
||||||
|
|
||||||
|
if(returnVal != 0) {
|
||||||
|
if(returnVal == _lastENCread) {
|
||||||
|
_ENCcounter++;
|
||||||
|
if((micros() - _lastENCreadTime) < _pauseLength) {
|
||||||
|
changevalue = max((_ENCcounter/_stepSize)*_multiplier,1);
|
||||||
|
}
|
||||||
|
_lastENCreadTime = micros();
|
||||||
|
} else {
|
||||||
|
_ENCcounter=0;
|
||||||
|
}
|
||||||
|
_lastENCread = returnVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnVal*changevalue;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
/***********************************
|
||||||
|
Written by Joshua Oster-Morris/craftycoder.
|
||||||
|
BSD license, check license.txt for more information
|
||||||
|
All text above must be included in any redistribution
|
||||||
|
|
||||||
|
I strongly urge hardware debouncing with rotary encoders.
|
||||||
|
A 10000pF cap between both the A and B pins to GND (the C pin)
|
||||||
|
is suffcient to offer very consistent reads.
|
||||||
|
|
||||||
|
*ENC_A* is the arduino pin the A pin of the encoder is plugged in to.
|
||||||
|
*ENC_B* is the arduino pin the B pin of the encoder is plugged in to.
|
||||||
|
*multiplier* is what is sounds like
|
||||||
|
*stepSize* is used to find the *multiplicand*
|
||||||
|
*pauseLength* is the maximum amount of time in microseconds a user can pause before the number of steps resets
|
||||||
|
Equations of interest.
|
||||||
|
*multiplicand* = (consecutive steps in one direction with less than a *pauseLength* between them)/*stepSize*
|
||||||
|
*direction* = 1 for clockwise or -1 for counterclockwise
|
||||||
|
readEncoder() returns *multiplicand*x*multiplier*x*direction*
|
||||||
|
****************************************/
|
||||||
|
|
||||||
|
#if ARDUINO >= 100
|
||||||
|
#include "Arduino.h"
|
||||||
|
#else
|
||||||
|
#include "WProgram.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class RotaryEncoder {
|
||||||
|
public:
|
||||||
|
RotaryEncoder(int ENC_A, int ENC_B, int multiplier, int stepSize, int pauseLength);
|
||||||
|
int readEncoder();
|
||||||
|
private:
|
||||||
|
int _ENC_A, _ENC_B, _oldENC_A, _oldENC_B, _lastENCread, _ENCcounter, _pauseLength, _multiplier, _stepSize;
|
||||||
|
long _lastENCreadTime;
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
#include <RotaryEncoder.h>;
|
||||||
|
int val = 0;
|
||||||
|
RotaryEncoder encoder(A0,A2,5,6,3000);
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
Serial.begin(57600);
|
||||||
|
}
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
int enc = encoder.readEncoder();
|
||||||
|
int changevalue = 1;
|
||||||
|
if(enc != 0) {
|
||||||
|
val = val + (enc);
|
||||||
|
val = min(val,4095);
|
||||||
|
val = max(val,0);
|
||||||
|
Serial.println(val);
|
||||||
|
}
|
||||||
|
delayMicroseconds(5);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2012, Joshua Oster-Morris
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holders nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1 @@
|
||||||
|
doc/
|
|
@ -0,0 +1,38 @@
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
Library for controlling Electronic Assembly eDIPTFT displays
|
||||||
|
|
||||||
|
Copyright (c) 2013 Stefan Gofferje. All rights reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later
|
||||||
|
version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be
|
||||||
|
useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||||
|
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. See the GNU Lesser General Public License for more
|
||||||
|
details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General
|
||||||
|
Public License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
Boston, MA 02110-1301 USA
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
---- 10feb2015 Stefan Lehmann
|
||||||
|
- Added support for displays with only 1 Byte display coordinates (<255 pixels):
|
||||||
|
eDIP128, eDIP160 and eDIP240
|
||||||
|
|
||||||
|
---- 24feb2013 Stefan Gofferje
|
||||||
|
- Added functions for touch switches and radio groups
|
||||||
|
|
||||||
|
---- 03feb2013 Stefan Gofferje
|
||||||
|
- Smallprotocol works!!! Yay!
|
||||||
|
- More functions added.
|
||||||
|
|
||||||
|
---- 29jan2013 Stefan Gofferje
|
||||||
|
- Basic functionality is there
|
||||||
|
|
||||||
|
---- 26jan2013 Stefan Gofferje
|
||||||
|
- Project started
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,697 @@
|
||||||
|
//
|
||||||
|
// Library for controlling Electronic Assembly eDIPTFT displays
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013 Stefan Gofferje. All rights reserved.
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; either
|
||||||
|
// version 2.1 of the License, or (at your option) any later
|
||||||
|
// version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be
|
||||||
|
// useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||||
|
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE. See the GNU Lesser General Public License for more
|
||||||
|
// details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General
|
||||||
|
// Public License along with this library; if not, write to the
|
||||||
|
// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
// Boston, MA 02110-1301 USA
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "EDIPTFT.h"
|
||||||
|
#include "Arduino.h"
|
||||||
|
#define DEBUG false
|
||||||
|
|
||||||
|
|
||||||
|
EDIPTFT::EDIPTFT(boolean smallprotocol, boolean displaybool) {
|
||||||
|
_smallprotocol = smallprotocol;
|
||||||
|
_displaybool = displaybool;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::begin(long baud) {
|
||||||
|
SERIAL_DEV.begin(baud);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::sendByte(char data) {
|
||||||
|
SERIAL_DEV.write(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char EDIPTFT::readByte() {
|
||||||
|
return SERIAL_DEV.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::waitBytesAvailable() {
|
||||||
|
const uint32_t t_start = millis();
|
||||||
|
char loop = 0;
|
||||||
|
while (loop == 0)
|
||||||
|
{
|
||||||
|
if (bytesAvailable() != 0){
|
||||||
|
loop = 1;
|
||||||
|
}
|
||||||
|
if(t_start + 100 < millis())
|
||||||
|
{
|
||||||
|
//Serial.println("Error: waited to long!");
|
||||||
|
loop =1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char EDIPTFT::waitandreadByte() {
|
||||||
|
waitBytesAvailable();
|
||||||
|
char result = readByte();
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned char EDIPTFT::bytesAvailable() {
|
||||||
|
return SERIAL_DEV.available();
|
||||||
|
//ÄNDERN
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::sendData(char* data, char len) {
|
||||||
|
|
||||||
|
/*for(int i=0; i < len; i++) {
|
||||||
|
Serial.print(data[i]);
|
||||||
|
}
|
||||||
|
Serial.print('\n');
|
||||||
|
Serial.println(len);*/
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
unsigned char i;
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
//Serial.print(byte(data[i]), HEX);
|
||||||
|
SERIAL_DEV.print(byte(data[i]), HEX);
|
||||||
|
SERIAL_DEV.print(" ");
|
||||||
|
}
|
||||||
|
SERIAL_DEV.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_smallprotocol) {
|
||||||
|
sendSmall(data, len);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
unsigned char i;
|
||||||
|
for(i=0; i < len; i++) {
|
||||||
|
sendByte(data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::sendSmall(char* data, char len) {
|
||||||
|
unsigned char i, bcc;
|
||||||
|
char ok = 0;
|
||||||
|
const uint32_t t_start = millis();
|
||||||
|
|
||||||
|
while (ok == 0) {
|
||||||
|
sendByte(0x11);
|
||||||
|
bcc = 0x11;
|
||||||
|
|
||||||
|
sendByte(len);
|
||||||
|
bcc = bcc + len;
|
||||||
|
|
||||||
|
for(i=0; i < len; i++) {
|
||||||
|
sendByte(data[i]);
|
||||||
|
bcc = bcc + data[i];
|
||||||
|
}
|
||||||
|
sendByte(bcc);
|
||||||
|
waitBytesAvailable();
|
||||||
|
if (bytesAvailable() > 0) {
|
||||||
|
char x = readByte();
|
||||||
|
//Serial.print(uint16_t(x));
|
||||||
|
if (x == ACK) ok = 1;
|
||||||
|
else {
|
||||||
|
ok = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
delay(200);
|
||||||
|
ok = 0;
|
||||||
|
}
|
||||||
|
if(t_start + 1000 < millis())
|
||||||
|
{
|
||||||
|
//Serial.println("Error: waited to long!");
|
||||||
|
ok =1;
|
||||||
|
_displaybool = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::sendSmallDC2(char* data, char len) {
|
||||||
|
unsigned char i, bcc;
|
||||||
|
char ok = 0;
|
||||||
|
|
||||||
|
while (ok == 0) {
|
||||||
|
|
||||||
|
sendByte(0x12);
|
||||||
|
bcc = 0x12;
|
||||||
|
|
||||||
|
for(i=0; i < len; i++) {
|
||||||
|
sendByte(data[i]);
|
||||||
|
bcc = bcc + data[i];
|
||||||
|
}
|
||||||
|
sendByte(bcc);
|
||||||
|
waitBytesAvailable(); //delay(6); im 17er
|
||||||
|
if (bytesAvailable() > 0) {
|
||||||
|
if (readByte() == ACK) ok = 1;
|
||||||
|
else ok = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
delay(200);
|
||||||
|
ok = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::smallProtoSelect(char address) {
|
||||||
|
char command [] = {
|
||||||
|
0x03, 'A', 'S', address
|
||||||
|
};
|
||||||
|
sendSmallDC2(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::smallProtoDeselect(char address) {
|
||||||
|
char command [] = {
|
||||||
|
0x03, 'A', 'D', address
|
||||||
|
};
|
||||||
|
sendSmallDC2(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned char EDIPTFT::datainBuffer() {
|
||||||
|
unsigned char result;
|
||||||
|
char command [] = {
|
||||||
|
0x01, 'I'
|
||||||
|
};
|
||||||
|
sendSmallDC2(command, sizeof(command));
|
||||||
|
waitandreadByte();
|
||||||
|
waitandreadByte();
|
||||||
|
result=waitandreadByte();
|
||||||
|
waitandreadByte();
|
||||||
|
waitandreadByte();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int EDIPTFT::readBuffer(char* data) { //return void
|
||||||
|
unsigned char len, i; // char in 17er
|
||||||
|
char command [] = {
|
||||||
|
0x01, 'S'
|
||||||
|
};
|
||||||
|
sendSmallDC2(command, sizeof(command));
|
||||||
|
waitandreadByte();
|
||||||
|
len=waitandreadByte();
|
||||||
|
char result[len];
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
result[i] = waitandreadByte();
|
||||||
|
}
|
||||||
|
memcpy(data, result, len);
|
||||||
|
waitandreadByte();
|
||||||
|
return len; //zeile nicht vorhanden
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::clear() { //vgl 17er
|
||||||
|
this->deleteDisplay();
|
||||||
|
this->removeTouchArea(0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::deleteDisplay() {
|
||||||
|
char command [] = {
|
||||||
|
27, 'D', 'L'
|
||||||
|
};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::invert() {
|
||||||
|
char command [] = {
|
||||||
|
27, 'D', 'I'
|
||||||
|
};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::setDisplayColor(char fg, char bg) {
|
||||||
|
char command [] = {
|
||||||
|
27, 'F', 'D', fg, bg
|
||||||
|
};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::fillDisplayColor(char bg) {
|
||||||
|
char command [] = {
|
||||||
|
27, 'D', 'F', bg
|
||||||
|
};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::terminalOn(boolean on) {
|
||||||
|
if (on) {
|
||||||
|
char command [] = {27, 'T', 'E'};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
char command [] = {27, 'T', 'A'};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::loadImage(int x1, int y1, int nr) {
|
||||||
|
char command [] = {27, 'U', 'I',
|
||||||
|
#if COORD_SIZE == 1
|
||||||
|
(char)x1, (char)y1,
|
||||||
|
#else
|
||||||
|
lowByte(x1), highByte(x1), lowByte(y1), highByte(y1),
|
||||||
|
#endif
|
||||||
|
nr};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::cursorOn(boolean on) {
|
||||||
|
if (on) {
|
||||||
|
char command [] = {27, 'T', 'C', 1};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
char command [] = {27, 'T', 'C', 0};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::setCursor(char col, char row) {
|
||||||
|
char command [] = {27, 'T', 'P', col, row};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
void EDIPTFT::displayLight(char no) {
|
||||||
|
char command [] = {
|
||||||
|
27, 'Y', 'H', no
|
||||||
|
};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
void EDIPTFT::defineBargraph(char dir, char no, int x1, int y1, int x2, int y2, byte sv, byte ev, char type, char mst) {
|
||||||
|
char command [] = {
|
||||||
|
27, 'B', dir, no,
|
||||||
|
#if COORD_SIZE == 1
|
||||||
|
x1, y1, x2, y2,
|
||||||
|
#else
|
||||||
|
lowByte(x1), highByte(x1), lowByte(y1), highByte(y1),
|
||||||
|
lowByte(x2), highByte(x2), lowByte(y2), highByte(y2),
|
||||||
|
#endif
|
||||||
|
char(sv),
|
||||||
|
char(ev),
|
||||||
|
type,
|
||||||
|
mst
|
||||||
|
};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
//mst fehlt 17
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::updateBargraph(char no, char val) {
|
||||||
|
char command [] = {
|
||||||
|
27, 'B', 'A', no, val
|
||||||
|
};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::setBargraphColor(char no, char fg, char bg, char fr) {
|
||||||
|
char command [] = {
|
||||||
|
27, 'F', 'B', no, fg, bg, fr
|
||||||
|
};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::linkBargraphLight(char no) {
|
||||||
|
char command [] = {
|
||||||
|
27, 'Y', 'B', no
|
||||||
|
};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::makeBargraphTouch(char no) {
|
||||||
|
char command [] = {
|
||||||
|
27, 'A', 'B', no
|
||||||
|
};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::deleteBargraph(char no,char n1) {
|
||||||
|
char command [] = {
|
||||||
|
27, 'B', 'D', no, n1
|
||||||
|
};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::defineInstrument(char no, int x1, int y1, char image, char angle, char sv, char ev) {
|
||||||
|
char command [] = {
|
||||||
|
27, 'I', 'P', no,
|
||||||
|
#if COORD_SIZE == 1
|
||||||
|
x1, y1,
|
||||||
|
#else
|
||||||
|
lowByte(x1), highByte(x1), lowByte(y1), highByte(y1),
|
||||||
|
#endif
|
||||||
|
image, angle, sv, ev
|
||||||
|
};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::updateInstrument(char no, char val) {
|
||||||
|
char command [] = {
|
||||||
|
27, 'I', 'A', no, val
|
||||||
|
};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::redrawInstrument(char no) {
|
||||||
|
char command [] = {
|
||||||
|
27, 'I', 'N', no
|
||||||
|
};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::deleteInstrument(char no, char n1, char n2) {
|
||||||
|
char command [] = {
|
||||||
|
27, 'B', 'D', no, n1, n2
|
||||||
|
};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::setLineColor(char fg, char bg) {
|
||||||
|
char command [] = {
|
||||||
|
27, 'F', 'G', fg, bg
|
||||||
|
};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::setLineThick(char x, char y) {
|
||||||
|
char command [] = {
|
||||||
|
27, 'G', 'Z', x, y
|
||||||
|
};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::setTextColor(char fg, char bg) {
|
||||||
|
char command [] = {
|
||||||
|
27, 'F', 'Z', fg, bg
|
||||||
|
};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::setTextFont(char font) {
|
||||||
|
char command [] = {
|
||||||
|
27, 'Z', 'F', font
|
||||||
|
};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
void EDIPTFT::setTextSize(int xsize, int ysize){
|
||||||
|
char command[] = {27, 'Z', 'Z', xsize, ysize};
|
||||||
|
sendData(command,sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
void EDIPTFT::setTextAngle(char angle) {
|
||||||
|
// 0 = 0°, 1 = 90°, 2 = 180°, 3 = 270°
|
||||||
|
char command [] = {
|
||||||
|
27, 'Z', 'W', angle
|
||||||
|
};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::drawText(uint16_t x1, uint16_t y1, char justification, const char* text) {
|
||||||
|
//nicht const 17//
|
||||||
|
byte len = strlen(text);
|
||||||
|
byte i;
|
||||||
|
char helper [3 + 4 + len + 1];
|
||||||
|
helper[0] = 27; //esc
|
||||||
|
helper[1] = 'Z';
|
||||||
|
helper[2] = justification;
|
||||||
|
helper[3] = x1 & 0xFF;
|
||||||
|
helper[4] = (x1 >> 8) & 0xFF;
|
||||||
|
helper[5] = y1 & 0xFF;
|
||||||
|
helper[6] = (y1 >> 8) & 0xFF;
|
||||||
|
for (i = 0; i <= len; i++) {
|
||||||
|
helper[i + 7] = text[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
sendData(helper, sizeof(helper));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::drawLine(int x1, int y1, int x2, int y2) {
|
||||||
|
char command [] = {
|
||||||
|
27,'G','D',
|
||||||
|
#if COORD_SIZE == 1
|
||||||
|
x1, y1, x2, y2
|
||||||
|
#else
|
||||||
|
lowByte(x1),highByte(x1),lowByte(y1),highByte(y1),
|
||||||
|
lowByte(x2),highByte(x2),lowByte(y2),highByte(y2)
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::drawRect(int x1, int y1, int x2, int y2) {
|
||||||
|
char command [] = {
|
||||||
|
27,'G','R',
|
||||||
|
#if COORD_SIZE == 1
|
||||||
|
x1, y1, x2, y2
|
||||||
|
#else
|
||||||
|
lowByte(x1),highByte(x1),lowByte(y1),highByte(y1),
|
||||||
|
lowByte(x2),highByte(x2),lowByte(y2),highByte(y2)
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::drawRectf(int x1, int y1, int x2, int y2, char color) {
|
||||||
|
char command [] = {
|
||||||
|
27,'R','F',
|
||||||
|
#if COORD_SIZE == 1
|
||||||
|
x1, y1, x2, y2,
|
||||||
|
#else
|
||||||
|
lowByte(x1),highByte(x1),lowByte(y1),highByte(y1),
|
||||||
|
lowByte(x2),highByte(x2),lowByte(y2),highByte(y2),
|
||||||
|
#endif
|
||||||
|
color
|
||||||
|
};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::defineTouchKey(int x1, int y1, int x2, int y2, char down, char up,
|
||||||
|
const char* text) { //text nicht const 17
|
||||||
|
byte len = strlen(text);
|
||||||
|
byte i;
|
||||||
|
char helper [len + 6 + 4 * COORD_SIZE];//len+13 17
|
||||||
|
char command [] = {
|
||||||
|
27, 'A', 'T',
|
||||||
|
#if COORD_SIZE == 1
|
||||||
|
x1, y1, x2, y2,
|
||||||
|
#else
|
||||||
|
lowByte(x1), highByte(x1), lowByte(y1), highByte(y1),
|
||||||
|
lowByte(x2), highByte(x2), lowByte(y2), highByte(y2),
|
||||||
|
#endif
|
||||||
|
down, up
|
||||||
|
};
|
||||||
|
for (i = 0; i < (5 + 4 * COORD_SIZE); i++) helper[i] = command[i];//i<=12 17
|
||||||
|
for (i = 0; i <= len+1; i++) helper[i + 5 + 4 * COORD_SIZE] = text[i];//i<=len 17
|
||||||
|
sendData(helper, sizeof(helper));//size len+14 17
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::defineTouchSwitch(int x1, int y1, int x2, int y2,
|
||||||
|
char down, char up, const char* text) {//const nicht 17
|
||||||
|
byte len = strlen(text);
|
||||||
|
byte i;
|
||||||
|
char helper [len + 6 + 4 * COORD_SIZE];//len+13 17
|
||||||
|
char command [] = {
|
||||||
|
27, 'A', 'K',
|
||||||
|
#if COORD_SIZE == 1
|
||||||
|
x1, y1, x2, y2,
|
||||||
|
#else
|
||||||
|
lowByte(x1),highByte(x1),lowByte(y1),highByte(y1),
|
||||||
|
lowByte(x2),highByte(x2),lowByte(y2),highByte(y2),
|
||||||
|
#endif
|
||||||
|
down, up
|
||||||
|
};
|
||||||
|
for (i = 0; i < 5 + 4 * COORD_SIZE; i++) helper[i] = command[i];
|
||||||
|
for (i = 0; i <= len; i++) helper[i + 5 + 4 * COORD_SIZE] = text[i];
|
||||||
|
sendData(helper, sizeof(helper));//size len+14
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::defineTouchSwitch(int x, int y, int img, char downcode,
|
||||||
|
char upcode, const char* text) {
|
||||||
|
byte len = strlen(text);
|
||||||
|
byte i;
|
||||||
|
byte n = 6 + 2 * COORD_SIZE;
|
||||||
|
char helper [len + n + 1];
|
||||||
|
char command [] = {
|
||||||
|
27, 'A', 'J',
|
||||||
|
#if COORD_SIZE == 1
|
||||||
|
x, y,
|
||||||
|
#else
|
||||||
|
lowByte(x), highByte(x), lowByte(y), highByte(y),
|
||||||
|
#endif
|
||||||
|
img, downcode, upcode
|
||||||
|
};
|
||||||
|
for (i = 0; i < n; i++) helper[i] = command[i];
|
||||||
|
for (i = 0; i <= len; i++) helper[i + n] = text[i];
|
||||||
|
sendData(helper, sizeof(helper));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::setTouchSwitch(char code,char value) {
|
||||||
|
char command [] = {
|
||||||
|
27, 'A', 'P', code, value
|
||||||
|
};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::setTouchkeyColors(
|
||||||
|
char n1, char n2, char n3, char s1, char s2, char s3) {
|
||||||
|
char command [] = {
|
||||||
|
27, 'F', 'E', n1, n2, n3, s1, s2, s3
|
||||||
|
};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::setTouchkeyFont(char font) {
|
||||||
|
char command [] = {
|
||||||
|
27, 'A', 'F', font
|
||||||
|
};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::setTouchkeyLabelColors(char nf, char sf) {
|
||||||
|
char command [] = {
|
||||||
|
27, 'F', 'A', nf, sf
|
||||||
|
};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::setTouchGroup(char group) {
|
||||||
|
char command [] = {
|
||||||
|
27, 'A', 'R', group
|
||||||
|
};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::removeTouchArea(char code, char n1) {
|
||||||
|
char command [] = {
|
||||||
|
27, 'A', 'L', code, n1
|
||||||
|
};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::callMacro(uint nr) {
|
||||||
|
char command[] = {
|
||||||
|
27, 'M', 'N', nr
|
||||||
|
};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::callTouchMacro(uint nr) {
|
||||||
|
char command[] = {
|
||||||
|
27, 'M', 'T', nr
|
||||||
|
};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::callMenuMacro(uint nr) {
|
||||||
|
char command[] = {
|
||||||
|
27, 'M', 'M', nr
|
||||||
|
};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::defineTouchMenu(int x1, int y1, int x2, int y2,
|
||||||
|
char downcode, char upcode, char mnucode, const char *text) {
|
||||||
|
byte len = strlen(text);
|
||||||
|
byte n = 6 + 4 * COORD_SIZE;
|
||||||
|
char helper [len + n + 1];
|
||||||
|
|
||||||
|
char command [] = {
|
||||||
|
27, 'A', 'M',
|
||||||
|
#if COORD_SIZE == 1
|
||||||
|
x1, y1, x2, y2,
|
||||||
|
#else
|
||||||
|
lowByte(x1),highByte(x1),lowByte(y1),highByte(y1),
|
||||||
|
lowByte(x2),highByte(x2),lowByte(y2),highByte(y2),
|
||||||
|
#endif
|
||||||
|
downcode, upcode, mnucode
|
||||||
|
};
|
||||||
|
for (int i = 0; i < n; i++) helper[i] = command[i];
|
||||||
|
for (int i = 0; i <= len; i++) helper[i + n] = text[i];
|
||||||
|
sendData(helper, sizeof(helper));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::openTouchMenu() {
|
||||||
|
char command [] = {
|
||||||
|
27, 'N', 'T', 2
|
||||||
|
};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::setMenuFont(char font) {
|
||||||
|
char command [] = {
|
||||||
|
27, 'N', 'F', font
|
||||||
|
};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDIPTFT::setTouchMenuAutomation(bool val) {
|
||||||
|
char n1 = val ? 1 : 0;
|
||||||
|
char command [] = {
|
||||||
|
27, 'N', 'T', n1
|
||||||
|
};
|
||||||
|
sendData(command, sizeof(command));
|
||||||
|
}
|
|
@ -0,0 +1,434 @@
|
||||||
|
//
|
||||||
|
// Library for controlling Electronic Assembly eDIPTFT displays
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013 Stefan Gofferje. All rights reserved.
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; either
|
||||||
|
// version 2.1 of the License, or (at your option) any later
|
||||||
|
// version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be
|
||||||
|
// useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||||
|
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE. See the GNU Lesser General Public License for more
|
||||||
|
// details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General
|
||||||
|
// Public License along with this library; if not, write to the
|
||||||
|
// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
// Boston, MA 02110-1301 USA
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef EDIPTFT_h
|
||||||
|
#define EDIPTFT_h
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
|
||||||
|
//Devices
|
||||||
|
#define EDIP128 1
|
||||||
|
#define EDIP160 1
|
||||||
|
#define EDIP240 1
|
||||||
|
#define EDIP320 2
|
||||||
|
|
||||||
|
//Set your device
|
||||||
|
#define DEVICE EDIP320
|
||||||
|
#define COORD_SIZE DEVICE //Byte count for coordinates
|
||||||
|
#define SERIAL_DEV Serial3
|
||||||
|
|
||||||
|
#define EA_BLACK 1
|
||||||
|
#define EA_BLUE 2
|
||||||
|
#define EA_RED 3
|
||||||
|
#define EA_GREEN 4
|
||||||
|
#define EA_PURPLE 5
|
||||||
|
#define EA_CYAN 6
|
||||||
|
#define EA_YELLOW 7
|
||||||
|
#define EA_WHITE 8
|
||||||
|
#define EA_DARKGREY 9
|
||||||
|
#define EA_ORANGE 10
|
||||||
|
#define EA_LILA 11
|
||||||
|
#define EA_DARKPURPLE 12
|
||||||
|
#define EA_MINT 13
|
||||||
|
#define EA_GRASSGREEN 14
|
||||||
|
#define EA_LIGHTBLUE 15
|
||||||
|
#define EA_LIGHTGREY 16
|
||||||
|
|
||||||
|
// Fonts
|
||||||
|
#define EA_FONT8X8 0
|
||||||
|
#define EA_FONT4X6 1
|
||||||
|
#define EA_FONT6X8 2
|
||||||
|
#define EA_FONT7X12 3
|
||||||
|
#define EA_GENEVA10 4
|
||||||
|
#define EA_CHICAGO14 5
|
||||||
|
#define EA_SWISS30B 6
|
||||||
|
#define EA_BIGZIF57 7
|
||||||
|
|
||||||
|
#define NAK 0x15
|
||||||
|
#define ACK 0x06
|
||||||
|
#define ESC 0x1B
|
||||||
|
|
||||||
|
#define uint unsigned int
|
||||||
|
|
||||||
|
class EDIPTFT {
|
||||||
|
public:
|
||||||
|
EDIPTFT(boolean smallprotocol=true, boolean displaybool=false);
|
||||||
|
boolean _displaybool;
|
||||||
|
|
||||||
|
void begin(long baud=115200);
|
||||||
|
|
||||||
|
// helper functions
|
||||||
|
char readByte();
|
||||||
|
char waitandreadByte();
|
||||||
|
unsigned char datainBuffer();
|
||||||
|
int readBuffer(char* data);
|
||||||
|
void smallProtoSelect(char address);
|
||||||
|
void smallProtoDeselect(char address);
|
||||||
|
void sendData(char* data, char len);
|
||||||
|
|
||||||
|
// Basic display functions
|
||||||
|
/*! \brief Clear display
|
||||||
|
*
|
||||||
|
* Clear display contents (all pixels off) and remove touch areas
|
||||||
|
*/
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
/*! \brief Delete display
|
||||||
|
*
|
||||||
|
* Delete display contents (all pixels off). Touch areas are still active.
|
||||||
|
*/
|
||||||
|
void deleteDisplay();
|
||||||
|
|
||||||
|
/*! \brief Invert display
|
||||||
|
*
|
||||||
|
* Invert display contents (invert all pixels)
|
||||||
|
*/
|
||||||
|
void invert();
|
||||||
|
|
||||||
|
void setDisplayColor(char fg, char bg);
|
||||||
|
|
||||||
|
void fillDisplayColor(char bg);
|
||||||
|
|
||||||
|
/*! \brief Terminal on
|
||||||
|
*
|
||||||
|
* Terminal display is switched on if \a on is true
|
||||||
|
*
|
||||||
|
* \param on determine if terminal is switched on
|
||||||
|
*/
|
||||||
|
void terminalOn(boolean on);
|
||||||
|
|
||||||
|
/*! \brief Load internal image
|
||||||
|
*
|
||||||
|
* Load internal image with the \a nr (0..255) from the *EEPROM* memory to
|
||||||
|
* \a x1, \a y1
|
||||||
|
*
|
||||||
|
* \param x1 x position of image on the display
|
||||||
|
* \param y1 y position of image on the display
|
||||||
|
* \param nr number of the image on the *EEPROM*
|
||||||
|
*/
|
||||||
|
void loadImage(int x1, int y1, int nr);
|
||||||
|
|
||||||
|
/*! \brief Cursor on/off
|
||||||
|
*
|
||||||
|
* Switch cursor on/off
|
||||||
|
*
|
||||||
|
* \param on `n1=0`: cursor is invisible, `n1=1`: cursor flashes
|
||||||
|
*/
|
||||||
|
void cursorOn(boolean on);
|
||||||
|
|
||||||
|
/*! \brief Position cursor
|
||||||
|
*
|
||||||
|
* origin upper-left corner `(1, 1)`
|
||||||
|
*
|
||||||
|
* \param col new cursor column
|
||||||
|
* \param row new cursor row
|
||||||
|
*/
|
||||||
|
void setCursor(char col, char row);
|
||||||
|
|
||||||
|
void displayLight(char no);
|
||||||
|
// Bargraph
|
||||||
|
/*! \brief Define bargraph
|
||||||
|
*
|
||||||
|
* Define bargraph to form the rectangle enclosing the
|
||||||
|
* bargraph. \a sv and \a ev are the values for `0%` and `100%`.
|
||||||
|
*
|
||||||
|
* \param dir direction ('L'eft, 'R'ight, 'O'up, 'U'down)
|
||||||
|
* \param no bargraph number `1..32`
|
||||||
|
* \param x1 upper left x coordinate
|
||||||
|
* \param y1 upper left y coordinate
|
||||||
|
* \param x2 lower right x coordinate
|
||||||
|
* \param y2 lower right y coordinate
|
||||||
|
* \param sv start value (0%)
|
||||||
|
* \param ev end value (100%)
|
||||||
|
|
||||||
|
* \param type set the style of the bargraph:\n
|
||||||
|
* `type=0`: pattern bar, \a mst=bar pattern,\n
|
||||||
|
* `type=1`: pattern bar in rectangle, \a mst=bar pattern,\n
|
||||||
|
* `type=2`: pattern line, \a mst=line width,\n
|
||||||
|
* `type=3`: pattern line in rectangle, \a mst=line width
|
||||||
|
*
|
||||||
|
* \param mst additional parameter for type specification
|
||||||
|
*/
|
||||||
|
void defineBargraph(char dir, char no, int x1, int y1, int x2, int y2,
|
||||||
|
byte sv, byte ev, char type, char mst);
|
||||||
|
|
||||||
|
/*! \brief Update bargraph
|
||||||
|
*
|
||||||
|
* Set and draw the bargraph *no* to the new *value*
|
||||||
|
*
|
||||||
|
* \param no number of the bargraph `1..32`
|
||||||
|
* \param val new value of the bargraph
|
||||||
|
*/
|
||||||
|
void updateBargraph(char no, char val);
|
||||||
|
|
||||||
|
void setBargraphColor(char no, char fg, char bg, char fr);
|
||||||
|
|
||||||
|
/*! \brief Set bargraph by touch
|
||||||
|
*
|
||||||
|
* The bargraph with number *no* is defined for input by touch panel
|
||||||
|
*
|
||||||
|
* \param no number of the bargraph `1..32`
|
||||||
|
*/
|
||||||
|
void makeBargraphTouch(char no);
|
||||||
|
|
||||||
|
void linkBargraphLight(char no);
|
||||||
|
|
||||||
|
/*! \brief Delete bargraph
|
||||||
|
*
|
||||||
|
* The definition of the bargraph with number *no* becomes invalid. If the
|
||||||
|
* bargraph was defined as input with touch, the touchfield will also be
|
||||||
|
* deleted.
|
||||||
|
*
|
||||||
|
* \param no number of the bargraph `1..32`
|
||||||
|
* \param n1 additional parameter\n
|
||||||
|
* `n1=0`: bargraph remains visible\n
|
||||||
|
* `n1=1`: bargraph is deleted
|
||||||
|
*/
|
||||||
|
void deleteBargraph(char no, char n1);
|
||||||
|
|
||||||
|
// Instrument
|
||||||
|
void defineInstrument(char no, int x1, int y1, char image,
|
||||||
|
char angle, char sv, char ev);
|
||||||
|
void updateInstrument(char no, char val);
|
||||||
|
void redrawInstrument(char no);
|
||||||
|
void deleteInstrument(char no, char n1, char n2);
|
||||||
|
|
||||||
|
// Text
|
||||||
|
void setTextColor(char fg, char bg);
|
||||||
|
|
||||||
|
/*! \brief Set font
|
||||||
|
*
|
||||||
|
* Set font with the number *font*
|
||||||
|
*
|
||||||
|
* \param font font number `font=0..15`, use font defines here
|
||||||
|
*/
|
||||||
|
void setTextFont(char font);
|
||||||
|
|
||||||
|
void setTextSize(int xsize, int ysize);
|
||||||
|
|
||||||
|
/*! \brief Set text angle
|
||||||
|
*
|
||||||
|
* Set text output angle
|
||||||
|
*
|
||||||
|
* \param angle text output angle\n
|
||||||
|
`angle=0`: 0°
|
||||||
|
`angle=1`: 90°
|
||||||
|
*/
|
||||||
|
void setTextAngle(char angle);
|
||||||
|
|
||||||
|
/*! \brief Draw text on display
|
||||||
|
*
|
||||||
|
* Draw a *text* on screen. Several lines are separated by the character `|`
|
||||||
|
* ($7C).
|
||||||
|
* * place text between `~`: characters flash on/off
|
||||||
|
* * place text between `@`: characters flash inversely
|
||||||
|
* * use `\\` as to escape special characters
|
||||||
|
*
|
||||||
|
* \param x1: x coordinate
|
||||||
|
* \param y1: y coordinate
|
||||||
|
* \param justification set text justification to `L`(eft), `R`(ight),
|
||||||
|
* `C`(enter)
|
||||||
|
* \param text text to draw on display
|
||||||
|
*/
|
||||||
|
void drawText(uint16_t x1, uint16_t y1, char justification, const char* text);
|
||||||
|
|
||||||
|
// Rectangle and Line
|
||||||
|
void setLineColor(char fg, char bg);
|
||||||
|
|
||||||
|
/*! \brief Point size/line thickness
|
||||||
|
*
|
||||||
|
* \param x x-point size (1..15)
|
||||||
|
* \param y y-point size (1..15)
|
||||||
|
*/
|
||||||
|
void setLineThick(char x, char y);
|
||||||
|
|
||||||
|
/*! \brief Draw straight line
|
||||||
|
*
|
||||||
|
* Draw straight line from point *x1*, *y1* to point *x2*, *y2*
|
||||||
|
*/
|
||||||
|
void drawLine(int x1, int y1, int x2, int y2);
|
||||||
|
|
||||||
|
/*! \brief Draw rectangle
|
||||||
|
*
|
||||||
|
* Draw four straight lines as a rectangle from *x1*, *y1* to *x2*, *y2*
|
||||||
|
*/
|
||||||
|
void drawRect(int x1, int y1, int x2, int y2);
|
||||||
|
|
||||||
|
void drawRectf(int x1, int y1, int x2, int y2, char color);
|
||||||
|
|
||||||
|
// Touch keys
|
||||||
|
|
||||||
|
/*! \brief Define touch key
|
||||||
|
*
|
||||||
|
* Key remains pressed as long as there is contact. The area from *x1*, *y1*
|
||||||
|
* to *x2*, *y2* is drawn with actual border and defined as a key.
|
||||||
|
* The label is drawn with the current touch font. The first character
|
||||||
|
* determines the alignment of the text (`L`(eft), `R`(ight), `C`(enter)).
|
||||||
|
* Multiline texts are separated by the character `|`.
|
||||||
|
*
|
||||||
|
* \param down return/touchmacro (1-255) if pressed
|
||||||
|
* \param up return/touchmacro (1-255) if released
|
||||||
|
* \param text label of the touch key
|
||||||
|
*/
|
||||||
|
void defineTouchKey(int x1, int y1, int x2, int y2,
|
||||||
|
char down, char up, const char* text);
|
||||||
|
|
||||||
|
/*! \brief Define touch switch
|
||||||
|
*
|
||||||
|
* Status of the switch toggles after each contact. The area from *x1*, *y1*
|
||||||
|
* to *x2*, *y2* is drawn with actual border and defined as a key.
|
||||||
|
* The label is drawn with the current touch font. The first character
|
||||||
|
* determines the alignment of the text (`L`(eft), `R`(ight), `C`(enter)).
|
||||||
|
* Multiline texts are separated by the character `|`.
|
||||||
|
*
|
||||||
|
* \param down return/touchmacro (1-255) if pressed
|
||||||
|
* \param up return/touchmacro (1-255) if released
|
||||||
|
* \param text label of the touch key
|
||||||
|
*/
|
||||||
|
void defineTouchSwitch(int x1, int y1, int x2, int y2,
|
||||||
|
char down, char up, const char* text);
|
||||||
|
|
||||||
|
/*! \brief Define touch switch with image
|
||||||
|
*
|
||||||
|
* Status of the switch toggles after each contact. Image number *img* is
|
||||||
|
* loaded to *x*, *y* and defined as a switch.
|
||||||
|
* The label is drawn with the current touch font. The first character
|
||||||
|
* determines the alignment of the text (`L`(eft), `R`(ight), `C`(enter)).
|
||||||
|
* Multiline texts are separated by the character `|`.
|
||||||
|
*
|
||||||
|
* \param down return/touchmacro (1-255) if pressed
|
||||||
|
* \param up return/touchmacro (1-255) if released
|
||||||
|
* \param text label of the touch switch
|
||||||
|
*/
|
||||||
|
void defineTouchSwitch(int x, int y, int img, char downcode,
|
||||||
|
char upcode, const char* text);
|
||||||
|
|
||||||
|
/*! \brief Set touch switch
|
||||||
|
*
|
||||||
|
* Set the status of the touch switch with the return code *code*
|
||||||
|
* to *value*.
|
||||||
|
*
|
||||||
|
* \param code Return code of the switch
|
||||||
|
* \param value `value=0`: OFF, `value=1`: ON
|
||||||
|
*/
|
||||||
|
void setTouchSwitch(char code,char value);
|
||||||
|
|
||||||
|
void setTouchkeyColors(char n1, char n2, char n3,
|
||||||
|
char s1, char s2, char s3);
|
||||||
|
|
||||||
|
/*! \brief Label font
|
||||||
|
*
|
||||||
|
* Apply font with number *font* for touch key labels
|
||||||
|
*/
|
||||||
|
void setTouchkeyFont(char font);
|
||||||
|
|
||||||
|
void setTouchkeyLabelColors(char nf,char sf);
|
||||||
|
|
||||||
|
/*! \brief Radio group for switches
|
||||||
|
*
|
||||||
|
* `group=0`: newly defined switches don't belong to a group
|
||||||
|
* `group=1..255`: newly defined switches are assigned to the group with
|
||||||
|
* the given number
|
||||||
|
* Only one switch in a group is active at once. All others are deactivated.
|
||||||
|
* For switches only the *down code* is applicable. The *up code* will be
|
||||||
|
* ignored.
|
||||||
|
*/
|
||||||
|
void setTouchGroup(char group);
|
||||||
|
|
||||||
|
/*! \brief Delete toch area by up- or downcode
|
||||||
|
*
|
||||||
|
* The touch area with the return code is removed from the touch query
|
||||||
|
*
|
||||||
|
* \param code the code of the touch area (code=0: all touch areas)
|
||||||
|
* \param n1 n1==0: the area remains visible on the display,
|
||||||
|
* n1==1: the area is deleted
|
||||||
|
*/
|
||||||
|
void removeTouchArea(char code,char n1);
|
||||||
|
|
||||||
|
// Macro Calls
|
||||||
|
/*! \brief Run macro
|
||||||
|
*
|
||||||
|
* Call the (normal) macro with number *nr* (max. 7 levels).
|
||||||
|
*/
|
||||||
|
void callMacro(uint nr);
|
||||||
|
|
||||||
|
/*! \brief Run touch macro
|
||||||
|
*
|
||||||
|
* Call touch macro with number *nr* (max. 7 levels)
|
||||||
|
*/
|
||||||
|
void callTouchMacro(uint nr);
|
||||||
|
|
||||||
|
/*! \brief Run menu macro
|
||||||
|
*
|
||||||
|
* Call menu macro with number *nr* (max. 7 levels)
|
||||||
|
*/
|
||||||
|
void callMenuMacro(uint nr);
|
||||||
|
|
||||||
|
/*! \brief Define touch key with menu function
|
||||||
|
*
|
||||||
|
* Define the area from *x1*, *y1* to *x2*, *y2* as a menu key.
|
||||||
|
* The first character determines the direction in which the menu opens (R=right,L=left,O=up,U=down)
|
||||||
|
* The second character determines the alignment of the touch text (C=center,L=left-,R=right justified)
|
||||||
|
* The menu items are separated by the character '|' ($7C,dec:124) (e.g. "UCkey|item1|item2|item3".
|
||||||
|
* The key text is written with the current touch font and the menu items are written with the current menu font. The background of the menu is saved automatically.
|
||||||
|
* \param downcode `1-255` return/touchmacro if pressed
|
||||||
|
* \param upcode `1-255` return/touchmacro if released
|
||||||
|
* \param mnucode return/menumacro+(item nr - 1) after selection of a
|
||||||
|
* menu item
|
||||||
|
* \param text string with the key text and menu items
|
||||||
|
*/
|
||||||
|
void defineTouchMenu(int x1, int y1, int x2, int y2,
|
||||||
|
char downcode, char upcode, char mnucode,
|
||||||
|
const char *text);
|
||||||
|
|
||||||
|
/*! \brief Send *open* signal after a Menu open request has been sent from TFT.
|
||||||
|
*
|
||||||
|
* If a touch menu is not set to open automatically the TFT sends a
|
||||||
|
* request 'ESC T 0'. This function sends 'ESC N T 2' to open the menu.
|
||||||
|
*/
|
||||||
|
void openTouchMenu();
|
||||||
|
|
||||||
|
/*! \brief Set menu font
|
||||||
|
*
|
||||||
|
* Set font with number *font* (`0..15`) for menu display
|
||||||
|
*/
|
||||||
|
void setMenuFont(char font);
|
||||||
|
|
||||||
|
/*! \brief enable/disable touchmenu automation
|
||||||
|
*
|
||||||
|
* if val==true touch menu opens automatically, if val==false touchmenu
|
||||||
|
* doesn' t open automatically, instead a request is sent to the
|
||||||
|
* host computer, which can then open the menu with openTouchMenu()
|
||||||
|
*/
|
||||||
|
void setTouchMenuAutomation(bool val);
|
||||||
|
|
||||||
|
private:
|
||||||
|
boolean _smallprotocol;
|
||||||
|
int _counter;
|
||||||
|
unsigned char bytesAvailable();
|
||||||
|
void waitBytesAvailable();
|
||||||
|
void sendByte(char data);
|
||||||
|
void sendSmall(char* data, char len);
|
||||||
|
void sendSmallDC2(char* data, char len);
|
||||||
|
};
|
||||||
|
#endif
|
|
@ -0,0 +1,165 @@
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
|
||||||
|
This version of the GNU Lesser General Public License incorporates
|
||||||
|
the terms and conditions of version 3 of the GNU General Public
|
||||||
|
License, supplemented by the additional permissions listed below.
|
||||||
|
|
||||||
|
0. Additional Definitions.
|
||||||
|
|
||||||
|
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||||
|
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||||
|
General Public License.
|
||||||
|
|
||||||
|
"The Library" refers to a covered work governed by this License,
|
||||||
|
other than an Application or a Combined Work as defined below.
|
||||||
|
|
||||||
|
An "Application" is any work that makes use of an interface provided
|
||||||
|
by the Library, but which is not otherwise based on the Library.
|
||||||
|
Defining a subclass of a class defined by the Library is deemed a mode
|
||||||
|
of using an interface provided by the Library.
|
||||||
|
|
||||||
|
A "Combined Work" is a work produced by combining or linking an
|
||||||
|
Application with the Library. The particular version of the Library
|
||||||
|
with which the Combined Work was made is also called the "Linked
|
||||||
|
Version".
|
||||||
|
|
||||||
|
The "Minimal Corresponding Source" for a Combined Work means the
|
||||||
|
Corresponding Source for the Combined Work, excluding any source code
|
||||||
|
for portions of the Combined Work that, considered in isolation, are
|
||||||
|
based on the Application, and not on the Linked Version.
|
||||||
|
|
||||||
|
The "Corresponding Application Code" for a Combined Work means the
|
||||||
|
object code and/or source code for the Application, including any data
|
||||||
|
and utility programs needed for reproducing the Combined Work from the
|
||||||
|
Application, but excluding the System Libraries of the Combined Work.
|
||||||
|
|
||||||
|
1. Exception to Section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
You may convey a covered work under sections 3 and 4 of this License
|
||||||
|
without being bound by section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
2. Conveying Modified Versions.
|
||||||
|
|
||||||
|
If you modify a copy of the Library, and, in your modifications, a
|
||||||
|
facility refers to a function or data to be supplied by an Application
|
||||||
|
that uses the facility (other than as an argument passed when the
|
||||||
|
facility is invoked), then you may convey a copy of the modified
|
||||||
|
version:
|
||||||
|
|
||||||
|
a) under this License, provided that you make a good faith effort to
|
||||||
|
ensure that, in the event an Application does not supply the
|
||||||
|
function or data, the facility still operates, and performs
|
||||||
|
whatever part of its purpose remains meaningful, or
|
||||||
|
|
||||||
|
b) under the GNU GPL, with none of the additional permissions of
|
||||||
|
this License applicable to that copy.
|
||||||
|
|
||||||
|
3. Object Code Incorporating Material from Library Header Files.
|
||||||
|
|
||||||
|
The object code form of an Application may incorporate material from
|
||||||
|
a header file that is part of the Library. You may convey such object
|
||||||
|
code under terms of your choice, provided that, if the incorporated
|
||||||
|
material is not limited to numerical parameters, data structure
|
||||||
|
layouts and accessors, or small macros, inline functions and templates
|
||||||
|
(ten or fewer lines in length), you do both of the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the object code that the
|
||||||
|
Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
4. Combined Works.
|
||||||
|
|
||||||
|
You may convey a Combined Work under terms of your choice that,
|
||||||
|
taken together, effectively do not restrict modification of the
|
||||||
|
portions of the Library contained in the Combined Work and reverse
|
||||||
|
engineering for debugging such modifications, if you also do each of
|
||||||
|
the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the Combined Work that
|
||||||
|
the Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
c) For a Combined Work that displays copyright notices during
|
||||||
|
execution, include the copyright notice for the Library among
|
||||||
|
these notices, as well as a reference directing the user to the
|
||||||
|
copies of the GNU GPL and this license document.
|
||||||
|
|
||||||
|
d) Do one of the following:
|
||||||
|
|
||||||
|
0) Convey the Minimal Corresponding Source under the terms of this
|
||||||
|
License, and the Corresponding Application Code in a form
|
||||||
|
suitable for, and under terms that permit, the user to
|
||||||
|
recombine or relink the Application with a modified version of
|
||||||
|
the Linked Version to produce a modified Combined Work, in the
|
||||||
|
manner specified by section 6 of the GNU GPL for conveying
|
||||||
|
Corresponding Source.
|
||||||
|
|
||||||
|
1) Use a suitable shared library mechanism for linking with the
|
||||||
|
Library. A suitable mechanism is one that (a) uses at run time
|
||||||
|
a copy of the Library already present on the user's computer
|
||||||
|
system, and (b) will operate properly with a modified version
|
||||||
|
of the Library that is interface-compatible with the Linked
|
||||||
|
Version.
|
||||||
|
|
||||||
|
e) Provide Installation Information, but only if you would otherwise
|
||||||
|
be required to provide such information under section 6 of the
|
||||||
|
GNU GPL, and only to the extent that such information is
|
||||||
|
necessary to install and execute a modified version of the
|
||||||
|
Combined Work produced by recombining or relinking the
|
||||||
|
Application with a modified version of the Linked Version. (If
|
||||||
|
you use option 4d0, the Installation Information must accompany
|
||||||
|
the Minimal Corresponding Source and Corresponding Application
|
||||||
|
Code. If you use option 4d1, you must provide the Installation
|
||||||
|
Information in the manner specified by section 6 of the GNU GPL
|
||||||
|
for conveying Corresponding Source.)
|
||||||
|
|
||||||
|
5. Combined Libraries.
|
||||||
|
|
||||||
|
You may place library facilities that are a work based on the
|
||||||
|
Library side by side in a single library together with other library
|
||||||
|
facilities that are not Applications and are not covered by this
|
||||||
|
License, and convey such a combined library under terms of your
|
||||||
|
choice, if you do both of the following:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work based
|
||||||
|
on the Library, uncombined with any other library facilities,
|
||||||
|
conveyed under the terms of this License.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library that part of it
|
||||||
|
is a work based on the Library, and explaining where to find the
|
||||||
|
accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
6. Revised Versions of the GNU Lesser General Public License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the GNU Lesser General Public License from time to time. Such new
|
||||||
|
versions will be similar in spirit to the present version, but may
|
||||||
|
differ in detail to address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Library as you received it specifies that a certain numbered version
|
||||||
|
of the GNU Lesser General Public License "or any later version"
|
||||||
|
applies to it, you have the option of following the terms and
|
||||||
|
conditions either of that published version or of any later version
|
||||||
|
published by the Free Software Foundation. If the Library as you
|
||||||
|
received it does not specify a version number of the GNU Lesser
|
||||||
|
General Public License, you may choose any version of the GNU Lesser
|
||||||
|
General Public License ever published by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Library as you received it specifies that a proxy can decide
|
||||||
|
whether future versions of the GNU Lesser General Public License shall
|
||||||
|
apply, that proxy's public statement of acceptance of any version is
|
||||||
|
permanent authorization for you to choose that version for the
|
||||||
|
Library.
|
|
@ -0,0 +1,36 @@
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
Library for controlling Electronic Assembly eDIPTFT displays
|
||||||
|
|
||||||
|
Copyright (c) 2013 Stefan Gofferje. All rights reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 3 of the License, or (at your option) any later
|
||||||
|
version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be
|
||||||
|
useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||||
|
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. See the GNU Lesser General Public License for more
|
||||||
|
details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General
|
||||||
|
Public License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
Boston, MA 02110-1301 USA
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
There isn't much documentation yet. I have started to write the functions on
|
||||||
|
25JAN2013 and converted them into a library on 01FEB2013. I'm mainly
|
||||||
|
developing this library inside another projects, so functions are added as
|
||||||
|
they are needed in that other project. Once the other project is ready, I
|
||||||
|
might complete this library.
|
||||||
|
|
||||||
|
Documentation on the eDIPTFT series is available from
|
||||||
|
|
||||||
|
http://www.lcd-module.com/
|
||||||
|
|
||||||
|
CAVEAT: When using Smallprotocol to communicate with the display (highly
|
||||||
|
recommended!) via RS232, the display MUST be selected by with a select
|
||||||
|
command, otherwise it will ignore ANY communication!
|
|
@ -0,0 +1,55 @@
|
||||||
|
|
||||||
|
A library for controlling Electronic Assembly eDIPTFT displays.
|
||||||
|
|
||||||
|
* copyright (c) 2015 by Stefan Lehmann
|
||||||
|
* licensed under the GNU Lesser General Public Licens (LGPL)
|
||||||
|
|
||||||
|
This is a fork of the [ediptft library][edip1] written by *Stefan Gofferje*.
|
||||||
|
As its original it is licensed under the GNU Lesser General Public License
|
||||||
|
(LGPL). See the original copyright note at the bottom of this file.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
* draw text, lines, rectangles
|
||||||
|
* define touch areas
|
||||||
|
* define radio touch groups
|
||||||
|
* define menus
|
||||||
|
* call macros, touch macros and menu macros
|
||||||
|
* draw bargraphs and define them as touch areas
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
#include <ediptft.h>
|
||||||
|
|
||||||
|
EDIPTFT tft = EDIPTFT();
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
tft.begin(115200); // start display communication
|
||||||
|
tft.clear(); // clear display
|
||||||
|
tft.setTextFont(EA_GENEVA10); // set a text font
|
||||||
|
tft.drawText(100, 30, 'C', "Hello World"); // draw some text
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
## Original copyright note
|
||||||
|
|
||||||
|
Copyright (c) 2013 Stefan Gofferje. All rights reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 3 of the License, or (at your option) any later
|
||||||
|
version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be
|
||||||
|
useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||||
|
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. See the GNU Lesser General Public License for more
|
||||||
|
details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General
|
||||||
|
Public License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
[edip1]:https://github.com/sgofferj/EDIPTFT
|
|
@ -0,0 +1,31 @@
|
||||||
|
EDIPTFT KEYWORD1
|
||||||
|
ESC KEYWORD1
|
||||||
|
ACK KEYWORD1
|
||||||
|
NAK KEYWORD1
|
||||||
|
sendData KEYWORD2
|
||||||
|
clear KEYWORD2
|
||||||
|
invert KEYWORD2
|
||||||
|
setDisplayColor KEYWORD2
|
||||||
|
fillDisplayColor KEYWORD2
|
||||||
|
terminalOn KEYWORD2
|
||||||
|
cursorOn KEYWORD2
|
||||||
|
setCursor KEYWORD2
|
||||||
|
defineBargraph KEYWORD2
|
||||||
|
updateBargraph KEYWORD2
|
||||||
|
setBargraphColor KEYWORD2
|
||||||
|
makeBargraphTouch KEYWORD2
|
||||||
|
linkBargraphLight KEYWORD2
|
||||||
|
deleteBargraph KEYWORD2
|
||||||
|
setTextColor KEYWORD2
|
||||||
|
setTextFont KEYWORD2
|
||||||
|
setTextAngle KEYWORD2
|
||||||
|
drawText KEYWORD2
|
||||||
|
setLineColor KEYWORD2
|
||||||
|
drawLine KEYWORD2
|
||||||
|
drawRect KEYWORD2
|
||||||
|
drawRectf KEYWORD2
|
||||||
|
defineTouchKey KEYWORD2
|
||||||
|
setTouchkeyColors KEYWORD2
|
||||||
|
setTouchkeyFont KEYWORD2
|
||||||
|
setTouchkeyLabelColors KEYWORD2
|
||||||
|
removeTouchArea KEYWORD2
|
|
@ -0,0 +1,9 @@
|
||||||
|
due_can
|
||||||
|
=======
|
||||||
|
|
||||||
|
Object oriented canbus library for Arduino Due compatible boards
|
||||||
|
|
||||||
|
Download the archived 1.0 release if you are compiling against existing
|
||||||
|
code bases such as the EVTV GEVCU project. New projects will probably
|
||||||
|
find that the current "master" branch version of the project is easier
|
||||||
|
to use.
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,314 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2013 Arduino. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
See the GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _CAN_LIBRARY_
|
||||||
|
#define _CAN_LIBRARY_
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
//add some extra stuff that is needed for Arduino 1.5.2
|
||||||
|
#ifndef PINS_CAN0
|
||||||
|
static const uint8_t CAN1RX = 88;
|
||||||
|
static const uint8_t CAN1TX = 89;
|
||||||
|
|
||||||
|
// CAN0
|
||||||
|
#define PINS_CAN0 (90u)
|
||||||
|
// CAN1
|
||||||
|
#define PINS_CAN1 (91u)
|
||||||
|
#define ARDUINO152
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define CAN Can0
|
||||||
|
#define CAN2 Can1
|
||||||
|
|
||||||
|
#define CAN0_EN 50 //these enable pins match most all recent EVTV boards (EVTVDue, CAN Due 2.0)
|
||||||
|
#define CAN1_EN 48 //they're only defaults, you can set whichever pin you need when calling begin()
|
||||||
|
|
||||||
|
/** Define the Mailbox mask for eight mailboxes. */
|
||||||
|
#define GLOBAL_MAILBOX_MASK 0x000000ff
|
||||||
|
|
||||||
|
/** Disable all interrupt mask */
|
||||||
|
#define CAN_DISABLE_ALL_INTERRUPT_MASK 0xffffffff
|
||||||
|
|
||||||
|
/** Define the typical baudrate for CAN communication. */
|
||||||
|
#ifdef CAN_BPS_500K
|
||||||
|
#undef CAN_BPS_1000K
|
||||||
|
#undef CAN_BPS_800K
|
||||||
|
#undef CAN_BPS_500K
|
||||||
|
#undef CAN_BPS_250K
|
||||||
|
#undef CAN_BPS_125K
|
||||||
|
#undef CAN_BPS_50K
|
||||||
|
#undef CAN_BPS_33333
|
||||||
|
#undef CAN_BPS_25K
|
||||||
|
#undef CAN_BPS_10K
|
||||||
|
#undef CAN_BPS_5K
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define CAN_BPS_1000K 1000000
|
||||||
|
#define CAN_BPS_800K 800000
|
||||||
|
#define CAN_BPS_500K 500000
|
||||||
|
#define CAN_BPS_250K 250000
|
||||||
|
#define CAN_BPS_125K 125000
|
||||||
|
#define CAN_BPS_50K 50000
|
||||||
|
#define CAN_BPS_33333 33333
|
||||||
|
#define CAN_BPS_25K 25000
|
||||||
|
#define CAN_BPS_10K 10000
|
||||||
|
#define CAN_BPS_5K 5000
|
||||||
|
|
||||||
|
#define CAN_DEFAULT_BAUD CAN_BPS_250K
|
||||||
|
|
||||||
|
/** Define the mailbox mode. */
|
||||||
|
#define CAN_MB_DISABLE_MODE 0
|
||||||
|
#define CAN_MB_RX_MODE 1
|
||||||
|
#define CAN_MB_RX_OVER_WR_MODE 2
|
||||||
|
#define CAN_MB_TX_MODE 3
|
||||||
|
#define CAN_MB_CONSUMER_MODE 4
|
||||||
|
#define CAN_MB_PRODUCER_MODE 5
|
||||||
|
|
||||||
|
/** Define CAN mailbox transfer status code. */
|
||||||
|
#define CAN_MAILBOX_TRANSFER_OK 0 //! Read from or write into mailbox successfully.
|
||||||
|
#define CAN_MAILBOX_NOT_READY 0x01 //! Receiver is empty or transmitter is busy.
|
||||||
|
#define CAN_MAILBOX_RX_OVER 0x02 //! Message overwriting happens or there're messages lost in different receive modes.
|
||||||
|
#define CAN_MAILBOX_RX_NEED_RD_AGAIN 0x04 //! Application needs to re-read the data register in Receive with Overwrite mode.
|
||||||
|
|
||||||
|
#define SIZE_RX_BUFFER 32 //RX incoming ring buffer is this big
|
||||||
|
#define SIZE_TX_BUFFER 16 //TX ring buffer is this big
|
||||||
|
#define SIZE_LISTENERS 4 //number of classes that can register as listeners with this class
|
||||||
|
|
||||||
|
/** Define the timemark mask. */
|
||||||
|
#define TIMEMARK_MASK 0x0000ffff
|
||||||
|
|
||||||
|
/* CAN timeout for synchronization. */
|
||||||
|
#define CAN_TIMEOUT 100000
|
||||||
|
|
||||||
|
/** The max value for CAN baudrate prescale. */
|
||||||
|
#define CAN_BAUDRATE_MAX_DIV 128
|
||||||
|
|
||||||
|
/** Define the scope for TQ. */
|
||||||
|
#define CAN_MIN_TQ_NUM 8
|
||||||
|
#define CAN_MAX_TQ_NUM 25
|
||||||
|
|
||||||
|
/** Define the fixed bit time value. */
|
||||||
|
#define CAN_BIT_SYNC 1
|
||||||
|
#define CAN_BIT_IPT 2
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t uc_tq; //! CAN_BIT_SYNC + uc_prog + uc_phase1 + uc_phase2 = uc_tq, 8 <= uc_tq <= 25.
|
||||||
|
uint8_t uc_prog; //! Propagation segment, (3-bits + 1), 1~8;
|
||||||
|
uint8_t uc_phase1; //! Phase segment 1, (3-bits + 1), 1~8;
|
||||||
|
uint8_t uc_phase2; //! Phase segment 2, (3-bits + 1), 1~8, CAN_BIT_IPT <= uc_phase2;
|
||||||
|
uint8_t uc_sjw; //! Resynchronization jump width, (2-bits + 1), min(uc_phase1, 4);
|
||||||
|
uint8_t uc_sp; //! Sample point value, 0~100 in percent.
|
||||||
|
} can_bit_timing_t;
|
||||||
|
|
||||||
|
|
||||||
|
/** Values of bit time register for different baudrates, Sample point = ((1 + uc_prog + uc_phase1) / uc_tq) * 100%. */
|
||||||
|
const can_bit_timing_t can_bit_time[] = {
|
||||||
|
{8, (2 + 1), (1 + 1), (1 + 1), (2 + 1), 75},
|
||||||
|
{9, (1 + 1), (2 + 1), (2 + 1), (1 + 1), 67},
|
||||||
|
{10, (2 + 1), (2 + 1), (2 + 1), (2 + 1), 70},
|
||||||
|
{11, (3 + 1), (2 + 1), (2 + 1), (3 + 1), 72},
|
||||||
|
{12, (2 + 1), (3 + 1), (3 + 1), (3 + 1), 67},
|
||||||
|
{13, (3 + 1), (3 + 1), (3 + 1), (3 + 1), 77},
|
||||||
|
{14, (3 + 1), (3 + 1), (4 + 1), (3 + 1), 64},
|
||||||
|
{15, (3 + 1), (4 + 1), (4 + 1), (3 + 1), 67},
|
||||||
|
{16, (4 + 1), (4 + 1), (4 + 1), (3 + 1), 69},
|
||||||
|
{17, (5 + 1), (4 + 1), (4 + 1), (3 + 1), 71},
|
||||||
|
{18, (4 + 1), (5 + 1), (5 + 1), (3 + 1), 67},
|
||||||
|
{19, (5 + 1), (5 + 1), (5 + 1), (3 + 1), 68},
|
||||||
|
{20, (6 + 1), (5 + 1), (5 + 1), (3 + 1), 70},
|
||||||
|
{21, (7 + 1), (5 + 1), (5 + 1), (3 + 1), 71},
|
||||||
|
{22, (6 + 1), (6 + 1), (6 + 1), (3 + 1), 68},
|
||||||
|
{23, (7 + 1), (7 + 1), (6 + 1), (3 + 1), 70},
|
||||||
|
{24, (6 + 1), (7 + 1), (7 + 1), (3 + 1), 67},
|
||||||
|
{25, (7 + 1), (7 + 1), (7 + 1), (3 + 1), 68}
|
||||||
|
};
|
||||||
|
|
||||||
|
//This is architecture specific. DO NOT USE THIS UNION ON ANYTHING OTHER THAN THE CORTEX M3 / Arduino Due
|
||||||
|
//UNLESS YOU DOUBLE CHECK THINGS!
|
||||||
|
typedef union {
|
||||||
|
uint64_t value;
|
||||||
|
struct {
|
||||||
|
uint32_t low;
|
||||||
|
uint32_t high;
|
||||||
|
};
|
||||||
|
struct {
|
||||||
|
uint16_t s0;
|
||||||
|
uint16_t s1;
|
||||||
|
uint16_t s2;
|
||||||
|
uint16_t s3;
|
||||||
|
};
|
||||||
|
uint8_t bytes[8];
|
||||||
|
uint8_t byte[8]; //alternate name so you can omit the s if you feel it makes more sense
|
||||||
|
} BytesUnion;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint32_t id; // EID if ide set, SID otherwise
|
||||||
|
uint32_t fid; // family ID
|
||||||
|
uint8_t rtr; // Remote Transmission Request
|
||||||
|
uint8_t priority; // Priority but only important for TX frames and then only for special uses.
|
||||||
|
uint8_t extended; // Extended ID flag
|
||||||
|
uint8_t length; // Number of data bytes
|
||||||
|
BytesUnion data; // 64 bits - lots of ways to access it.
|
||||||
|
} CAN_FRAME;
|
||||||
|
|
||||||
|
class CANListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CANListener();
|
||||||
|
|
||||||
|
virtual void gotFrame(CAN_FRAME *frame, int mailbox);
|
||||||
|
|
||||||
|
void attachMBHandler(uint8_t mailBox);
|
||||||
|
void detachMBHandler(uint8_t mailBox);
|
||||||
|
void attachGeneralHandler();
|
||||||
|
void detachGeneralHandler();
|
||||||
|
|
||||||
|
private:
|
||||||
|
int callbacksActive; //bitfield letting the code know which callbacks to actually try to use (for object oriented callbacks only)
|
||||||
|
|
||||||
|
friend class CANRaw; //class has to have access to the the guts of this one
|
||||||
|
};
|
||||||
|
|
||||||
|
class CANRaw
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
int numTXBoxes; //There are 8 mailboxes, anything not TX will be set RX
|
||||||
|
|
||||||
|
private:
|
||||||
|
/* CAN peripheral, set by constructor */
|
||||||
|
Can* m_pCan ;
|
||||||
|
|
||||||
|
volatile CAN_FRAME rx_frame_buff[SIZE_RX_BUFFER];
|
||||||
|
volatile CAN_FRAME tx_frame_buff[SIZE_TX_BUFFER];
|
||||||
|
|
||||||
|
volatile uint16_t rx_buffer_head, rx_buffer_tail;
|
||||||
|
volatile uint16_t tx_buffer_head, tx_buffer_tail;
|
||||||
|
void mailbox_int_handler(uint8_t mb, uint32_t ul_status);
|
||||||
|
|
||||||
|
uint8_t enablePin;
|
||||||
|
uint32_t busSpeed; //what speed is the bus currently initialized at? 0 if it is off right now
|
||||||
|
|
||||||
|
uint32_t write_id; //public storage for an id. Will be used by the write function to set which ID to send to.
|
||||||
|
bool bigEndian;
|
||||||
|
|
||||||
|
void (*cbCANFrame[9])(CAN_FRAME *); //8 mailboxes plus an optional catch all
|
||||||
|
CANListener *listener[SIZE_LISTENERS];
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
CANRaw( Can* pCan, uint32_t En);
|
||||||
|
|
||||||
|
int setRXFilter(uint32_t id, uint32_t mask, bool extended);
|
||||||
|
int setRXFilter(uint8_t mailbox, uint32_t id, uint32_t mask, bool extended);
|
||||||
|
int watchFor(); //allow anything through
|
||||||
|
int watchFor(uint32_t id); //allow just this ID through (automatic determination of extended status)
|
||||||
|
int watchFor(uint32_t id, uint32_t mask); //allow a range of ids through
|
||||||
|
int watchForRange(uint32_t id1, uint32_t id2); //try to allow the range from id1 to id2 - automatically determine base ID and mask
|
||||||
|
|
||||||
|
void setNumTXBoxes(int txboxes);
|
||||||
|
int findFreeRXMailbox();
|
||||||
|
uint8_t mailbox_get_mode(uint8_t uc_index);
|
||||||
|
uint32_t mailbox_get_id(uint8_t uc_index);
|
||||||
|
uint32_t getMailboxIer(int8_t mailbox);
|
||||||
|
uint32_t set_baudrate(uint32_t ul_baudrate);
|
||||||
|
|
||||||
|
uint32_t init(uint32_t ul_baudrate);
|
||||||
|
uint32_t begin();
|
||||||
|
uint32_t begin(uint32_t baudrate);
|
||||||
|
uint32_t begin(uint32_t baudrate, uint8_t enablePin);
|
||||||
|
uint32_t getBusSpeed();
|
||||||
|
|
||||||
|
void enable();
|
||||||
|
void disable();
|
||||||
|
|
||||||
|
bool sendFrame(CAN_FRAME& txFrame);
|
||||||
|
void setWriteID(uint32_t id);
|
||||||
|
template <typename t> void write(t inputValue); //write a variable # of bytes out in a frame. Uses id as the ID.
|
||||||
|
void setBigEndian(bool);
|
||||||
|
|
||||||
|
void setCallback(int mailbox, void (*cb)(CAN_FRAME *));
|
||||||
|
void setGeneralCallback(void (*cb)(CAN_FRAME *));
|
||||||
|
//note that these below versions still use mailbox number. There isn't a good way around this.
|
||||||
|
void attachCANInterrupt(void (*cb)(CAN_FRAME *)); //alternative callname for setGeneralCallback
|
||||||
|
void attachCANInterrupt(uint8_t mailBox, void (*cb)(CAN_FRAME *));
|
||||||
|
void detachCANInterrupt(uint8_t mailBox);
|
||||||
|
|
||||||
|
//now, object oriented versions to make OO projects easier
|
||||||
|
boolean attachObj(CANListener *listener);
|
||||||
|
boolean detachObj(CANListener *listener);
|
||||||
|
|
||||||
|
void reset_all_mailbox();
|
||||||
|
void interruptHandler();
|
||||||
|
bool rx_avail();
|
||||||
|
int available(); //like rx_avail but returns the number of waiting frames
|
||||||
|
|
||||||
|
uint32_t get_rx_buff(CAN_FRAME &);
|
||||||
|
uint32_t read(CAN_FRAME &);
|
||||||
|
|
||||||
|
//misc old cruft kept around just in case anyone actually used any of it in older code.
|
||||||
|
//some are used within the functions above. Unless you really know of a good reason to use
|
||||||
|
//any of these you probably should steer clear of them.
|
||||||
|
void disable_low_power_mode();
|
||||||
|
void enable_low_power_mode();
|
||||||
|
void disable_autobaud_listen_mode();
|
||||||
|
void enable_autobaud_listen_mode();
|
||||||
|
void disable_overload_frame();
|
||||||
|
void enable_overload_frame();
|
||||||
|
void set_timestamp_capture_point(uint32_t ul_flag);
|
||||||
|
void disable_time_triggered_mode();
|
||||||
|
void enable_time_triggered_mode();
|
||||||
|
void disable_timer_freeze();
|
||||||
|
void enable_timer_freeze();
|
||||||
|
void disable_tx_repeat();
|
||||||
|
void enable_tx_repeat();
|
||||||
|
void set_rx_sync_stage(uint32_t ul_stage);
|
||||||
|
void enable_interrupt(uint32_t dw_mask);
|
||||||
|
void disable_interrupt(uint32_t dw_mask);
|
||||||
|
uint32_t get_interrupt_mask();
|
||||||
|
uint32_t get_status();
|
||||||
|
uint32_t get_internal_timer_value();
|
||||||
|
uint32_t get_timestamp_value();
|
||||||
|
uint8_t get_tx_error_cnt();
|
||||||
|
uint8_t get_rx_error_cnt();
|
||||||
|
void reset_internal_timer();
|
||||||
|
void global_send_transfer_cmd(uint8_t uc_mask);
|
||||||
|
void global_send_abort_cmd(uint8_t uc_mask);
|
||||||
|
void mailbox_set_timemark(uint8_t uc_index, uint16_t us_cnt);
|
||||||
|
uint32_t mailbox_get_status(uint8_t uc_index);
|
||||||
|
void mailbox_send_transfer_cmd(uint8_t uc_index);
|
||||||
|
void mailbox_send_abort_cmd(uint8_t uc_index);
|
||||||
|
void mailbox_init(uint8_t uc_index);
|
||||||
|
uint32_t mailbox_read(uint8_t uc_index, volatile CAN_FRAME *rxframe);
|
||||||
|
uint32_t mailbox_tx_frame(uint8_t uc_index);
|
||||||
|
void mailbox_set_id(uint8_t uc_index, uint32_t id, bool extended);
|
||||||
|
void mailbox_set_priority(uint8_t uc_index, uint8_t pri);
|
||||||
|
void mailbox_set_accept_mask(uint8_t uc_index, uint32_t mask, bool ext);
|
||||||
|
void mailbox_set_mode(uint8_t uc_index, uint8_t mode);
|
||||||
|
void mailbox_set_databyte(uint8_t uc_index, uint8_t bytepos, uint8_t val);
|
||||||
|
void mailbox_set_datalen(uint8_t uc_index, uint8_t dlen);
|
||||||
|
void mailbox_set_datal(uint8_t uc_index, uint32_t val);
|
||||||
|
void mailbox_set_datah(uint8_t uc_index, uint32_t val);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern CANRaw Can0;
|
||||||
|
extern CANRaw Can1;
|
||||||
|
|
||||||
|
#endif // _CAN_LIBRARY_
|
|
@ -0,0 +1,87 @@
|
||||||
|
// Arduino Due - CAN Sample 1
|
||||||
|
// Brief CAN example for Arduino Due
|
||||||
|
// Test the transmission from CAN0 Mailbox 0 to CAN1 Mailbox 0
|
||||||
|
// By Thibaut Viard/Wilfredo Molina/Collin Kidder 2013
|
||||||
|
|
||||||
|
// Required libraries
|
||||||
|
#include "variant.h"
|
||||||
|
#include <due_can.h>
|
||||||
|
|
||||||
|
#define TEST1_CAN_COMM_MB_IDX 0
|
||||||
|
#define TEST1_CAN_TRANSFER_ID 0x07
|
||||||
|
#define TEST1_CAN0_TX_PRIO 15
|
||||||
|
#define CAN_MSG_DUMMY_DATA 0x55AAEE22
|
||||||
|
|
||||||
|
// CAN frame max data length
|
||||||
|
#define MAX_CAN_FRAME_DATA_LEN 8
|
||||||
|
|
||||||
|
// Message variable to be send
|
||||||
|
uint32_t CAN_MSG_1 = 0;
|
||||||
|
|
||||||
|
//Leave defined if you use native port, comment if using programming port
|
||||||
|
#define Serial SerialUSB
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
CAN_FRAME output;
|
||||||
|
|
||||||
|
// start serial port at 9600 bps:
|
||||||
|
Serial.begin(9600);
|
||||||
|
Serial.println("Type CAN message to send");
|
||||||
|
while (Serial.available() == 0);
|
||||||
|
}
|
||||||
|
void loop(){
|
||||||
|
|
||||||
|
CAN_FRAME output;
|
||||||
|
while (Serial.available() > 0) {
|
||||||
|
CAN_MSG_1 = Serial.parseInt();
|
||||||
|
if (Serial.read() == '\n') {
|
||||||
|
Serial.print("Sent value= ");
|
||||||
|
Serial.println(CAN_MSG_1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize CAN0 and CAN1, baudrate is 250kb/s
|
||||||
|
Can0.begin(CAN_BPS_250K);
|
||||||
|
Can1.begin(CAN_BPS_250K);
|
||||||
|
|
||||||
|
//The default is to allow nothing through if nothing is specified
|
||||||
|
|
||||||
|
//only allow this one frame ID through.
|
||||||
|
Can1.watchFor(TEST1_CAN_TRANSFER_ID);
|
||||||
|
|
||||||
|
// Prepare transmit ID, data and data length in CAN0 mailbox 0
|
||||||
|
output.id = TEST1_CAN_TRANSFER_ID;
|
||||||
|
output.length = MAX_CAN_FRAME_DATA_LEN;
|
||||||
|
//Set first four bytes (32 bits) all at once
|
||||||
|
output.data.low = CAN_MSG_1;
|
||||||
|
//Set last four bytes (32 bits) all at once
|
||||||
|
output.data.high = CAN_MSG_DUMMY_DATA;
|
||||||
|
//Send out the frame on whichever mailbox is free or queue it for
|
||||||
|
//sending when there is an opening.
|
||||||
|
CAN.sendFrame(output);
|
||||||
|
|
||||||
|
// Wait for second canbus port to receive the frame
|
||||||
|
while (Can1.available() == 0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the received data from CAN1 mailbox 0
|
||||||
|
CAN_FRAME incoming;
|
||||||
|
Can1.read(incoming);
|
||||||
|
|
||||||
|
Serial.print("CAN message received= ");
|
||||||
|
Serial.print(incoming.data.low, HEX);
|
||||||
|
Serial.print(incoming.data.high, HEX);
|
||||||
|
|
||||||
|
// Disable CAN0 Controller
|
||||||
|
Can0.disable();
|
||||||
|
|
||||||
|
// Disable CAN1 Controller
|
||||||
|
Can1.disable();
|
||||||
|
|
||||||
|
Serial.print("\nEnd of test");
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
// Arduino Due - CANbus Library - Extended Frames with Ping/Pong sending
|
||||||
|
// Ping/Pong torture test with extended frames.
|
||||||
|
// This example sets up a receive and transmit mailbox on both canbus devices.
|
||||||
|
// First CAN0 sends to CAN1. When CAN1 receives it sends to CAN0. PING/PONGs forever
|
||||||
|
// and as quickly as possible - This will saturate the bus so don't have anything important connected.
|
||||||
|
// By Thibaut Viard/Wilfredo Molina/Collin Kidder 2014
|
||||||
|
|
||||||
|
// Required libraries
|
||||||
|
#include "variant.h"
|
||||||
|
#include <due_can.h>
|
||||||
|
|
||||||
|
#define TEST1_CAN_TRANSFER_ID 0x11AE756A //random 29 bits
|
||||||
|
#define TEST1_CAN0_TX_PRIO 15
|
||||||
|
#define CAN_MSG_DUMMY_DATA 0x11BFFA4E
|
||||||
|
|
||||||
|
// CAN frame max data length
|
||||||
|
#define MAX_CAN_FRAME_DATA_LEN 8
|
||||||
|
|
||||||
|
uint32_t sentFrames, receivedFrames;
|
||||||
|
|
||||||
|
//Leave this defined if you use the native port or comment it out if you use the programming port
|
||||||
|
#define Serial SerialUSB
|
||||||
|
|
||||||
|
CAN_FRAME frame1, frame2, incoming;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
|
||||||
|
// start serial port at 115200 bps:
|
||||||
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
// Verify CAN0 and CAN1 initialization, baudrate is 1Mb/s:
|
||||||
|
if (Can0.begin(CAN_BPS_1000K) &&
|
||||||
|
Can1.begin(CAN_BPS_1000K)) {
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Serial.println("CAN initialization (sync) ERROR");
|
||||||
|
}
|
||||||
|
|
||||||
|
//Initialize the definitions for the frames we'll be sending.
|
||||||
|
//This can be done here because the frame never changes
|
||||||
|
frame1.id = TEST1_CAN_TRANSFER_ID;
|
||||||
|
frame1.length = MAX_CAN_FRAME_DATA_LEN;
|
||||||
|
//Below we set the 8 data bytes in 32 bit (4 byte) chunks
|
||||||
|
//Bytes can be set individually with frame1.data.bytes[which] = something
|
||||||
|
frame1.data.low = 0x20103040;
|
||||||
|
frame1.data.high = CAN_MSG_DUMMY_DATA;
|
||||||
|
//We are using extended frames so mark that here. Otherwise it will just use
|
||||||
|
//the first 11 bits of the ID set
|
||||||
|
frame1.extended = 1;
|
||||||
|
|
||||||
|
frame2.id = TEST1_CAN_TRANSFER_ID + 0x200;
|
||||||
|
frame2.length = MAX_CAN_FRAME_DATA_LEN;
|
||||||
|
frame2.data.low = 0xB8C8A8E8;
|
||||||
|
frame2.data.high = 0x01020304;
|
||||||
|
frame2.extended = 1;
|
||||||
|
|
||||||
|
//Both of these lines create a filter on the corresponding CAN device that allows
|
||||||
|
//just the one ID we're interested in to get through.
|
||||||
|
//The syntax is (mailbox #, ID, mask, extended)
|
||||||
|
//You can also leave off the mailbox number: (ID, mask, extended)
|
||||||
|
Can1.watchFor(TEST1_CAN_TRANSFER_ID + 0x200);
|
||||||
|
Can0.watchFor(TEST1_CAN_TRANSFER_ID);
|
||||||
|
|
||||||
|
test_1();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test rapid fire ping/pong of extended frames
|
||||||
|
static void test_1(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
CAN_FRAME inFrame;
|
||||||
|
uint32_t counter = 0;
|
||||||
|
|
||||||
|
// Send out the first frame
|
||||||
|
Can0.sendFrame(frame2);
|
||||||
|
sentFrames++;
|
||||||
|
|
||||||
|
while (1==1) {
|
||||||
|
if (Can0.available() > 0) {
|
||||||
|
Can0.read(incoming);
|
||||||
|
Can0.sendFrame(frame2);
|
||||||
|
delayMicroseconds(100);
|
||||||
|
sentFrames++;
|
||||||
|
receivedFrames++;
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
if (Can1.available() > 0) {
|
||||||
|
Can1.read(incoming);
|
||||||
|
Can1.sendFrame(frame1);
|
||||||
|
delayMicroseconds(100);
|
||||||
|
sentFrames++;
|
||||||
|
receivedFrames++;
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
if (counter > 5000) {
|
||||||
|
counter = 0;
|
||||||
|
Serial.print("S: ");
|
||||||
|
Serial.print(sentFrames);
|
||||||
|
Serial.print(" R: ");
|
||||||
|
Serial.println(receivedFrames);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// can_example application entry point
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
//Reads all traffic on CAN0 and forwards it to CAN1 (and in the reverse direction) but modifies some frames first.
|
||||||
|
// Required libraries
|
||||||
|
#include "variant.h"
|
||||||
|
#include <due_can.h>
|
||||||
|
|
||||||
|
//Leave defined if you use native port, comment if using programming port
|
||||||
|
#define Serial SerialUSB
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
|
||||||
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
// Initialize CAN0 and CAN1, Set the proper baud rates here
|
||||||
|
Can0.begin(CAN_BPS_250K);
|
||||||
|
Can1.begin(CAN_BPS_250K);
|
||||||
|
|
||||||
|
Can0.watchFor();
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendData()
|
||||||
|
{
|
||||||
|
CAN_FRAME outgoing;
|
||||||
|
outgoing.id = 0x400;
|
||||||
|
outgoing.extended = false;
|
||||||
|
outgoing.priority = 4; //0-15 lower is higher priority
|
||||||
|
|
||||||
|
outgoing.data.s0 = 0xFEED;
|
||||||
|
outgoing.data.byte[2] = 0xDD;
|
||||||
|
outgoing.data.byte[3] = 0x55;
|
||||||
|
outgoing.data.high = 0xDEADBEEF;
|
||||||
|
Can0.sendFrame(outgoing);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop(){
|
||||||
|
CAN_FRAME incoming;
|
||||||
|
static unsigned long lastTime = 0;
|
||||||
|
|
||||||
|
if (Can0.available() > 0) {
|
||||||
|
Can0.read(incoming);
|
||||||
|
Can1.sendFrame(incoming);
|
||||||
|
}
|
||||||
|
if (Can1.available() > 0) {
|
||||||
|
Can1.read(incoming);
|
||||||
|
Can0.sendFrame(incoming);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((millis() - lastTime) > 1000)
|
||||||
|
{
|
||||||
|
lastTime = millis();
|
||||||
|
sendData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
// Arduino Due - Displays all traffic found on either canbus port
|
||||||
|
//Modified version of the SnooperCallback sketch. This one illustrates
|
||||||
|
//how to use a class object to receive callbacks. It's a little different
|
||||||
|
//from the non-OO approach.
|
||||||
|
|
||||||
|
// By Thibaut Viard/Wilfredo Molina/Collin Kidder 2013-2015
|
||||||
|
|
||||||
|
// Required libraries
|
||||||
|
#include "variant.h"
|
||||||
|
#include <due_can.h>
|
||||||
|
|
||||||
|
//Leave defined if you use native port, comment if using programming port
|
||||||
|
//This sketch could provide a lot of traffic so it might be best to use the
|
||||||
|
//native port
|
||||||
|
#define Serial SerialUSB
|
||||||
|
|
||||||
|
class ExampleClass : public CANListener //CANListener provides an interface to get callbacks on this class
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void printFrame(CAN_FRAME *frame, int mailbox);
|
||||||
|
void gotFrame(CAN_FRAME *frame, int mailbox); //overrides the parent version so we can actually do something
|
||||||
|
};
|
||||||
|
|
||||||
|
//Prints out the most useful information about the incoming frame.
|
||||||
|
void ExampleClass::printFrame(CAN_FRAME *frame, int mailbox)
|
||||||
|
{
|
||||||
|
Serial.print("MB: ");
|
||||||
|
if (mailbox > -1) Serial.print(mailbox);
|
||||||
|
else Serial.print("???");
|
||||||
|
Serial.print(" ID: 0x");
|
||||||
|
Serial.print(frame->id, HEX);
|
||||||
|
Serial.print(" Len: ");
|
||||||
|
Serial.print(frame->length);
|
||||||
|
Serial.print(" Data: 0x");
|
||||||
|
for (int count = 0; count < frame->length; count++) {
|
||||||
|
Serial.print(frame->data.bytes[count], HEX);
|
||||||
|
Serial.print(" ");
|
||||||
|
}
|
||||||
|
Serial.print("\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
//Classes register just one method that receives all callbacks. If a frame didn't match any specific mailbox
|
||||||
|
//callback but the general callback was registered then the mailbox will be set as -1. Otherwise it is the mailbox
|
||||||
|
//with the matching filter for this frame.
|
||||||
|
void ExampleClass::gotFrame(CAN_FRAME* frame, int mailbox)
|
||||||
|
{
|
||||||
|
this->printFrame(frame, mailbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
ExampleClass myClass; //initialize the class global so the reference to it can be picked up anywhere
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
|
||||||
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
// Initialize CAN0, Set the proper baud rates here
|
||||||
|
// Pass the proper pin for enabling your transceiver or 255 if you don't need an enable pin to be toggled.
|
||||||
|
Can0.begin(CAN_BPS_500K, 50);
|
||||||
|
|
||||||
|
//By default there are 7 RX mailboxes for each device
|
||||||
|
//extended
|
||||||
|
//syntax is mailbox, ID, mask, extended
|
||||||
|
Can0.setRXFilter(0, 0x2FF00, 0x1FF2FF00, true);
|
||||||
|
Can0.setRXFilter(1, 0x1F0000, 0x1F1F0000, true);
|
||||||
|
Can0.setRXFilter(2, 0, 0, true); //catch all mailbox
|
||||||
|
|
||||||
|
//standard
|
||||||
|
Can0.setRXFilter(3, 0x40F, 0x7FF, false);
|
||||||
|
Can0.setRXFilter(4, 0x310, 0x7F0, false);
|
||||||
|
Can0.setRXFilter(5, 0x200, 0x700, false);
|
||||||
|
Can0.setRXFilter(6, 0, 0, false); //catch all mailbox
|
||||||
|
|
||||||
|
Can0.attachObj(&myClass);
|
||||||
|
//let library know we want to receive callbacks for the following mailboxes
|
||||||
|
//once we attach above the canbus object knows about us. The actual functions
|
||||||
|
//to attach are members of CANListener so use your class name
|
||||||
|
myClass.attachMBHandler(0);
|
||||||
|
myClass.attachMBHandler(1);
|
||||||
|
myClass.attachMBHandler(3);
|
||||||
|
myClass.attachMBHandler(4);
|
||||||
|
myClass.attachMBHandler(5);
|
||||||
|
|
||||||
|
//set to get a callback for any other mailboxes not already covered above
|
||||||
|
myClass.attachGeneralHandler();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop(){ //All work is done via callback as frames come in - no need to poll for them. SO, just print periodic message to show we're alive
|
||||||
|
delay(5000);
|
||||||
|
Serial.println("Still listening");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,101 @@
|
||||||
|
/*
|
||||||
|
Arduino Due - Displays frames that fall between a range of addresses.
|
||||||
|
Modified from some of the other examples - notably CAN_SnooperCallBack
|
||||||
|
The difference here is that we only allow a range of ids. This demonstrates
|
||||||
|
the new watchForRange function as well as per-mailbox and general callback
|
||||||
|
functionality
|
||||||
|
|
||||||
|
By Thibaut Viard/Wilfredo Molina/Collin Kidder 2013-2014
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Required libraries
|
||||||
|
#include "variant.h"
|
||||||
|
#include <due_can.h>
|
||||||
|
|
||||||
|
//Leave defined if you use native port, comment if using programming port
|
||||||
|
//This sketch could provide a lot of traffic so it might be best to use the
|
||||||
|
//native port
|
||||||
|
#define Serial SerialUSB
|
||||||
|
|
||||||
|
void printFrame(CAN_FRAME *frame, int filter) {
|
||||||
|
Serial.print("Fltr: ");
|
||||||
|
if (filter > -1) Serial.print(filter);
|
||||||
|
else Serial.print("???");
|
||||||
|
Serial.print(" ID: 0x");
|
||||||
|
Serial.print(frame->id, HEX);
|
||||||
|
Serial.print(" Len: ");
|
||||||
|
Serial.print(frame->length);
|
||||||
|
Serial.print(" Data: 0x");
|
||||||
|
for (int count = 0; count < frame->length; count++) {
|
||||||
|
Serial.print(frame->data.bytes[count], HEX);
|
||||||
|
Serial.print(" ");
|
||||||
|
}
|
||||||
|
Serial.print("\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void gotFrameMB0(CAN_FRAME *frame)
|
||||||
|
{
|
||||||
|
printFrame(frame, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gotFrameMB1(CAN_FRAME *frame)
|
||||||
|
{
|
||||||
|
printFrame(frame, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gotFrameMB3(CAN_FRAME *frame)
|
||||||
|
{
|
||||||
|
printFrame(frame, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gotFrameMB4(CAN_FRAME *frame)
|
||||||
|
{
|
||||||
|
printFrame(frame, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gotFrameMB5(CAN_FRAME *frame)
|
||||||
|
{
|
||||||
|
printFrame(frame, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gotFrame(CAN_FRAME *frame)
|
||||||
|
{
|
||||||
|
printFrame(frame, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
|
||||||
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
// Initialize CAN0, Set the proper baud rates here
|
||||||
|
Can0.init(CAN_BPS_250K);
|
||||||
|
|
||||||
|
//By default there are 7 RX mailboxes for each device
|
||||||
|
//extended
|
||||||
|
//syntax is mailbox, ID, mask, extended
|
||||||
|
Can0.watchForRange(0x10000000, 0x10004000);
|
||||||
|
Can0.watchForRange(0x10050000, 0x100500FF);
|
||||||
|
Can0.setRXFilter(0, 0, true); //catch all mailbox
|
||||||
|
|
||||||
|
//standard
|
||||||
|
Can0.watchForRange(0x400, 0x470);
|
||||||
|
Can0.watchForRange(0x500, 0x5FF);
|
||||||
|
Can0.watchForRange(0x200, 0x220);
|
||||||
|
Can0.setRXFilter(0, 0, false); //catch all mailbox
|
||||||
|
|
||||||
|
//now register all of the callback functions.
|
||||||
|
Can0.attachCANInterrupt(0, gotFrameMB0);
|
||||||
|
Can0.attachCANInterrupt(1, gotFrameMB1);
|
||||||
|
Can0.attachCANInterrupt(3, gotFrameMB3);
|
||||||
|
Can0.attachCANInterrupt(4, gotFrameMB4);
|
||||||
|
Can0.attachCANInterrupt(5, gotFrameMB5);
|
||||||
|
//this function will get a callback for any mailbox that doesn't have a registered callback from above -> 2 and 6
|
||||||
|
Can0.attachCANInterrupt(gotFrame);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop(){ //note the empty loop here. All work is done via callback as frames come in - no need to poll for them
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
// Arduino Due - Displays all traffic found on either canbus port
|
||||||
|
//Modified from the more generic TrafficSniffer sketch to instead use
|
||||||
|
//callback functions to receive the frames. Illustrates how to use
|
||||||
|
//the per-mailbox and general callback functionality
|
||||||
|
// By Thibaut Viard/Wilfredo Molina/Collin Kidder 2013-2014
|
||||||
|
|
||||||
|
// Required libraries
|
||||||
|
#include "variant.h"
|
||||||
|
#include <due_can.h>
|
||||||
|
|
||||||
|
//Leave defined if you use native port, comment if using programming port
|
||||||
|
//This sketch could provide a lot of traffic so it might be best to use the
|
||||||
|
//native port
|
||||||
|
#define Serial SerialUSB
|
||||||
|
|
||||||
|
void printFrame(CAN_FRAME *frame, int filter) {
|
||||||
|
Serial.print("Fltr: ");
|
||||||
|
if (filter > -1) Serial.print(filter);
|
||||||
|
else Serial.print("???");
|
||||||
|
Serial.print(" ID: 0x");
|
||||||
|
Serial.print(frame->id, HEX);
|
||||||
|
Serial.print(" Len: ");
|
||||||
|
Serial.print(frame->length);
|
||||||
|
Serial.print(" Data: 0x");
|
||||||
|
for (int count = 0; count < frame->length; count++) {
|
||||||
|
Serial.print(frame->data.bytes[count], HEX);
|
||||||
|
Serial.print(" ");
|
||||||
|
}
|
||||||
|
Serial.print("\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void gotFrameMB0(CAN_FRAME *frame)
|
||||||
|
{
|
||||||
|
printFrame(frame, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gotFrameMB1(CAN_FRAME *frame)
|
||||||
|
{
|
||||||
|
printFrame(frame, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gotFrameMB3(CAN_FRAME *frame)
|
||||||
|
{
|
||||||
|
printFrame(frame, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gotFrameMB4(CAN_FRAME *frame)
|
||||||
|
{
|
||||||
|
printFrame(frame, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gotFrameMB5(CAN_FRAME *frame)
|
||||||
|
{
|
||||||
|
printFrame(frame, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gotFrame(CAN_FRAME *frame)
|
||||||
|
{
|
||||||
|
printFrame(frame, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
|
||||||
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
// Initialize CAN0, Set the proper baud rates here
|
||||||
|
Can0.begin(CAN_BPS_250K);
|
||||||
|
|
||||||
|
//By default there are 7 RX mailboxes for each device
|
||||||
|
//extended
|
||||||
|
//syntax is mailbox, ID, mask, extended
|
||||||
|
Can0.setRXFilter(0, 0x2FF00, 0x1FF2FF00, true);
|
||||||
|
Can0.setRXFilter(1, 0x1F0000, 0x1F1F0000, true);
|
||||||
|
Can0.setRXFilter(2, 0, 0, true); //catch all mailbox
|
||||||
|
|
||||||
|
//standard
|
||||||
|
Can0.setRXFilter(3, 0x40F, 0x7FF, false);
|
||||||
|
Can0.setRXFilter(4, 0x310, 0x7F0, false);
|
||||||
|
Can0.watchFor(0x200, 0x700); //used in place of above syntax
|
||||||
|
Can0.setRXFilter(0, 0, false); //catch all mailbox - no mailbox ID specified
|
||||||
|
|
||||||
|
//now register all of the callback functions.
|
||||||
|
Can0.setCallback(0, gotFrameMB0);
|
||||||
|
Can0.setCallback(1, gotFrameMB1);
|
||||||
|
Can0.setCallback(3, gotFrameMB3);
|
||||||
|
Can0.setCallback(4, gotFrameMB4);
|
||||||
|
Can0.setCallback(5, gotFrameMB5);
|
||||||
|
//this function will get a callback for any mailbox that doesn't have a registered callback from above -> 2 and 6
|
||||||
|
Can0.setGeneralCallback(gotFrame);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop(){ //note the empty loop here. All work is done via callback as frames come in - no need to poll for them
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
//Reads all traffic on CAN0 and forwards it to CAN1 (and in the reverse direction) but modifies some frames first.
|
||||||
|
// Required libraries
|
||||||
|
#include "variant.h"
|
||||||
|
#include <due_can.h>
|
||||||
|
|
||||||
|
//Leave defined if you use native port, comment if using programming port
|
||||||
|
#define Serial SerialUSB
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
|
||||||
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
// Initialize CAN0 and CAN1, Set the proper baud rates here
|
||||||
|
Can0.begin(CAN_BPS_500K);
|
||||||
|
Can1.begin(CAN_BPS_250K);
|
||||||
|
|
||||||
|
//By default there are 7 mailboxes for each device that are RX boxes
|
||||||
|
//This sets each mailbox to have an open filter that will accept extended
|
||||||
|
//or standard frames
|
||||||
|
int filter;
|
||||||
|
//extended
|
||||||
|
for (filter = 0; filter < 3; filter++) {
|
||||||
|
Can0.setRXFilter(filter, 0, 0, true);
|
||||||
|
Can1.setRXFilter(filter, 0, 0, true);
|
||||||
|
}
|
||||||
|
//standard
|
||||||
|
//for (int filter = 3; filter < 7; filter++) {
|
||||||
|
//Can0.setRXFilter(filter, 0, 0, false);
|
||||||
|
//Can1.setRXFilter(filter, 0, 0, false);
|
||||||
|
//}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void printFrame(CAN_FRAME &frame) {
|
||||||
|
Serial.print("ID: 0x");
|
||||||
|
Serial.print(frame.id, HEX);
|
||||||
|
Serial.print(" Len: ");
|
||||||
|
Serial.print(frame.length);
|
||||||
|
Serial.print(" Data: 0x");
|
||||||
|
for (int count = 0; count < frame.length; count++) {
|
||||||
|
Serial.print(frame.data.bytes[count], HEX);
|
||||||
|
Serial.print(" ");
|
||||||
|
}
|
||||||
|
Serial.print("\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop(){
|
||||||
|
CAN_FRAME incoming;
|
||||||
|
|
||||||
|
if (Can0.available() > 0) {
|
||||||
|
Can0.read(incoming);
|
||||||
|
Can1.sendFrame(incoming);
|
||||||
|
//printFrame(incoming); //uncomment line to print frames that are going out
|
||||||
|
}
|
||||||
|
if (Can1.available() > 0) {
|
||||||
|
Can1.read(incoming);
|
||||||
|
Can0.sendFrame(incoming);
|
||||||
|
//printFrame(incoming);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
// Arduino Due - Displays all traffic found on either canbus port
|
||||||
|
// By Thibaut Viard/Wilfredo Molina/Collin Kidder 2013-2014
|
||||||
|
|
||||||
|
// Required libraries
|
||||||
|
#include "variant.h"
|
||||||
|
#include <due_can.h>
|
||||||
|
|
||||||
|
//Leave defined if you use native port, comment if using programming port
|
||||||
|
//This sketch could provide a lot of traffic so it might be best to use the
|
||||||
|
//native port
|
||||||
|
#define Serial SerialUSB
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
|
||||||
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
// Initialize CAN0 and CAN1, Set the proper baud rates here
|
||||||
|
Can0.begin(CAN_BPS_250K);
|
||||||
|
Can1.begin(CAN_BPS_250K);
|
||||||
|
|
||||||
|
//By default there are 7 mailboxes for each device that are RX boxes
|
||||||
|
//This sets each mailbox to have an open filter that will accept extended
|
||||||
|
//or standard frames
|
||||||
|
int filter;
|
||||||
|
//extended
|
||||||
|
for (filter = 0; filter < 3; filter++) {
|
||||||
|
Can0.setRXFilter(filter, 0, 0, true);
|
||||||
|
Can1.setRXFilter(filter, 0, 0, true);
|
||||||
|
}
|
||||||
|
//standard
|
||||||
|
for (int filter = 3; filter < 7; filter++) {
|
||||||
|
Can0.setRXFilter(filter, 0, 0, false);
|
||||||
|
Can1.setRXFilter(filter, 0, 0, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void printFrame(CAN_FRAME &frame) {
|
||||||
|
Serial.print("ID: 0x");
|
||||||
|
Serial.print(frame.id, HEX);
|
||||||
|
Serial.print(" Len: ");
|
||||||
|
Serial.print(frame.length);
|
||||||
|
Serial.print(" Data: 0x");
|
||||||
|
for (int count = 0; count < frame.length; count++) {
|
||||||
|
Serial.print(frame.data.bytes[count], HEX);
|
||||||
|
Serial.print(" ");
|
||||||
|
}
|
||||||
|
Serial.print("\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop(){
|
||||||
|
CAN_FRAME incoming;
|
||||||
|
|
||||||
|
if (Can0.available() > 0) {
|
||||||
|
Can0.read(incoming);
|
||||||
|
printFrame(incoming);
|
||||||
|
}
|
||||||
|
if (Can1.available() > 0) {
|
||||||
|
Can1.read(incoming);
|
||||||
|
printFrame(incoming);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,195 @@
|
||||||
|
The library has a ton of functions. A lot of them are complicated
|
||||||
|
and really aren't necessary for normal use. This document
|
||||||
|
explains how to use the library simply and will suffice for most
|
||||||
|
applications.
|
||||||
|
|
||||||
|
To start with, you'll need to initialize the canbus hardware. There are two
|
||||||
|
Canbus ports on the Due. There are objects already created
|
||||||
|
for each port: Can0 and Can1. All functions below are called on one
|
||||||
|
of those two objects. Note: The library used to use CAN and CAN2 in place
|
||||||
|
of Can0 and Can1. You can still use those other names as they've been maintained
|
||||||
|
as aliases. Where functions have been added the old functions have been left behind
|
||||||
|
so backward compatibility is maintained. Use whichever functions work best for you.
|
||||||
|
|
||||||
|
init(baudrate) - Initializes the given canbus port with the given baud
|
||||||
|
rate. Sets up for interrupt driven canbus with 7 receive mailboxes
|
||||||
|
and 1 transmit mailbox. You don't need to worry about mailboxes though
|
||||||
|
if you don't want to. Also sets the default enable pin (62 for Can0, 65 for Can1)
|
||||||
|
Example: Can0.init(250000);
|
||||||
|
|
||||||
|
begin(baudrate) - Exactly like init above.
|
||||||
|
|
||||||
|
begin(baudrate, enablepin) - Like above two but with addition of an enable pin. The enable pin
|
||||||
|
will be raised high when the relevant canbus port is enabled and sunk low when the relevant port
|
||||||
|
is disabled. If you do not need an enable pin then pass 255.
|
||||||
|
Example: Can0.begin(250000, 62);
|
||||||
|
|
||||||
|
begin() - Initializes with default settings for both baud and enable (250k baud, enable as above)
|
||||||
|
|
||||||
|
set_baudrate(baudrate) - Set the baud rate of the canbus. This
|
||||||
|
can be set to anything you'd like (within reason) but the common
|
||||||
|
baud rates are 33333, 125000, 250000, 500000, 1000000. Do not
|
||||||
|
use this unless you are changing the baud rate of an already
|
||||||
|
initialized canbus port.
|
||||||
|
Example: Can0.set_baudrate(500000);
|
||||||
|
|
||||||
|
enable() - Enable the canbus port. You don't need to call this unless
|
||||||
|
you've disabled the port at some time in the past.
|
||||||
|
Example: Can0.enable();
|
||||||
|
|
||||||
|
disable() - Disable the canbus port. You will no longer be able to
|
||||||
|
properly use it.
|
||||||
|
Example: Can0.disable();
|
||||||
|
|
||||||
|
Then, it is on to using the newly set-up canbus port:
|
||||||
|
|
||||||
|
This is the structure you will use for both sending and receiving.
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint32_t id; // Can0 be either 11 or 29 bit ID
|
||||||
|
uint32_t fid; // Family ID is a somewhat advanced thing. You Can0 ignore it.
|
||||||
|
uint8_t rtr; // Remote Transmission Request - Don't use this.
|
||||||
|
uint8_t priority; // Priority for TX frames. Probably not that useful normally
|
||||||
|
uint8_t extended;//Set to true for extended frames, false for standard
|
||||||
|
uint8_t length; // Number of data bytes
|
||||||
|
BytesUnion data; // Data bytes
|
||||||
|
} CAN_FRAME;
|
||||||
|
|
||||||
|
In turn, BytesUnion is a way to access the 8 data bytes in a variety of ways with a variety of names:
|
||||||
|
typedef union {
|
||||||
|
uint64_t value;
|
||||||
|
struct {
|
||||||
|
uint32_t low;
|
||||||
|
uint32_t high;
|
||||||
|
};
|
||||||
|
struct {
|
||||||
|
uint16_t s0;
|
||||||
|
uint16_t s1;
|
||||||
|
uint16_t s2;
|
||||||
|
uint16_t s3;
|
||||||
|
};
|
||||||
|
uint8_t bytes[8];
|
||||||
|
uint8_t byte[8]; //alternate name so you can omit the s if you feel it makes more sense
|
||||||
|
} BytesUnion;
|
||||||
|
|
||||||
|
int setRXFilter(id, mask, extended) - Set up a filter for incoming frames.
|
||||||
|
This version of the function allows one to forget about mailboxes and just
|
||||||
|
set a filter. It will handle the details for you and return which mailbox it used
|
||||||
|
in case you need to change it later. It returns -1 if there was a problem.
|
||||||
|
Example: Can0.setRXFilter(0x7E0, 0x7E0, false);
|
||||||
|
|
||||||
|
int setRXFilter(mailbox,id,mask,extended) - The other version of setting a filter.
|
||||||
|
It takes the mailbox to change. So long as you pass a valid mailbox number (0-7)
|
||||||
|
you will get that number back as the return value. It returns -1 on error.
|
||||||
|
Example: Can0.setRXFilter(0, 0x10000, 0x10000, true);
|
||||||
|
|
||||||
|
int watchFor() - An easy way to allow all traffic through. Will automatically add 1 mailbox
|
||||||
|
for standard frames and 1 for extended frames.
|
||||||
|
Example: Can0.watchFor();
|
||||||
|
|
||||||
|
int watchFor(uint32_t id) - Watch for a specific and single ID. Will automatically determine whether to accept
|
||||||
|
extended or standard frames.
|
||||||
|
Example: Can0.watchFor(0x740);
|
||||||
|
|
||||||
|
int watchFor(uint32_t id, uint32_t mask) - Watch for a group of IDs based on ID and a mask. Also uses
|
||||||
|
automatic determination of extended/standard.
|
||||||
|
Example: Can0.watchFor(0x620, 0x7F0); //Watch for a range of ids from 0x620 to 0x62F
|
||||||
|
|
||||||
|
int watchForRange(uint32_t id1, uint32_t id2) - A potentially much easier routine. Pass the lowest and highest
|
||||||
|
IDs you want to accept and it will automatically determine a suitable ID and mask to use. It might accept
|
||||||
|
more IDs than what you passed if necessary.
|
||||||
|
Example: Can0.watchForRange(0x620, 0x64F); //Accept frames with IDs from 0x620 to 0x64F
|
||||||
|
|
||||||
|
int findFreeRXMailbox() - Allows your program to get a free mailbox if you're
|
||||||
|
going to use the above function directly. You shouldn't need to use this very often.
|
||||||
|
Example: mailbox = Can0.findFreeRXMailbox();
|
||||||
|
|
||||||
|
setNumTXBoxes(txboxes) - Above it was mentioned that the default setup is to
|
||||||
|
have 7 RX mailboxes and 1 TX mailbox. This should work for 95% of programs
|
||||||
|
because the underlying library code uses interrupts with large buffers. But, if you
|
||||||
|
will only be sending or only receiving or if you otherwise really need to tweak the
|
||||||
|
arrangement you Can0 with this function. This function totally reinitializes all
|
||||||
|
mailboxes so be sure to call this function before you start setting up your filters.
|
||||||
|
Example: Can0.setNumTXBoxes(2);
|
||||||
|
|
||||||
|
There are two ways to receive canbus frames with this library. You Can0 choose from
|
||||||
|
callback driven reception or buffered frames. Either one is interrupt driven. The
|
||||||
|
choice really comes down to whether you'd like to process frames at a given point
|
||||||
|
in your code or whether you'd like to immediately get a call when a frame comes in.
|
||||||
|
|
||||||
|
Buffered / Polling version:
|
||||||
|
|
||||||
|
bool rx_avail() - The actual frame reception code is interrupt driven so you do not
|
||||||
|
need to rapidly poll for incoming frames at risk of losing some. However, it is still
|
||||||
|
handy to know if one or more frames came in. This function returns true if there
|
||||||
|
are received frames waiting to be processed by your program.
|
||||||
|
Example: if (Can0.rx_avail()) //do something here.
|
||||||
|
|
||||||
|
int available() - Returns the number of waiting frames in the receive buffer. Can be used in place
|
||||||
|
of rx_avail()
|
||||||
|
Example: if (Can0.available() > 0) //do something
|
||||||
|
|
||||||
|
get_rx_buff(CAN_FRAME &) - Read a waiting frame into the variable passed to the function.
|
||||||
|
Example:
|
||||||
|
CAN_FRAME myFrame;
|
||||||
|
if (Can0.rx_avail()) get_rx_buff(myFrame);
|
||||||
|
|
||||||
|
read(CAN_FRAME &) - Exactly like get_rx_buff but with an easier to remember name.
|
||||||
|
Example: Can0.read(myFrame);
|
||||||
|
|
||||||
|
Callback version:
|
||||||
|
|
||||||
|
setCallback(mailbox, cb) - Set a callback function for a mailbox (0-7)
|
||||||
|
Example:
|
||||||
|
void someFunction(Can0_FRAME *frame)
|
||||||
|
{
|
||||||
|
//do something with frame in here
|
||||||
|
}
|
||||||
|
setCallback(3, someFunction); //sets callback for third mailbox
|
||||||
|
|
||||||
|
setGeneralCallback(cb) - Set a callback that will be used for any mailbox that doesn't have a registered callback
|
||||||
|
Example: Can0.setGeneralCallback(someFunction);
|
||||||
|
|
||||||
|
void attachCANInterrupt(void (*cb)(CAN_FRAME *)) - Merely an alternative name for setGeneralCallback
|
||||||
|
|
||||||
|
void attachCANInterrupt(uint8_t mailBox, void (*cb)(CAN_FRAME *)) - An alternative name for setCallback
|
||||||
|
|
||||||
|
void detachCANInterrupt(uint8_t mailBox) - Removes the handler from the given mailbox.
|
||||||
|
Example: Can0.detachCANInterrupt(0);
|
||||||
|
|
||||||
|
These calls will not require any polling at all. You will immediately be given any frames that come into the system.
|
||||||
|
However, care must be taken as your callback function will be in interrupt context. Do not do very much work
|
||||||
|
in the callback function. Any frame that was returned via callback will not be buffered and thus will not be available
|
||||||
|
to the buffered system described previously.
|
||||||
|
|
||||||
|
|
||||||
|
Frame sending:
|
||||||
|
|
||||||
|
bool sendFrame(Can0_FRAME&) - Send a frame over canbus. It will try to send immediately
|
||||||
|
but will automatically fall back to buffering the frame and sending via interrupt
|
||||||
|
when the bus frees up. Returns whether it could send a frame (true/false). Only false if the TX buffer
|
||||||
|
fills up for some reason. In that cases you'll have to send frames at a slower rate or check to be sure
|
||||||
|
that the CAN bus is actually operational.
|
||||||
|
Example:
|
||||||
|
CAN_FRAME myFrame;
|
||||||
|
myFrame.id = 45;
|
||||||
|
myFrame.length = 1
|
||||||
|
myFrame.data[0] = 128;
|
||||||
|
Can0.sendFrame(myFrame);
|
||||||
|
|
||||||
|
There is an alternative output method now. You can set the ID and then use write to write out frames. This will
|
||||||
|
send one frame per call but can be used to output the value of variables up to 8 bytes in size:
|
||||||
|
|
||||||
|
void setWriteID(uint32_t id) - Set the ID to use for the write function.
|
||||||
|
Example: Can0.setWriteID(0x620);
|
||||||
|
|
||||||
|
void setBigEndian(bool) - Set how to output the bytes sent by the write function. The Due is little endian so
|
||||||
|
setting True to this function will cause bytes to be output in reverse order (big endian)
|
||||||
|
Example: Can0.setBigEndian(true);
|
||||||
|
|
||||||
|
template <typename t> void write(t inputValue) - Write the given input bytewise into a frame and send it. Uses
|
||||||
|
the ID from the setWriteID function. Immediately tries to send the frame. This function is probably most useful
|
||||||
|
for simple tests as it does not support sending multiple values in the same frame.
|
||||||
|
Example:
|
||||||
|
int SomeValue = 23423;
|
||||||
|
Can0.write(SomeValue);
|
|
@ -0,0 +1,117 @@
|
||||||
|
###classes, datatypes, C++ keywords
|
||||||
|
CAN_FRAME KEYWORD1
|
||||||
|
CANListener KEYWORD1
|
||||||
|
|
||||||
|
###functions and methods
|
||||||
|
setRXFilter KEYWORD2
|
||||||
|
watchFor KEYWORD2
|
||||||
|
watchForRange KEYWORD2
|
||||||
|
setNumTXBoxes KEYWORD2
|
||||||
|
begin KEYWORD2
|
||||||
|
set_baudrate KEYWORD2
|
||||||
|
init KEYWORD2
|
||||||
|
enable KEYWORD2
|
||||||
|
disable KEYWORD2
|
||||||
|
disable_low_power_mode KEYWORD2
|
||||||
|
enable_low_power_mode KEYWORD2
|
||||||
|
disable_autobaud_listen_mode KEYWORD2
|
||||||
|
enable_autobaud_listen_mode KEYWORD2
|
||||||
|
disable_overload_frame KEYWORD2
|
||||||
|
enable_overload_frame KEYWORD2
|
||||||
|
set_timestamp_capture_point KEYWORD2
|
||||||
|
disable_time_triggered_mode KEYWORD2
|
||||||
|
enable_time_triggered_mode KEYWORD2
|
||||||
|
disable_timer_freeze KEYWORD2
|
||||||
|
enable_timer_freeze KEYWORD2
|
||||||
|
disable_tx_repeat KEYWORD2
|
||||||
|
enable_tx_repeat KEYWORD2
|
||||||
|
set_rx_sync_stage KEYWORD2
|
||||||
|
enable_interrupt KEYWORD2
|
||||||
|
disable_interrupt KEYWORD2
|
||||||
|
get_interrupt_mask KEYWORD2
|
||||||
|
get_status KEYWORD2
|
||||||
|
get_internal_timer_value KEYWORD2
|
||||||
|
get_timestamp_value KEYWORD2
|
||||||
|
get_tx_error_cnt KEYWORD2
|
||||||
|
get_rx_error_cnt KEYWORD2
|
||||||
|
reset_internal_timer KEYWORD2
|
||||||
|
global_send_transfer_cmd KEYWORD2
|
||||||
|
global_send_abort_cmd KEYWORD2
|
||||||
|
mailbox_set_timemark KEYWORD2
|
||||||
|
mailbox_get_status KEYWORD2
|
||||||
|
mailbox_send_transfer_cmd KEYWORD2
|
||||||
|
mailbox_send_abort_cmd KEYWORD2
|
||||||
|
mailbox_init KEYWORD2
|
||||||
|
mailbox_read KEYWORD2
|
||||||
|
mailbox_tx_frame KEYWORD2
|
||||||
|
mailbox_set_id KEYWORD2
|
||||||
|
mailbox_set_priority KEYWORD2
|
||||||
|
mailbox_set_accept_mask KEYWORD2
|
||||||
|
mailbox_set_mode KEYWORD2
|
||||||
|
mailbox_set_databyte KEYWORD2
|
||||||
|
mailbox_set_datalen KEYWORD2
|
||||||
|
mailbox_set_datal KEYWORD2
|
||||||
|
mailbox_set_datah KEYWORD2
|
||||||
|
reset_all_mailbox KEYWORD2
|
||||||
|
rx_avail KEYWORD2
|
||||||
|
get_rx_buff KEYWORD2
|
||||||
|
sendFrame KEYWORD2
|
||||||
|
setWriteID KEYWORD2
|
||||||
|
write KEYWORD2
|
||||||
|
setBigEndian KEYWORD2
|
||||||
|
setCallBack KEYWORD2
|
||||||
|
setGeneralCallback KEYWORD2
|
||||||
|
attachCANInterrupt KEYWORD2
|
||||||
|
detachCANInterrupt KEYWORD2
|
||||||
|
available KEYWORD2
|
||||||
|
read KEYWORD2
|
||||||
|
getBusSpeed KEYWORD2
|
||||||
|
attachObj KEYWORD2
|
||||||
|
detachObj KEYWORD2
|
||||||
|
|
||||||
|
|
||||||
|
CAN KEYWORD3
|
||||||
|
CAN2 KEYWORD3
|
||||||
|
Can0 KEYWORD3
|
||||||
|
Can1 KEYWORD3
|
||||||
|
|
||||||
|
|
||||||
|
###Constants
|
||||||
|
CAN_BPS_1000K LITERAL1
|
||||||
|
CAN_BPS_800K LITERAL1
|
||||||
|
CAN_BPS_500K LITERAL1
|
||||||
|
CAN_BPS_250K LITERAL1
|
||||||
|
CAN_BPS_125K LITERAL1
|
||||||
|
CAN_BPS_50K LITERAL1
|
||||||
|
CAN_BPS_25K LITERAL1
|
||||||
|
CAN_BPS_10K LITERAL1
|
||||||
|
CAN_BPS_5K LITERAL1
|
||||||
|
CAN_MB_DISABLE_MODE LITERAL1
|
||||||
|
CAN_MB_RX_MODE LITERAL1
|
||||||
|
CAN_MB_RX_OVER_WR_MODE LITERAL1
|
||||||
|
CAN_MB_TX_MODE LITERAL1
|
||||||
|
CAN_MB_CONSUMER_MODE LITERAL1
|
||||||
|
CAN_MB_PRODUCER_MODE LITERAL1
|
||||||
|
CAN_TCR_MB0 LITERAL1
|
||||||
|
CAN_TCR_MB1 LITERAL1
|
||||||
|
CAN_TCR_MB2 LITERAL1
|
||||||
|
CAN_TCR_MB3 LITERAL1
|
||||||
|
CAN_TCR_MB4 LITERAL1
|
||||||
|
CAN_TCR_MB5 LITERAL1
|
||||||
|
CAN_TCR_MB6 LITERAL1
|
||||||
|
CAN_TCR_MB7 LITERAL1
|
||||||
|
CAN_MSR_MRDY LITERAL1
|
||||||
|
CAN_IER_MB0 LITERAL1
|
||||||
|
CAN_IER_MB1 LITERAL1
|
||||||
|
CAN_IER_MB2 LITERAL1
|
||||||
|
CAN_IER_MB3 LITERAL1
|
||||||
|
CAN_IER_MB4 LITERAL1
|
||||||
|
CAN_IER_MB5 LITERAL1
|
||||||
|
CAN_IER_MB6 LITERAL1
|
||||||
|
CAN_IER_MB7 LITERAL1
|
||||||
|
CAN_DISABLE_ALL_INTERRUPT_MASK LITERAL1
|
||||||
|
CAN0_IRQn LITERAL1
|
||||||
|
CAN1_IRQn LITERAL1
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
name=due_can
|
||||||
|
version=2.0.1
|
||||||
|
author=Collin Kidder <kidderc@gmail.com>, Thibaut Viard, Wilfredo Molina
|
||||||
|
maintainer=Collin Kidder <kidderc@gmail.com>
|
||||||
|
sentence=Allows for CAN bus communications with the Arduino Due
|
||||||
|
paragraph=Implements interrupt driven communication and supports both object oriented and non-OOP callbacks
|
||||||
|
category=Communication
|
||||||
|
url=https://github.com/collin80/due_can
|
||||||
|
architectures=sam
|
|
@ -0,0 +1,20 @@
|
||||||
|
; PlatformIO Project Configuration File
|
||||||
|
;
|
||||||
|
; Build options: build flags, source filter
|
||||||
|
; Upload options: custom upload port, speed and extra flags
|
||||||
|
; Library options: dependencies, extra library storages
|
||||||
|
; Advanced options: extra scripting
|
||||||
|
;
|
||||||
|
; Please visit documentation for the other options and examples
|
||||||
|
; https://docs.platformio.org/page/projectconf.html
|
||||||
|
|
||||||
|
[env]
|
||||||
|
platform = atmelsam
|
||||||
|
board = due
|
||||||
|
framework = arduino
|
||||||
|
|
||||||
|
[env:combustion]
|
||||||
|
src_filter = +<*> -<18estw.cpp>
|
||||||
|
|
||||||
|
[env:electric]
|
||||||
|
src_filter = +<*> -<18stw.cpp>
|
|
@ -0,0 +1,25 @@
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <DueTimer.h>
|
||||||
|
#include <due_can.h>
|
||||||
|
#include <FT18e_STW_INIT.h>
|
||||||
|
#include <FT_2018e_STW_CAN.h>
|
||||||
|
#include <EDIPTFT.h>
|
||||||
|
#include <FT18e_STW_DISPLAY.h>
|
||||||
|
#include <Bounce2.h>
|
||||||
|
#include <RotaryEncoder.h>
|
||||||
|
|
||||||
|
void setup(){
|
||||||
|
set_pins();
|
||||||
|
//Serial.begin(9600);
|
||||||
|
//Serial.println("Hi");
|
||||||
|
Init_Can_0();
|
||||||
|
init_display();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
//read_buttons(); //in Send_0x110() aufgerufen
|
||||||
|
//read_rotary(); //in Send_0x110() aufgerufen
|
||||||
|
//Send_0x110(); //alle 10 ms als interrupt aufgerufen
|
||||||
|
update_LED();
|
||||||
|
update_display();
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <FT18_STW_INIT.h>
|
||||||
|
#include <DueTimer.h>
|
||||||
|
#include <due_can.h>
|
||||||
|
#include <FT_2018_STW_CAN.h>
|
||||||
|
#include <EDIPTFT.h>
|
||||||
|
#include <FT18_STW_DISPLAY.h>
|
||||||
|
#include <Bounce2.h>
|
||||||
|
#include <RotaryEncoder.h>
|
||||||
|
|
||||||
|
void setup(){
|
||||||
|
set_pins();
|
||||||
|
//Serial.begin(9600);
|
||||||
|
//Serial.println("Hi");
|
||||||
|
Init_Can_0();
|
||||||
|
init_display();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
//read_buttons(); //in Send_0x110() aufgerufen
|
||||||
|
//read_rotary(); //in Send_0x110() aufgerufen
|
||||||
|
//Send_0x110(); //alle 10 ms als interrupt aufgerufen
|
||||||
|
update_LED();
|
||||||
|
update_display();
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
This directory is intended for PlatformIO Unit Testing and project tests.
|
||||||
|
|
||||||
|
Unit Testing is a software testing method by which individual units of
|
||||||
|
source code, sets of one or more MCU program modules together with associated
|
||||||
|
control data, usage procedures, and operating procedures, are tested to
|
||||||
|
determine whether they are fit for use. Unit testing finds problems early
|
||||||
|
in the development cycle.
|
||||||
|
|
||||||
|
More information about PlatformIO Unit Testing:
|
||||||
|
- https://docs.platformio.org/page/plus/unit-testing.html
|
Loading…
Reference in New Issue