Initial commit

This is just the 2018 code configured for PlatformIO
This commit is contained in:
jvblanck 2021-06-09 12:10:12 +02:00
commit 4faddf9248
77 changed files with 10334 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
.pio
.vscode/*
!.vscode/extensions.json

7
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,7 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"platformio.platformio-ide"
]
}

39
include/README Normal file
View File

@ -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

1
lib/Bounce2/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*.db

BIN
lib/Bounce2/Bounce1.zip Normal file

Binary file not shown.

125
lib/Bounce2/Bounce2.cpp Normal file
View File

@ -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);
}

110
lib/Bounce2/Bounce2.h Normal file
View File

@ -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

1
lib/Bounce2/INSTALL.txt Normal file
View File

@ -0,0 +1 @@
Put the "Bounce2" folder in your Arduino or Wiring "libraries" folder.

20
lib/Bounce2/LICENSE Normal file
View File

@ -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.

37
lib/Bounce2/README.md Normal file
View File

@ -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.

View File

@ -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 );
}
}

View File

@ -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 );
}
}

View File

@ -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);
}
}

View File

@ -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

View File

@ -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();
}
}

View File

@ -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");
}
}
}

29
lib/Bounce2/keywords.txt Normal file
View File

@ -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)
#######################################

16
lib/Bounce2/library.json Normal file
View File

@ -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": "*"
}

View File

@ -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=*

308
lib/DueTimer/DueTimer.cpp Normal file
View File

@ -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

109
lib/DueTimer/DueTimer.h Normal file
View File

@ -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

21
lib/DueTimer/LICENSE.txt Normal file
View File

@ -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.

119
lib/DueTimer/README.md Normal file
View File

@ -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).

View File

@ -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

View File

@ -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){
// ...
}
}

View File

@ -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();
}

View File

@ -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...
}
}

20
lib/DueTimer/keywords.txt Normal file
View File

@ -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

12
lib/DueTimer/library.json Normal file
View File

@ -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"
}

View File

@ -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

View File

@ -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);
}
}
}

View File

@ -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

View File

@ -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);
}*/
}

View File

@ -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

View File

@ -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);
}
}
}

View File

@ -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

View File

@ -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);
}*/
}

View File

@ -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

View File

@ -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);
}*/
}

View File

@ -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);

View File

@ -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);
}*/
}

View File

@ -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);

46
lib/README Normal file
View File

@ -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

View File

@ -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;
}
}

View File

@ -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;
};

View File

@ -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);
}

View File

@ -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.

1
lib/arduino-ediptft-master/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
doc/

View File

@ -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

View File

@ -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));
}

View File

@ -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

View File

@ -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.

View File

@ -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!

View File

@ -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

View File

@ -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

9
lib/due_can/README.md Normal file
View File

@ -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.

1387
lib/due_can/due_can.cpp Normal file

File diff suppressed because it is too large Load Diff

314
lib/due_can/due_can.h Normal file
View File

@ -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_

View File

@ -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) {
}
}

View File

@ -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()
{
}

View File

@ -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();
}
}

View File

@ -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");
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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);
}
}

View File

@ -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);
}
}

195
lib/due_can/howtouse.txt Normal file
View File

@ -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);

117
lib/due_can/keywords.txt Normal file
View File

@ -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

View File

@ -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

20
platformio.ini Normal file
View File

@ -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>

25
src/18estw.cpp Normal file
View File

@ -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();
}

25
src/18stw.cpp Normal file
View File

@ -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();
}

11
test/README Normal file
View File

@ -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