Drivers + Threads
This commit is contained in:
115
workspace/TS100/Core/Drivers/Buttons.cpp
Normal file
115
workspace/TS100/Core/Drivers/Buttons.cpp
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Buttons.c
|
||||
*
|
||||
* Created on: 29 May 2020
|
||||
* Author: Ralim
|
||||
*/
|
||||
#include <Buttons.hpp>
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "gui.hpp"
|
||||
uint32_t lastButtonTime = 0;
|
||||
|
||||
ButtonState getButtonState() {
|
||||
/*
|
||||
* Read in the buttons and then determine if a state change needs to occur
|
||||
*/
|
||||
|
||||
/*
|
||||
* If the previous state was 00 Then we want to latch the new state if
|
||||
* different & update time
|
||||
* If the previous state was !00 Then we want to search if we trigger long
|
||||
* press (buttons still down), or if release we trigger press
|
||||
* (downtime>filter)
|
||||
*/
|
||||
static uint8_t previousState = 0;
|
||||
static uint32_t previousStateChange = 0;
|
||||
const uint16_t timeout = 40;
|
||||
uint8_t currentState;
|
||||
currentState = (getButtonA()) << 0;
|
||||
currentState |= (getButtonB()) << 1;
|
||||
|
||||
if (currentState)
|
||||
lastButtonTime = xTaskGetTickCount();
|
||||
if (currentState == previousState) {
|
||||
if (currentState == 0)
|
||||
return BUTTON_NONE;
|
||||
if ((xTaskGetTickCount() - previousStateChange) > timeout) {
|
||||
// User has been holding the button down
|
||||
// We want to send a button is held message
|
||||
if (currentState == 0x01)
|
||||
return BUTTON_F_LONG;
|
||||
else if (currentState == 0x02)
|
||||
return BUTTON_B_LONG;
|
||||
else
|
||||
return BUTTON_NONE; // Both being held case, we dont long hold this
|
||||
} else
|
||||
return BUTTON_NONE;
|
||||
} else {
|
||||
// A change in button state has occurred
|
||||
ButtonState retVal = BUTTON_NONE;
|
||||
if (currentState) {
|
||||
// User has pressed a button down (nothing done on down)
|
||||
if (currentState != previousState) {
|
||||
// There has been a change in the button states
|
||||
// If there is a rising edge on one of the buttons from double press we
|
||||
// want to mask that out As users are having issues with not release
|
||||
// both at once
|
||||
if (previousState == 0x03)
|
||||
currentState = 0x03;
|
||||
}
|
||||
} else {
|
||||
// User has released buttons
|
||||
// If they previously had the buttons down we want to check if they were <
|
||||
// long hold and trigger a press
|
||||
if ((xTaskGetTickCount() - previousStateChange) < timeout) {
|
||||
// The user didn't hold the button for long
|
||||
// So we send button press
|
||||
|
||||
if (previousState == 0x01)
|
||||
retVal = BUTTON_F_SHORT;
|
||||
else if (previousState == 0x02)
|
||||
retVal = BUTTON_B_SHORT;
|
||||
else
|
||||
retVal = BUTTON_BOTH; // Both being held case
|
||||
}
|
||||
}
|
||||
previousState = currentState;
|
||||
previousStateChange = xTaskGetTickCount();
|
||||
return retVal;
|
||||
}
|
||||
return BUTTON_NONE;
|
||||
}
|
||||
|
||||
void waitForButtonPress() {
|
||||
// we are just lazy and sleep until user confirms button press
|
||||
// This also eats the button press event!
|
||||
ButtonState buttons = getButtonState();
|
||||
while (buttons) {
|
||||
buttons = getButtonState();
|
||||
GUIDelay();
|
||||
}
|
||||
while (!buttons) {
|
||||
buttons = getButtonState();
|
||||
GUIDelay();
|
||||
}
|
||||
}
|
||||
|
||||
void waitForButtonPressOrTimeout(uint32_t timeout) {
|
||||
timeout += xTaskGetTickCount();
|
||||
// calculate the exit point
|
||||
|
||||
ButtonState buttons = getButtonState();
|
||||
while (buttons) {
|
||||
buttons = getButtonState();
|
||||
GUIDelay();
|
||||
if (xTaskGetTickCount() > timeout)
|
||||
return;
|
||||
}
|
||||
while (!buttons) {
|
||||
buttons = getButtonState();
|
||||
GUIDelay();
|
||||
if (xTaskGetTickCount() > timeout)
|
||||
return;
|
||||
}
|
||||
}
|
||||
35
workspace/TS100/Core/Drivers/Buttons.hpp
Normal file
35
workspace/TS100/Core/Drivers/Buttons.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Buttons.h
|
||||
*
|
||||
* Created on: 29 May 2020
|
||||
* Author: Ralim
|
||||
*/
|
||||
#include "BSP.h"
|
||||
#ifndef INC_BUTTONS_H_
|
||||
#define INC_BUTTONS_H_
|
||||
|
||||
extern uint32_t lastButtonTime;
|
||||
|
||||
enum ButtonState {
|
||||
BUTTON_NONE = 0, /* No buttons pressed / < filter time*/
|
||||
BUTTON_F_SHORT = 1, /* User has pressed the front button*/
|
||||
BUTTON_B_SHORT = 2, /* User has pressed the back button*/
|
||||
BUTTON_F_LONG = 4, /* User is holding the front button*/
|
||||
BUTTON_B_LONG = 8, /* User is holding the back button*/
|
||||
BUTTON_BOTH = 16, /* User has pressed both buttons*/
|
||||
|
||||
/*
|
||||
* Note:
|
||||
* Pressed means press + release, we trigger on a full \__/ pulse
|
||||
* holding means it has gone low, and been low for longer than filter time
|
||||
*/
|
||||
};
|
||||
|
||||
//Returns what buttons are pressed (if any)
|
||||
ButtonState getButtonState();
|
||||
//Helpers
|
||||
void waitForButtonPressOrTimeout(uint32_t timeout);
|
||||
void waitForButtonPress();
|
||||
|
||||
|
||||
#endif /* INC_BUTTONS_H_ */
|
||||
192
workspace/TS100/Core/Drivers/Font.h
Normal file
192
workspace/TS100/Core/Drivers/Font.h
Normal file
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Font.h
|
||||
*
|
||||
* Created on: 17 Sep 2016
|
||||
* Author: Ralim
|
||||
*
|
||||
* ... This file contains the font...
|
||||
*/
|
||||
|
||||
#ifndef FONT_H_
|
||||
#define FONT_H_
|
||||
#include "Translation.h"
|
||||
|
||||
#define FONT_12_WIDTH 12
|
||||
// FONTS ARE NO LONGER HERE, MOVED TO PYTHON AUTO GEN
|
||||
|
||||
|
||||
const uint8_t ExtraFontChars[] = {
|
||||
//width = 12
|
||||
//height = 16
|
||||
0x00,0x18,0x24,0x24,0x18,0xC0,0x40,0x40,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x02,0x02,0x02,0x00,0x00,0x00, // Degrees F
|
||||
0x00,0x18,0x24,0x24,0x18,0x80,0x40,0x20,0x20,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x08,0x10,0x10,0x10,0x00,0x00, // Degrees C
|
||||
0x00,0x00,0x20,0x30,0x38,0xFC,0xFE,0xFC,0x38,0x30,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x7F,0x7F,0x00,0x00,0x00,0x00, // UP arrow
|
||||
|
||||
0x00,0xF0,0x08,0x0E,0x02,0x02,0x02,0x02,0x0E,0x08,0xF0,0x00,0x00,0x3F,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x3F,0x00, // Battery Empty
|
||||
0x00,0xF0,0x08,0x0E,0x02,0x02,0x02,0x02,0x0E,0x08,0xF0,0x00,0x00,0x3F,0x40,0x50,0x50,0x50,0x50,0x50,0x50,0x40,0x3F,0x00, // Battery 1*/
|
||||
0x00,0xF0,0x08,0x0E,0x02,0x02,0x02,0x02,0x0E,0x08,0xF0,0x00,0x00,0x3F,0x40,0x58,0x58,0x58,0x58,0x58,0x58,0x40,0x3F,0x00, // Battery 2*/
|
||||
0x00,0xF0,0x08,0x0E,0x02,0x02,0x02,0x02,0x0E,0x08,0xF0,0x00,0x00,0x3F,0x40,0x5C,0x5C,0x5C,0x5C,0x5C,0x5C,0x40,0x3F,0x00, // Battery 3*/
|
||||
0x00,0xF0,0x08,0x0E,0x02,0x02,0x02,0x02,0x0E,0x08,0xF0,0x00,0x00,0x3F,0x40,0x5E,0x5E,0x5E,0x5E,0x5E,0x5E,0x40,0x3F,0x00, // Battery 4*/
|
||||
0x00,0xF0,0x08,0x0E,0x02,0x02,0x02,0x02,0x0E,0x08,0xF0,0x00,0x00,0x3F,0x40,0x5F,0x5F,0x5F,0x5F,0x5F,0x5F,0x40,0x3F,0x00, // Battery 5*/
|
||||
0x00,0xF0,0x08,0x8E,0x82,0x82,0x82,0x82,0x8E,0x08,0xF0,0x00,0x00,0x3F,0x40,0x5F,0x5F,0x5F,0x5F,0x5F,0x5F,0x40,0x3F,0x00, // Battery 6*/
|
||||
0x00,0xF0,0x08,0xCE,0xC2,0xC2,0xC2,0xC2,0xCE,0x08,0xF0,0x00,0x00,0x3F,0x40,0x5F,0x5F,0x5F,0x5F,0x5F,0x5F,0x40,0x3F,0x00, // Battery 7*/
|
||||
0x00,0xF0,0x08,0xEE,0xE2,0xE2,0xE2,0xE2,0xEE,0x08,0xF0,0x00,0x00,0x3F,0x40,0x5F,0x5F,0x5F,0x5F,0x5F,0x5F,0x40,0x3F,0x00, // Battery 8*/
|
||||
0x00,0xF0,0x08,0xEE,0xE2,0xF2,0xF2,0xE2,0xEE,0x08,0xF0,0x00,0x00,0x3F,0x40,0x5F,0x5F,0x5F,0x5F,0x5F,0x5F,0x40,0x3F,0x00, // Battery 9*/
|
||||
0x00,0xF0,0x08,0xEE,0xE2,0xFA,0xFA,0xE2,0xEE,0x08,0xF0,0x00,0x00,0x3F,0x40,0x5F,0x5F,0x5F,0x5F,0x5F,0x5F,0x40,0x3F,0x00, // Battery 10*/
|
||||
|
||||
0x00,0x00,0x38,0xC4,0x00,0x38,0xC4,0x00,0x38,0xC4,0x00,0x00,0x00,0x38,0x3A,0x39,0x38,0x3A,0x39,0x38,0x3A,0x39,0x10,0x10, // heating
|
||||
0x00,0x60,0xE0,0xFE,0xE0,0xE0,0xE0,0xE0,0xFE,0xE0,0x60,0x00,0x00,0x00,0x00,0x01,0x03,0xFF,0xFF,0x03,0x01,0x00,0x00,0x00, // AC
|
||||
|
||||
0xFC,0x02,0x02,0x02,0x02,0x02,0x02,0x82,0x62,0x1A,0x02,0xFC,0x3F,0x40,0x42,0x46,0x4C,0x58,0x46,0x41,0x40,0x40,0x40,0x3F, // ☑ (check box on, menu true)
|
||||
0xFC,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0xFC,0x3F,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x3F, // ☐ (check box off, menu false)
|
||||
|
||||
/*
|
||||
0x00,0x00,0x00,0x80,0x80,0xFE,0xFF,0x83,0x87,0x06,0x00,0x00,0x00,0x00,0x30,0x70,0x60,0x7F,0x3F,0x00,0x00,0x00,0x00,0x00, // Function?
|
||||
0x00,0x70,0xFA,0xDB,0xDB,0xDB,0xDB,0xDB,0xDB,0xFF,0xFE,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x00,0x00, // a_
|
||||
0x00,0x3C,0x7E,0xE7,0xC3,0xC3,0xC3,0xC3,0xE7,0x7E,0x3C,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x00,0x00, // 0_
|
||||
0x55,0x00,0xAA,0x00,0x55,0x00,0xAA,0x00,0x55,0x00,0xAA,0x00,0x55,0x00,0xAA,0x00,0x55,0x00,0xAA,0x00,0x55,0x00,0xAA,0x00, // 25% block
|
||||
0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55, // 50% pipe
|
||||
0xAA,0xFF,0x55,0xFF,0xAA,0xFF,0x55,0xFF,0xAA,0xFF,0x55,0xFF,0xAA,0xFF,0x55,0xFF,0xAA,0xFF,0x55,0xFF,0xAA,0xFF,0x55,0xFF, // 75% block
|
||||
0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00, // | pipe
|
||||
0x80,0x80,0x80,0x80,0x80,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00, // T pipe ,|
|
||||
0xC0,0xC0,0xFF,0xFF,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x06,0x06,0xFE,0xFE,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00, // ,| double pipe
|
||||
0x00,0x00,0xFF,0xFF,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00, // || double pipe
|
||||
0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x06,0x06,0xFE,0xFE,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00, // #NAME?//#NAME?
|
||||
0xC0,0xC0,0xFF,0xFF,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x06,0x07,0x07,0x00,0x00,0x00,0x00,0x00, // ,^ double pupe
|
||||
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00, // #NAME?//#NAME?
|
||||
0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01, // ,> pipe
|
||||
0x80,0x80,0x80,0x80,0x80,0xFF,0xFF,0x80,0x80,0x80,0x80,0x80,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, // _|_ pipe
|
||||
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x01,0x01,0x01,0x01,0x01,0xFF,0xFF,0x01,0x01,0x01,0x01,0x01, // ,|, pipe
|
||||
0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x01,0x01,0x01,0x01,0x01, // |, pipe
|
||||
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, // #NAME?//#NAME?
|
||||
0x80,0x80,0x80,0x80,0x80,0xFF,0xFF,0x80,0x80,0x80,0x80,0x80,0x01,0x01,0x01,0x01,0x01,0xFF,0xFF,0x01,0x01,0x01,0x01,0x01, // #NAME?//#NAME?
|
||||
0x00,0x00,0xFF,0xFF,0x00,0xFF,0xFF,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x07,0x07,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06, // ,> double pipe
|
||||
0x00,0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0xFF,0xFF,0x00,0xFE,0xFE,0x06,0x06,0x06,0x06,0x06, // ^, double pipe
|
||||
0xC0,0xC0,0xFF,0xFF,0x00,0xFF,0xFF,0xC0,0xC0,0xC0,0xC0,0xC0,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06, // _|_ double pipe
|
||||
0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x06,0x06,0xFE,0xFE,0x00,0xFE,0xFE,0x06,0x06,0x06,0x06,0x06, // ,|, double pipe
|
||||
0x00,0x00,0xFF,0xFF,0x00,0xFF,0xFF,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0xFF,0xFF,0x00,0xFE,0xFE,0x06,0x06,0x06,0x06,0x06, // |, double pipe
|
||||
0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06, // == double pipe
|
||||
0xC0,0xC0,0xFF,0xFF,0x00,0xFF,0xFF,0xC0,0xC0,0xC0,0xC0,0xC0,0x06,0x06,0xFE,0xFE,0x00,0xFE,0xFE,0x06,0x06,0x06,0x06,0x06, // #NAME?//#NAME?
|
||||
0x00,0x00,0x00,0x78,0xFC,0xCC,0x8C,0x0C,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x3E,0x33,0x33,0x3F,0x1E,0x00,0x00,0x00, // Delta lowercase
|
||||
0x00,0x00,0x00,0x00,0x00,0x7E,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 27 (')
|
||||
0x80,0x80,0x80,0x80,0x80,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00, // ,^ pipe
|
||||
0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x01,0x01,0x01,0x01,0x01, // | , pipe
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // solid block
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // half block bottom
|
||||
0x00,0x00,0x00,0x00,0x00,0xBF,0xBF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x3F,0x00,0x00,0x00,0x00,0x00, // 7C (|)
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // top half solid block
|
||||
0x00,0x00,0x0C,0xFC,0xFC,0x6C,0x60,0x60,0xE0,0xC0,0x00,0x00,0x00,0x00,0x30,0x3F,0x3F,0x36,0x06,0x06,0x07,0x03,0x00,0x00, // DE small
|
||||
0x00,0x00,0x03,0xFF,0xFF,0x1B,0x18,0x18,0xF8,0xF0,0x00,0x00,0x00,0x00,0x30,0x3F,0x3F,0x36,0x06,0x06,0x07,0x03,0x00,0x00, // DE large
|
||||
0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ? (,)
|
||||
0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x06,0x06,0x00,0x00,0x00, // =
|
||||
0x00,0x00,0x00,0x40,0x80,0x80,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // sideways comma
|
||||
0x00,0x00,0x80,0xC0,0x80,0x00,0x00,0x80,0xC0,0x80,0x00,0x00,0x00,0x00,0x01,0x03,0x01,0x00,0x00,0x01,0x03,0x01,0x00,0x00, // ..
|
||||
0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x01,0x00,0x00,0x00,0x00, // .
|
||||
0x00,0x00,0x02,0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // tiny 1
|
||||
0x00,0x00,0x00,0x00,0xF0,0xF0,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00, // small block
|
||||
*/
|
||||
};
|
||||
|
||||
const uint8_t FontSymbols[] = {
|
||||
0x00,0x00,0x00,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x0F,0x07,0x03,0x01,0x00,0x00,0x00,0x00, // Right block
|
||||
0x00,0x00,0x00,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x07,0x0F,0x1F,0x00,0x00,0x00, // left block
|
||||
0x00,0x00,0x00,0x10,0x18,0x1C,0xFE,0x1C,0x18,0x10,0x00,0x00,0x00,0x00,0x00,0x04,0x0C,0x1C,0x3F,0x1C,0x0C,0x04,0x00,0x00, // UD arrow
|
||||
0x00,0x00,0x00,0xFE,0xFE,0x00,0x00,0xFE,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x37,0x37,0x00,0x00,0x37,0x37,0x00,0x00,0x00, // !!
|
||||
0x00,0x38,0x7C,0xC6,0x82,0xFE,0xFE,0x02,0xFE,0xFE,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x3F,0x00,0x3F,0x3F,0x00,0x00, // paragraph
|
||||
0x00,0x00,0xDC,0xFE,0x22,0x22,0x22,0x22,0xE6,0xC4,0x00,0x00,0x00,0x00,0x08,0x19,0x11,0x11,0x11,0x11,0x1F,0x0E,0x00,0x00, // section
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x00, // cursor
|
||||
0x00,0x00,0x00,0x08,0x0C,0x0E,0xFF,0x0E,0x0C,0x08,0x00,0x00,0x00,0x00,0x00,0x44,0x4C,0x5C,0x7F,0x5C,0x4C,0x44,0x00,0x00, // UD arrow
|
||||
0x00,0x00,0x00,0x10,0x18,0x1C,0xFE,0x1C,0x18,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,0x00, // UP arrow
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x0C,0x1C,0x3F,0x1C,0x0C,0x04,0x00,0x00, // Down arrow
|
||||
0x00,0x00,0x80,0x80,0x80,0x80,0x80,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x03,0x01,0x00,0x00, // right arrow
|
||||
0x00,0x00,0x80,0xC0,0xE0,0xF0,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x00,0x01,0x03,0x07,0x00,0x00,0x00,0x00,0x00,0x00, // left arrow
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,
|
||||
0x00,0x80,0xC0,0xE0,0xF0,0x80,0x80,0x80,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x01,0x03,0x07,0x00,0x00,0x00,0x07,0x03,0x01,0x00, // LR arrow
|
||||
0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x04,0x06,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x06,0x04, // UP block
|
||||
0x00,0x20,0x60,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0x60,0x20,0x00,0x00,0x00,0x00,0x01,0x03,0x07,0x03,0x01,0x00,0x00,0x00 // Down block
|
||||
};
|
||||
|
||||
const uint8_t WarningBlock24[] = {
|
||||
//width = 24
|
||||
//height = 16
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x30,0x0C,0x02,0xF1,0xF1,0xF1,0x02,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0xC0,0xB0,0x8C,0x83,0x80,0x80,0x80,0x80,0xB3,0xB3,0xB3,0x80,0x80,0x80,0x80,0x83,0x8C,0xB0,0xC0,0x00,0x00
|
||||
};
|
||||
|
||||
const uint8_t idleScreenBG[] = {
|
||||
//width = 84
|
||||
//height = 16
|
||||
0x00,0xE0,0x18,0x04,0x02,0x02,0x01,0x41,0x61,0x61,0x61,0xE1,0xC1,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,
|
||||
0x81,0x81,0x81,0x81,0xC1,0xE1,0x61,0x61,0x61,0x41,0x01,0x01,0x02,0x02,0x04,0x18,0xE0,0x00,0x00,0xE0,0x18,0x04,0x02,0x02,
|
||||
0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
|
||||
0x99,0x65,0x01,0x01,0x81,0x41,0x01,0x02,0x02,0x04,0x18,0xE0,
|
||||
0x00,0x07,0x18,0x20,0x40,0x40,0x80,0x82,0x86,0x86,0x86,0x87,0x83,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,
|
||||
0x81,0x81,0x81,0x81,0x83,0x87,0x86,0x86,0x86,0x82,0x80,0x80,0x40,0x40,0x20,0x18,0x07,0x00,0x00,0x07,0x18,0x20,0x40,0x40,
|
||||
0x80,0x82,0x87,0x85,0x85,0x85,0x85,0x87,0x87,0x85,0x87,0x85,0x87,0x87,0x82,0x82,0x82,0x80,0x82,0x80,0x82,0x82,0x82,0x92,
|
||||
0x8A,0x84,0x82,0x81,0x80,0x80,0x80,0x40,0x40,0x20,0x18,0x07
|
||||
};
|
||||
|
||||
const uint8_t idleScreenBGF[] = {
|
||||
//width = 84
|
||||
//height = 16
|
||||
0xE0,0x18,0x04,0x02,0x02,0x01,0x41,0x81,0x01,0x01,0x65,0x99,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
|
||||
0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02,0x02,0x04,0x18,0xE0,0x00,0x00,0xE0,0x18,0x04,0x02,0x02,
|
||||
0x01,0x01,0x41,0x61,0x61,0x61,0xE1,0xC1,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xC1,
|
||||
0xE1,0x61,0x61,0x61,0x41,0x01,0x02,0x02,0x04,0x18,0xE0,0x00,
|
||||
0x07,0x18,0x20,0x40,0x40,0x80,0x80,0x80,0x81,0x82,0x84,0x8A,0x92,0x82,0x82,0x82,0x80,0x82,0x80,0x82,0x82,0x82,0x87,0x87,
|
||||
0x85,0x87,0x85,0x87,0x87,0x85,0x85,0x85,0x85,0x87,0x82,0x80,0x40,0x40,0x20,0x18,0x07,0x00,0x00,0x07,0x18,0x20,0x40,0x40,
|
||||
0x80,0x80,0x82,0x86,0x86,0x86,0x87,0x83,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x83,
|
||||
0x87,0x86,0x86,0x86,0x82,0x80,0x40,0x40,0x20,0x18,0x07,0x00
|
||||
};
|
||||
|
||||
/*
|
||||
* 16x16 icons
|
||||
* */
|
||||
const uint8_t SettingsMenuIcons[] = {
|
||||
|
||||
// Soldering
|
||||
//width = 16
|
||||
//height = 16
|
||||
0x00, 0x02, 0x04, 0x08, 0x12, 0x24, 0xC4, 0x42, 0x82, 0x04,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01, 0x02, 0x07, 0x0A, 0x14, 0x28, 0x50,
|
||||
0x60, 0x00,
|
||||
|
||||
|
||||
|
||||
//Sleep
|
||||
//width = 16
|
||||
//height = 16
|
||||
0x00, 0xC6, 0xE6, 0xF6, 0xBE, 0x9E, 0x8E, 0x86, 0x00, 0x00,
|
||||
0x40, 0x40, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x01, 0x01, 0x01,
|
||||
0x45, 0x65, 0x75, 0x5D, 0x4C, 0x00, 0x06, 0x07, 0x07, 0x05,
|
||||
0x04, 0x00,
|
||||
|
||||
|
||||
|
||||
//Menu
|
||||
//width = 16
|
||||
//height = 16
|
||||
0x00,0x80,0x06,0x86,0x46,0x06,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x00,
|
||||
0x00,0x00,0x61,0x60,0x00,0x00,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x00,
|
||||
|
||||
//Wrench
|
||||
///width = 16
|
||||
//height = 16
|
||||
0x00, 0x18, 0x30, 0x32, 0x7E, 0x7C, 0xF0, 0xC0, 0x80, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01, 0x03, 0x0F, 0x3E, 0x7E, 0x4C, 0x0C,
|
||||
0x18, 0x00,
|
||||
#ifdef NOTUSED
|
||||
//Calibration (Not used, kept for future menu layouts)
|
||||
//width = 16
|
||||
//height = 16
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE8, 0x70,
|
||||
0x7A, 0x5E, 0x8E, 0x1C, 0x30, 0x00, 0x00, 0x10, 0x38, 0x1C,
|
||||
0x0E, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
#endif /* FONT_H_ */
|
||||
52
workspace/TS100/Core/Drivers/LIS2DH12.cpp
Normal file
52
workspace/TS100/Core/Drivers/LIS2DH12.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* LIS2DH12.cpp
|
||||
*
|
||||
* Created on: 27Feb.,2018
|
||||
* Author: Ralim
|
||||
*/
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "LIS2DH12.hpp"
|
||||
#include "cmsis_os.h"
|
||||
|
||||
typedef struct {
|
||||
const uint8_t reg;
|
||||
const uint8_t value;
|
||||
} LIS_REG;
|
||||
|
||||
static const LIS_REG i2c_registers[] = { { LIS_CTRL_REG1, 0x17 }, // 25Hz
|
||||
{ LIS_CTRL_REG2, 0b00001000 }, // Highpass filter off
|
||||
{ LIS_CTRL_REG3, 0b01100000 }, // Setup interrupt pins
|
||||
{ LIS_CTRL_REG4, 0b00001000 }, // Block update mode off, HR on
|
||||
{ LIS_CTRL_REG5, 0b00000010 }, { LIS_CTRL_REG6, 0b01100010 },
|
||||
//Basically setup the unit to run, and enable 4D orientation detection
|
||||
{ LIS_INT2_CFG, 0b01111110 }, //setup for movement detection
|
||||
{ LIS_INT2_THS, 0x28 }, { LIS_INT2_DURATION, 64 }, {
|
||||
LIS_INT1_CFG, 0b01111110 }, { LIS_INT1_THS, 0x28 }, {
|
||||
LIS_INT1_DURATION, 64 } };
|
||||
|
||||
void LIS2DH12::initalize() {
|
||||
for (size_t index = 0;
|
||||
index < (sizeof(i2c_registers) / sizeof(i2c_registers[0]));
|
||||
index++) {
|
||||
FRToSI2C::I2C_RegisterWrite(LIS2DH_I2C_ADDRESS,
|
||||
i2c_registers[index].reg, i2c_registers[index].value);
|
||||
}
|
||||
}
|
||||
|
||||
void LIS2DH12::getAxisReadings(int16_t &x, int16_t &y, int16_t &z) {
|
||||
std::array<int16_t, 3> sensorData;
|
||||
|
||||
FRToSI2C::Mem_Read(LIS2DH_I2C_ADDRESS, 0xA8, I2C_MEMADD_SIZE_8BIT,
|
||||
reinterpret_cast<uint8_t*>(sensorData.begin()),
|
||||
sensorData.size() * sizeof(int16_t));
|
||||
|
||||
x = sensorData[0];
|
||||
y = sensorData[1];
|
||||
z = sensorData[2];
|
||||
}
|
||||
|
||||
bool LIS2DH12::detect() {
|
||||
return FRToSI2C::probe(LIS2DH_I2C_ADDRESS);
|
||||
}
|
||||
43
workspace/TS100/Core/Drivers/LIS2DH12.hpp
Normal file
43
workspace/TS100/Core/Drivers/LIS2DH12.hpp
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* LIS2DH12.hpp
|
||||
*
|
||||
* Created on: 27Feb.,2018
|
||||
* Author: Ralim
|
||||
*/
|
||||
|
||||
#ifndef LIS2DH12_HPP_
|
||||
#define LIS2DH12_HPP_
|
||||
#include "stm32f1xx_hal.h"
|
||||
#include "FRToSI2C.hpp"
|
||||
#include "LIS2DH12_defines.hpp"
|
||||
#include "BSP.h"
|
||||
|
||||
class LIS2DH12 {
|
||||
public:
|
||||
static bool detect();
|
||||
static void initalize();
|
||||
//1 = rh, 2,=lh, 8=flat
|
||||
static Orientation getOrientation() {
|
||||
#ifdef LIS_ORI_FLIP
|
||||
uint8_t val = (FRToSI2C::I2C_RegisterRead(LIS2DH_I2C_ADDRESS,
|
||||
LIS_INT2_SRC) >> 2);
|
||||
if (val == 8)
|
||||
val = 3;
|
||||
else if (val == 1)
|
||||
val = 1;
|
||||
else if (val == 2)
|
||||
val = 0;
|
||||
else
|
||||
val = 3;
|
||||
return static_cast<Orientation>(val);
|
||||
#endif
|
||||
#ifdef MODEL_TS100
|
||||
return static_cast<Orientation>((FRToSI2C::I2C_RegisterRead(LIS2DH_I2C_ADDRESS,LIS_INT2_SRC) >> 2) - 1);
|
||||
#endif
|
||||
}
|
||||
static void getAxisReadings(int16_t& x, int16_t& y, int16_t& z);
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif /* LIS2DH12_HPP_ */
|
||||
28
workspace/TS100/Core/Drivers/LIS2DH12_defines.hpp
Normal file
28
workspace/TS100/Core/Drivers/LIS2DH12_defines.hpp
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* LIS2DH12_defines.hpp
|
||||
*
|
||||
* Created on: 27Feb.,2018
|
||||
* Author: Ralim
|
||||
*/
|
||||
|
||||
#ifndef LIS2DH12_DEFINES_HPP_
|
||||
#define LIS2DH12_DEFINES_HPP_
|
||||
|
||||
|
||||
#define LIS2DH_I2C_ADDRESS (25<<1)
|
||||
|
||||
#define LIS_CTRL_REG1 0x20|0x80
|
||||
#define LIS_CTRL_REG2 0x21|0x80
|
||||
#define LIS_CTRL_REG3 0x22|0x80
|
||||
#define LIS_CTRL_REG4 0x23|0x80
|
||||
#define LIS_CTRL_REG5 0x24|0x80
|
||||
#define LIS_CTRL_REG6 0x25|0x80
|
||||
#define LIS_INT1_CFG 0xB0|0x80
|
||||
#define LIS_INT2_CFG 0xB4|0x80
|
||||
#define LIS_INT1_DURATION 0x33|0x80
|
||||
#define LIS_INT1_THS 0x32|0x80
|
||||
#define LIS_INT1_SRC 0x31|0x80
|
||||
#define LIS_INT2_DURATION 0x37|0x80
|
||||
#define LIS_INT2_THS 0x36|0x80
|
||||
#define LIS_INT2_SRC 0x35|0x80
|
||||
#endif /* LIS2DH12_DEFINES_HPP_ */
|
||||
88
workspace/TS100/Core/Drivers/MMA8652FC.cpp
Normal file
88
workspace/TS100/Core/Drivers/MMA8652FC.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* MMA8652FC.cpp
|
||||
*
|
||||
* Created on: 31Aug.,2017
|
||||
* Author: Ben V. Brown
|
||||
*/
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "MMA8652FC.hpp"
|
||||
#include "cmsis_os.h"
|
||||
|
||||
typedef struct {
|
||||
const uint8_t reg;
|
||||
const uint8_t val;
|
||||
} MMA_REG;
|
||||
|
||||
static const MMA_REG i2c_registers[] = { { CTRL_REG2, 0 }, //Normal mode
|
||||
{ CTRL_REG2, 0x40 }, // Reset all registers to POR values
|
||||
{ FF_MT_CFG_REG, 0x78 }, // Enable motion detection for X, Y, Z axis, latch disabled
|
||||
{ PL_CFG_REG, 0x40 }, //Enable the orientation detection
|
||||
{ PL_COUNT_REG, 200 }, //200 count debounce
|
||||
{ PL_BF_ZCOMP_REG, 0b01000111 }, //Set the threshold to 42 degrees
|
||||
{ P_L_THS_REG, 0b10011100 }, //Up the trip angles
|
||||
{ CTRL_REG4, 0x01 | (1 << 4) }, // Enable dataready interrupt & orientation interrupt
|
||||
{ CTRL_REG5, 0x01 }, // Route data ready interrupts to INT1 ->PB5 ->EXTI5, leaving orientation routed to INT2
|
||||
{ CTRL_REG2, 0x12 }, //Set maximum resolution oversampling
|
||||
{ XYZ_DATA_CFG_REG, (1 << 4) }, //select high pass filtered data
|
||||
{ HP_FILTER_CUTOFF_REG, 0x03 }, //select high pass filtered data
|
||||
{ CTRL_REG1, 0x19 } // ODR=12 Hz, Active mode
|
||||
};
|
||||
|
||||
void MMA8652FC::initalize() {
|
||||
size_t index = 0;
|
||||
|
||||
//send all the init commands to the unit
|
||||
|
||||
FRToSI2C::I2C_RegisterWrite(MMA8652FC_I2C_ADDRESS, i2c_registers[index].reg,
|
||||
i2c_registers[index].val);
|
||||
index++;
|
||||
FRToSI2C::I2C_RegisterWrite(MMA8652FC_I2C_ADDRESS, i2c_registers[index].reg,
|
||||
i2c_registers[index].val);
|
||||
index++;
|
||||
|
||||
HAL_Delay(2); // ~1ms delay
|
||||
|
||||
while (index < (sizeof(i2c_registers) / sizeof(i2c_registers[0]))) {
|
||||
FRToSI2C::I2C_RegisterWrite(MMA8652FC_I2C_ADDRESS,
|
||||
i2c_registers[index].reg, i2c_registers[index].val);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
Orientation MMA8652FC::getOrientation() {
|
||||
//First read the PL_STATUS register
|
||||
uint8_t plStatus = FRToSI2C::I2C_RegisterRead(MMA8652FC_I2C_ADDRESS,
|
||||
PL_STATUS_REG);
|
||||
if ((plStatus & 0b10000000) == 0b10000000) {
|
||||
plStatus >>= 1; //We don't need the up/down bit
|
||||
plStatus &= 0x03; //mask to the two lower bits
|
||||
|
||||
//0 == left handed
|
||||
//1 == right handed
|
||||
|
||||
return static_cast<Orientation>(plStatus);
|
||||
}
|
||||
|
||||
return ORIENTATION_FLAT;
|
||||
}
|
||||
|
||||
void MMA8652FC::getAxisReadings(int16_t &x, int16_t &y, int16_t &z) {
|
||||
std::array<int16_t, 3> sensorData;
|
||||
|
||||
FRToSI2C::Mem_Read(MMA8652FC_I2C_ADDRESS, OUT_X_MSB_REG,
|
||||
I2C_MEMADD_SIZE_8BIT, reinterpret_cast<uint8_t*>(sensorData.begin()),
|
||||
sensorData.size() * sizeof(int16_t));
|
||||
|
||||
x = static_cast<int16_t>(__builtin_bswap16(
|
||||
*reinterpret_cast<uint16_t*>(&sensorData[0])));
|
||||
y = static_cast<int16_t>(__builtin_bswap16(
|
||||
*reinterpret_cast<uint16_t*>(&sensorData[1])));
|
||||
z = static_cast<int16_t>(__builtin_bswap16(
|
||||
*reinterpret_cast<uint16_t*>(&sensorData[2])));
|
||||
}
|
||||
|
||||
bool MMA8652FC::detect() {
|
||||
return FRToSI2C::probe(MMA8652FC_I2C_ADDRESS);
|
||||
}
|
||||
28
workspace/TS100/Core/Drivers/MMA8652FC.hpp
Normal file
28
workspace/TS100/Core/Drivers/MMA8652FC.hpp
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* MMA8652FC.h
|
||||
*
|
||||
* Created on: 31Aug.,2017
|
||||
* Author: Ben V. Brown
|
||||
*/
|
||||
|
||||
#ifndef MMA8652FC_HPP_
|
||||
#define MMA8652FC_HPP_
|
||||
#include "stm32f1xx_hal.h"
|
||||
#include "MMA8652FC_defines.h"
|
||||
#include "FRToSI2C.hpp"
|
||||
#include "BSP.h"
|
||||
|
||||
class MMA8652FC {
|
||||
|
||||
public:
|
||||
//Returns true if this accelerometer is detected
|
||||
static bool detect();
|
||||
//Init any internal state
|
||||
static void initalize();
|
||||
static Orientation getOrientation(); // Reads the I2C register and returns the orientation (true == left)
|
||||
static void getAxisReadings(int16_t &x, int16_t &y, int16_t &z);
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif /* MMA8652FC_HPP_ */
|
||||
124
workspace/TS100/Core/Drivers/MMA8652FC_defines.h
Normal file
124
workspace/TS100/Core/Drivers/MMA8652FC_defines.h
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* MMA8652FC_defines.h
|
||||
*
|
||||
* Created on: 31Aug.,2017
|
||||
* Author: Ben V. Brown
|
||||
*/
|
||||
|
||||
#ifndef MMA8652FC_DEFINES_H_
|
||||
#define MMA8652FC_DEFINES_H_
|
||||
|
||||
//--------------MMA8652 Registers-------------------------------------------//
|
||||
|
||||
#define STATUS_REG 0x00 // STATUS Register
|
||||
|
||||
#define OUT_X_MSB_REG 0x01 // [7:0] are 8 MSBs of the 14-bit X-axis sample
|
||||
#define OUT_X_LSB_REG 0x02 // [7:2] are the 6 LSB of 14-bit X-axis sample
|
||||
#define OUT_Y_MSB_REG 0x03 // [7:0] are 8 MSBs of the 14-bit Y-axis sample
|
||||
#define OUT_Y_LSB_REG 0x04 // [7:2] are the 6 LSB of 14-bit Y-axis sample
|
||||
#define OUT_Z_MSB_REG 0x05 // [7:0] are 8 MSBs of the 14-bit Z-axis sample
|
||||
#define OUT_Z_LSB_REG 0x06 // [7:2] are the 6 LSB of 14-bit Z-axis sample
|
||||
|
||||
#define F_SETUP_REG 0x09 // F_SETUP FIFO Setup Register
|
||||
#define TRIG_CFG_REG 0x0A // TRIG_CFG Map of FIFO data capture events
|
||||
#define SYSMOD_REG 0x0B // SYSMOD System Mode Register
|
||||
#define INT_SOURCE_REG 0x0C // INT_SOURCE System Interrupt Status Register
|
||||
#define WHO_AM_I_REG 0x0D // WHO_AM_I Device ID Register
|
||||
#define XYZ_DATA_CFG_REG 0x0E // XYZ_DATA_CFG Sensor Data Configuration Register
|
||||
#define HP_FILTER_CUTOFF_REG 0x0F // HP_FILTER_CUTOFF High Pass Filter Register
|
||||
|
||||
#define PL_STATUS_REG 0x10 // PL_STATUS Portrait/Landscape Status Register
|
||||
#define PL_CFG_REG 0x11 // PL_CFG Portrait/Landscape Configuration Register
|
||||
#define PL_COUNT_REG 0x12 // PL_COUNT Portrait/Landscape Debounce Register
|
||||
#define PL_BF_ZCOMP_REG 0x13 // PL_BF_ZCOMP Back/Front and Z Compensation Register
|
||||
#define P_L_THS_REG 0x14 // P_L_THS Portrait to Landscape Threshold Register
|
||||
|
||||
#define FF_MT_CFG_REG 0x15 // FF_MT_CFG Freefall and Motion Configuration Register
|
||||
#define FF_MT_SRC_REG 0x16 // FF_MT_SRC Freefall and Motion Source Register
|
||||
#define FF_MT_THS_REG 0x17 // FF_MT_THS Freefall and Motion Threshold Register
|
||||
#define FF_MT_COUNT_REG 0x18 // FF_MT_COUNT Freefall Motion Count Register
|
||||
|
||||
#define TRANSIENT_CFG_REG 0x1D // TRANSIENT_CFG Transient Configuration Register
|
||||
#define TRANSIENT_SRC_REG 0x1E // TRANSIENT_SRC Transient Source Register
|
||||
#define TRANSIENT_THS_REG 0x1F // TRANSIENT_THS Transient Threshold Register
|
||||
#define TRANSIENT_COUNT_REG 0x20 // TRANSIENT_COUNT Transient Debounce Counter Register
|
||||
|
||||
#define PULSE_CFG_REG 0x21 // PULSE_CFG Pulse Configuration Register
|
||||
#define PULSE_SRC_REG 0x22 // PULSE_SRC Pulse Source Register
|
||||
#define PULSE_THSX_REG 0x23 // PULSE_THS XYZ Pulse Threshold Registers
|
||||
#define PULSE_THSY_REG 0x24
|
||||
#define PULSE_THSZ_REG 0x25
|
||||
#define PULSE_TMLT_REG 0x26 // PULSE_TMLT Pulse Time Window Register
|
||||
#define PULSE_LTCY_REG 0x27 // PULSE_LTCY Pulse Latency Timer Register
|
||||
#define PULSE_WIND_REG 0x28 // PULSE_WIND Second Pulse Time Window Register
|
||||
|
||||
#define ASLP_COUNT_REG 0x29 // ASLP_COUNT Auto Sleep Inactivity Timer Register
|
||||
|
||||
#define CTRL_REG1 0x2A // CTRL_REG1 System Control 1 Register
|
||||
#define CTRL_REG2 0x2B // CTRL_REG2 System Control 2 Register
|
||||
#define CTRL_REG3 0x2C // CTRL_REG3 Interrupt Control Register
|
||||
#define CTRL_REG4 0x2D // CTRL_REG4 Interrupt Enable Register
|
||||
#define CTRL_REG5 0x2E // CTRL_REG5 Interrupt Configuration Register
|
||||
|
||||
#define OFF_X_REG 0x2F // XYZ Offset Correction Registers
|
||||
#define OFF_Y_REG 0x30
|
||||
#define OFF_Z_REG 0x31
|
||||
|
||||
//MMA8652FC 7-bit I2C address
|
||||
|
||||
#define MMA8652FC_I2C_ADDRESS (0x1D<<1)
|
||||
|
||||
//MMA8652FC Sensitivity
|
||||
|
||||
#define SENSITIVITY_2G 1024
|
||||
#define SENSITIVITY_4G 512
|
||||
#define SENSITIVITY_8G 256
|
||||
|
||||
#define STATUS_REG 0x00
|
||||
#define X_MSB_REG 0X01
|
||||
#define X_LSB_REG 0X02
|
||||
#define Y_MSB_REG 0X03
|
||||
#define Y_LSB_REG 0X04
|
||||
#define Z_MSB_REG 0X05
|
||||
#define Z_LSB_REG 0X06
|
||||
|
||||
#define TRIG_CFG 0X0A
|
||||
#define SYSMOD 0X0B
|
||||
#define INT_SOURCE 0X0C
|
||||
#define DEVICE_ID 0X0D
|
||||
|
||||
//-----STATUS_REG(0X00)-----Bit Define----------------------------------------//
|
||||
#define ZYXDR_BIT 0X08
|
||||
//----XYZ_DATA_CFG_REG(0xE)-Bit Define----------------------------------------//
|
||||
#define FS_MASK 0x03
|
||||
#define FULL_SCALE_2G 0x00 //2g=0x0,4g=0x1,8g=0x2
|
||||
#define FULL_SCALE_4G 0x01
|
||||
#define FULL_SCALE_8G 0x02
|
||||
//---------CTRL_REG1(0X2A)Bit Define------------------------------------------//
|
||||
#define ACTIVE_MASK 1<<0 //bit0
|
||||
#define DR_MASK 0x38 //bit D5,D4,D3
|
||||
#define FHZ800 0x0 //800hz
|
||||
#define FHZ400 0x1 //400hz
|
||||
#define FHZ200 0x2 //200hz
|
||||
#define FHZ100 0x3 //100hz
|
||||
#define FHZ50 0x4 //50hz
|
||||
#define FHZ2 0x5 //12.5hz
|
||||
#define FHZ1 0x6 //6.25hz
|
||||
#define FHZ0 0x7 //1.563hz
|
||||
|
||||
//---------CTRL_REG2(0X2B)Bit Define------------------------------------------//
|
||||
#define MODS_MASK 0x03 //Oversampling Mode 4
|
||||
#define Normal_Mode 0x0 //Normal=0,Low Noise Low Power MODS=1,
|
||||
//HI RESOLUTION=2,LOW POWER MODS = 11
|
||||
//----CTRL_REG4---Interrupt Enable BIT ---------------------------------------//
|
||||
//0 interrupt is disabled (default)
|
||||
//1 interrupt is enabled
|
||||
#define INT_EN_ASLP 1<<7 //Auto-SLEEP/WAKE Interrupt Enable
|
||||
#define INT_EN_FIFO 1<<6 //FIFO Interrupt Enable
|
||||
#define INT_EN_TRANS 1<<5 //Transient Interrupt Enable
|
||||
#define INT_EN_LNDPRT 1<<4 //Orientation(Landscape/Portrait)Interrupt Enable
|
||||
#define INT_EN_PULSE 1<<3 //Pulse Detection Interrupt Enable
|
||||
#define INT_EN_FF_MT 1<<2 //Freefall/Motion Interrupt Enable
|
||||
#define INT_EN_DRDY 1<<0 //Data Ready Interrupt Enable
|
||||
|
||||
#endif /* MMA8652FC_DEFINES_H_ */
|
||||
486
workspace/TS100/Core/Drivers/OLED.cpp
Normal file
486
workspace/TS100/Core/Drivers/OLED.cpp
Normal file
@@ -0,0 +1,486 @@
|
||||
/*
|
||||
* OLED.cpp
|
||||
*
|
||||
* Created on: 29Aug.,2017
|
||||
* Author: Ben V. Brown
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <OLED.hpp>
|
||||
#include <stdlib.h>
|
||||
#include "Translation.h"
|
||||
#include "cmsis_os.h"
|
||||
#include "../../configuration.h"
|
||||
|
||||
const uint8_t *OLED::currentFont; // Pointer to the current font used for
|
||||
// rendering to the buffer
|
||||
uint8_t *OLED::firstStripPtr; // Pointers to the strips to allow for buffer
|
||||
// having extra content
|
||||
uint8_t *OLED::secondStripPtr; // Pointers to the strips
|
||||
bool OLED::inLeftHandedMode; // Whether the screen is in left or not (used for
|
||||
// offsets in GRAM)
|
||||
OLED::DisplayState OLED::displayState;
|
||||
uint8_t OLED::fontWidth, OLED::fontHeight;
|
||||
int16_t OLED::cursor_x, OLED::cursor_y;
|
||||
uint8_t OLED::displayOffset;
|
||||
uint8_t OLED::screenBuffer[16 + (OLED_WIDTH * 2) + 10]; // The data buffer
|
||||
uint8_t OLED::secondFrameBuffer[OLED_WIDTH * 2];
|
||||
|
||||
/*Setup params for the OLED screen*/
|
||||
/*http://www.displayfuture.com/Display/datasheet/controller/SSD1307.pdf*/
|
||||
/*All commands are prefixed with 0x80*/
|
||||
/*Data packets are prefixed with 0x40*/
|
||||
uint8_t OLED_Setup_Array[] = {
|
||||
/**/
|
||||
0x80, 0xAE, /*Display off*/
|
||||
0x80, 0xD5, /*Set display clock divide ratio / osc freq*/
|
||||
0x80, 0x52, /*Divide ratios*/
|
||||
0x80, 0xA8, /*Set Multiplex Ratio*/
|
||||
0x80, 0x0F, /*16 == max brightness,39==dimmest*/
|
||||
0x80, 0xC0, /*Set COM Scan direction*/
|
||||
0x80, 0xD3, /*Set vertical Display offset*/
|
||||
0x80, 0x00, /*0 Offset*/
|
||||
0x80, 0x40, /*Set Display start line to 0*/
|
||||
0x80, 0xA0, /*Set Segment remap to normal*/
|
||||
0x80, 0x8D, /*Charge Pump*/
|
||||
0x80, 0x14, /*Charge Pump settings*/
|
||||
0x80, 0xDA, /*Set VCOM Pins hardware config*/
|
||||
0x80, 0x02, /*Combination 2*/
|
||||
0x80, 0x81, /*Contrast*/
|
||||
0x80, 0x33, /*^51*/
|
||||
0x80, 0xD9, /*Set pre-charge period*/
|
||||
0x80, 0xF1, /*Pre charge period*/
|
||||
0x80, 0xDB, /*Adjust VCOMH regulator ouput*/
|
||||
0x80, 0x30, /*VCOM level*/
|
||||
0x80, 0xA4, /*Enable the display GDDR*/
|
||||
0x80, 0XA6, /*Normal display*/
|
||||
0x80, 0x20, /*Memory Mode*/
|
||||
0x80, 0x00, /*Wrap memory*/
|
||||
0x80, 0xAF /*Display on*/
|
||||
};
|
||||
// Setup based on the SSD1307 and modified for the SSD1306
|
||||
|
||||
const uint8_t REFRESH_COMMANDS[17] = { 0x80, 0xAF, 0x80, 0x21, 0x80, 0x20, 0x80,
|
||||
0x7F, 0x80, 0xC0, 0x80, 0x22, 0x80, 0x00, 0x80, 0x01, 0x40 };
|
||||
|
||||
|
||||
/*
|
||||
* Animation timing function that follows a bezier curve.
|
||||
* @param t A given percentage value [0..<100]
|
||||
* Returns a new percentage value with ease in and ease out.
|
||||
* Original floating point formula: t * t * (3.0f - 2.0f * t);
|
||||
*/
|
||||
static uint8_t easeInOutTiming(uint8_t t) {
|
||||
return t * t * (300 - 2 * t) / 10000;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the value between a and b, using a percentage value t.
|
||||
* @param a The value associated with 0%
|
||||
* @param b The value associated with 100%
|
||||
* @param t The percentage [0..<100]
|
||||
*/
|
||||
static uint8_t lerp(uint8_t a, uint8_t b, uint8_t t) {
|
||||
return a + t * (b - a) / 100;
|
||||
}
|
||||
|
||||
void OLED::initialize() {
|
||||
cursor_x = cursor_y = 0;
|
||||
currentFont = USER_FONT_12;
|
||||
fontWidth = 12;
|
||||
inLeftHandedMode = false;
|
||||
firstStripPtr = &screenBuffer[FRAMEBUFFER_START];
|
||||
secondStripPtr = &screenBuffer[FRAMEBUFFER_START + OLED_WIDTH];
|
||||
fontHeight = 16;
|
||||
displayOffset = 0;
|
||||
memcpy(&screenBuffer[0], &REFRESH_COMMANDS[0], sizeof(REFRESH_COMMANDS));
|
||||
|
||||
// Set the display to be ON once the settings block is sent and send the
|
||||
// initialisation data to the OLED.
|
||||
|
||||
setDisplayState(DisplayState::ON);
|
||||
FRToSI2C::Transmit(DEVICEADDR_OLED, &OLED_Setup_Array[0],
|
||||
sizeof(OLED_Setup_Array));
|
||||
}
|
||||
|
||||
void OLED::setFramebuffer(uint8_t *buffer) {
|
||||
if (buffer == NULL) {
|
||||
firstStripPtr = &screenBuffer[FRAMEBUFFER_START];
|
||||
secondStripPtr = &screenBuffer[FRAMEBUFFER_START + OLED_WIDTH];
|
||||
return;
|
||||
}
|
||||
|
||||
firstStripPtr = &buffer[0];
|
||||
secondStripPtr = &buffer[OLED_WIDTH];
|
||||
}
|
||||
|
||||
/*
|
||||
* Prints a char to the screen.
|
||||
* UTF font handling is done using the two input chars.
|
||||
* Precursor is the command char that is used to select the table.
|
||||
*/
|
||||
void OLED::drawChar(char c) {
|
||||
if (c == '\x01' && cursor_y == 0) { // 0x01 is used as new line char
|
||||
cursor_x = 0;
|
||||
cursor_y = 8;
|
||||
return;
|
||||
} else if (c == 0) {
|
||||
return;
|
||||
}
|
||||
uint16_t index = c - 2; //First index is \x02
|
||||
uint8_t *charPointer;
|
||||
charPointer = ((uint8_t*) currentFont)
|
||||
+ ((fontWidth * (fontHeight / 8)) * index);
|
||||
drawArea(cursor_x, cursor_y, fontWidth, fontHeight, charPointer);
|
||||
cursor_x += fontWidth;
|
||||
}
|
||||
|
||||
/*
|
||||
* Draws a one pixel wide scrolling indicator. y is the upper vertical position
|
||||
* of the indicator in pixels (0..<16).
|
||||
*/
|
||||
void OLED::drawScrollIndicator(uint8_t y, uint8_t height) {
|
||||
union u_type {
|
||||
uint16_t whole;
|
||||
uint8_t strips[2];
|
||||
} column;
|
||||
|
||||
column.whole = (1 << height) - 1;
|
||||
column.whole <<= y;
|
||||
|
||||
// Draw a one pixel wide bar to the left with a single pixel as
|
||||
// the scroll indicator.
|
||||
fillArea(OLED_WIDTH - 1, 0, 1, 8, column.strips[0]);
|
||||
fillArea(OLED_WIDTH - 1, 8, 1, 8, column.strips[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Plays a transition animation between two framebuffers.
|
||||
* @param forwardNavigation Direction of the navigation animation.
|
||||
*
|
||||
* If forward is true, this displays a forward navigation to the second framebuffer contents.
|
||||
* Otherwise a rewinding navigation animation is shown to the second framebuffer contents.
|
||||
*/
|
||||
void OLED::transitionSecondaryFramebuffer(bool forwardNavigation) {
|
||||
uint8_t *firstBackStripPtr = &secondFrameBuffer[0];
|
||||
uint8_t *secondBackStripPtr = &secondFrameBuffer[OLED_WIDTH];
|
||||
|
||||
uint32_t totalDuration = 50; // 500ms
|
||||
uint32_t duration = 0;
|
||||
uint32_t start = xTaskGetTickCount();
|
||||
uint8_t offset = 0;
|
||||
|
||||
while (duration <= totalDuration) {
|
||||
duration = xTaskGetTickCount() - start;
|
||||
uint8_t progress = duration * 100 / totalDuration;
|
||||
progress = easeInOutTiming(progress);
|
||||
progress = lerp(0, OLED_WIDTH, progress);
|
||||
if (progress > OLED_WIDTH) {
|
||||
progress = OLED_WIDTH;
|
||||
}
|
||||
|
||||
// When forward, current contents move to the left out.
|
||||
// Otherwise the contents move to the right out.
|
||||
uint8_t oldStart = forwardNavigation ? 0 : progress;
|
||||
uint8_t oldPrevious = forwardNavigation ? progress - offset : offset;
|
||||
|
||||
// Content from the second framebuffer moves in from the right (forward)
|
||||
// or from the left (not forward).
|
||||
uint8_t newStart = forwardNavigation ? OLED_WIDTH - progress : 0;
|
||||
uint8_t newEnd = forwardNavigation ? 0 : OLED_WIDTH - progress;
|
||||
|
||||
offset = progress;
|
||||
|
||||
memmove(&firstStripPtr[oldStart], &firstStripPtr[oldPrevious], OLED_WIDTH - progress);
|
||||
memmove(&secondStripPtr[oldStart], &secondStripPtr[oldPrevious], OLED_WIDTH - progress);
|
||||
|
||||
memmove(&firstStripPtr[newStart], &firstBackStripPtr[newEnd], progress);
|
||||
memmove(&secondStripPtr[newStart], &secondBackStripPtr[newEnd], progress);
|
||||
|
||||
refresh();
|
||||
osDelay(40);
|
||||
}
|
||||
}
|
||||
|
||||
void OLED::useSecondaryFramebuffer(bool useSecondary) {
|
||||
if (useSecondary) {
|
||||
setFramebuffer(secondFrameBuffer);
|
||||
} else {
|
||||
setFramebuffer(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void OLED::setRotation(bool leftHanded) {
|
||||
#ifdef MODEL_TS80
|
||||
leftHanded = !leftHanded;
|
||||
#endif
|
||||
if (inLeftHandedMode == leftHanded) {
|
||||
return;
|
||||
}
|
||||
|
||||
// send command struct again with changes
|
||||
if (leftHanded) {
|
||||
OLED_Setup_Array[11] = 0xC8; // c1?
|
||||
OLED_Setup_Array[19] = 0xA1;
|
||||
} else {
|
||||
OLED_Setup_Array[11] = 0xC0;
|
||||
OLED_Setup_Array[19] = 0xA0;
|
||||
}
|
||||
FRToSI2C::Transmit(DEVICEADDR_OLED, (uint8_t*) OLED_Setup_Array,
|
||||
sizeof(OLED_Setup_Array));
|
||||
inLeftHandedMode = leftHanded;
|
||||
|
||||
screenBuffer[5] = inLeftHandedMode ? 0 : 32; // display is shifted by 32 in left handed
|
||||
// mode as driver ram is 128 wide
|
||||
screenBuffer[7] = inLeftHandedMode ? 95 : 0x7F; // End address of the ram segment we are writing to (96 wide)
|
||||
screenBuffer[9] = inLeftHandedMode ? 0xC8 : 0xC0;
|
||||
}
|
||||
|
||||
// print a string to the current cursor location
|
||||
void OLED::print(const char *str) {
|
||||
while (str[0]) {
|
||||
drawChar(str[0]);
|
||||
str++;
|
||||
}
|
||||
}
|
||||
|
||||
void OLED::setFont(uint8_t fontNumber) {
|
||||
if (fontNumber == 1) {
|
||||
// small font
|
||||
currentFont = USER_FONT_6x8;
|
||||
fontHeight = 8;
|
||||
fontWidth = 6;
|
||||
} else if (fontNumber == 2) {
|
||||
currentFont = ExtraFontChars;
|
||||
fontHeight = 16;
|
||||
fontWidth = 12;
|
||||
} else {
|
||||
currentFont = USER_FONT_12;
|
||||
fontHeight = 16;
|
||||
fontWidth = 12;
|
||||
}
|
||||
}
|
||||
uint8_t OLED::getFont() {
|
||||
if (currentFont == USER_FONT_6x8)
|
||||
return 1;
|
||||
else if (currentFont == ExtraFontChars)
|
||||
return 2;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
inline void stripLeaderZeros(char *buffer, uint8_t places) {
|
||||
//Removing the leading zero's by swapping them to SymbolSpace
|
||||
// Stop 1 short so that we dont blank entire number if its zero
|
||||
for (int i = 0; i < (places-1); i++) {
|
||||
if (buffer[i] == 2) {
|
||||
buffer[i] = SymbolSpace[0];
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// maximum places is 5
|
||||
void OLED::printNumber(uint16_t number, uint8_t places, bool noLeaderZeros) {
|
||||
char buffer[7] = { 0 };
|
||||
|
||||
if (places >= 5) {
|
||||
buffer[5] = 2 + number % 10;
|
||||
number /= 10;
|
||||
}
|
||||
if (places > 4) {
|
||||
buffer[4] = 2 + number % 10;
|
||||
number /= 10;
|
||||
}
|
||||
|
||||
if (places > 3) {
|
||||
buffer[3] = 2 + number % 10;
|
||||
number /= 10;
|
||||
}
|
||||
|
||||
if (places > 2) {
|
||||
buffer[2] = 2 + number % 10;
|
||||
number /= 10;
|
||||
}
|
||||
|
||||
if (places > 1) {
|
||||
buffer[1] = 2 + number % 10;
|
||||
number /= 10;
|
||||
}
|
||||
|
||||
buffer[0] = 2 + number % 10;
|
||||
if (noLeaderZeros)
|
||||
stripLeaderZeros(buffer, places);
|
||||
print(buffer);
|
||||
}
|
||||
|
||||
void OLED::debugNumber(int32_t val) {
|
||||
if (abs(val) > 99999) {
|
||||
OLED::print(SymbolSpace); // out of bounds
|
||||
return;
|
||||
}
|
||||
if (val >= 0) {
|
||||
OLED::print(SymbolSpace);
|
||||
OLED::printNumber(val, 5);
|
||||
} else {
|
||||
OLED::print(SymbolMinus);
|
||||
OLED::printNumber(-val, 5);
|
||||
}
|
||||
}
|
||||
|
||||
void OLED::drawSymbol(uint8_t symbolID) {
|
||||
// draw a symbol to the current cursor location
|
||||
setFont(2);
|
||||
drawChar(symbolID + 2);
|
||||
setFont(0);
|
||||
}
|
||||
|
||||
// Draw an area, but y must be aligned on 0/8 offset
|
||||
void OLED::drawArea(int16_t x, int8_t y, uint8_t wide, uint8_t height,
|
||||
const uint8_t *ptr) {
|
||||
// Splat this from x->x+wide in two strides
|
||||
if (x <= -wide)
|
||||
return; // cutoffleft
|
||||
if (x > 96)
|
||||
return; // cutoff right
|
||||
|
||||
uint8_t visibleStart = 0;
|
||||
uint8_t visibleEnd = wide;
|
||||
|
||||
// trimming to draw partials
|
||||
if (x < 0) {
|
||||
visibleStart -= x; // subtract negative value == add absolute value
|
||||
}
|
||||
if (x + wide > 96) {
|
||||
visibleEnd = 96 - x;
|
||||
}
|
||||
|
||||
if (y == 0) {
|
||||
// Splat first line of data
|
||||
for (uint8_t xx = visibleStart; xx < visibleEnd; xx++) {
|
||||
firstStripPtr[xx + x] = ptr[xx];
|
||||
}
|
||||
}
|
||||
if (y == 8 || height == 16) {
|
||||
// Splat the second line
|
||||
for (uint8_t xx = visibleStart; xx < visibleEnd; xx++) {
|
||||
secondStripPtr[x + xx] = ptr[xx + (height == 16 ? wide : 0)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw an area, but y must be aligned on 0/8 offset
|
||||
// For data which has octets swapped in a 16-bit word.
|
||||
void OLED::drawAreaSwapped(int16_t x, int8_t y, uint8_t wide, uint8_t height,
|
||||
const uint8_t *ptr) {
|
||||
// Splat this from x->x+wide in two strides
|
||||
if (x <= -wide)
|
||||
return; // cutoffleft
|
||||
if (x > 96)
|
||||
return; // cutoff right
|
||||
|
||||
uint8_t visibleStart = 0;
|
||||
uint8_t visibleEnd = wide;
|
||||
|
||||
// trimming to draw partials
|
||||
if (x < 0) {
|
||||
visibleStart -= x; // subtract negative value == add absolute value
|
||||
}
|
||||
if (x + wide > 96) {
|
||||
visibleEnd = 96 - x;
|
||||
}
|
||||
|
||||
if (y == 0) {
|
||||
// Splat first line of data
|
||||
for (uint8_t xx = visibleStart; xx < visibleEnd; xx += 2) {
|
||||
firstStripPtr[xx + x] = ptr[xx + 1];
|
||||
firstStripPtr[xx + x + 1] = ptr[xx];
|
||||
}
|
||||
}
|
||||
if (y == 8 || height == 16) {
|
||||
// Splat the second line
|
||||
for (uint8_t xx = visibleStart; xx < visibleEnd; xx += 2) {
|
||||
secondStripPtr[x + xx] = ptr[xx + 1 + (height == 16 ? wide : 0)];
|
||||
secondStripPtr[x + xx + 1] = ptr[xx + (height == 16 ? wide : 0)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OLED::fillArea(int16_t x, int8_t y, uint8_t wide, uint8_t height,
|
||||
const uint8_t value) {
|
||||
// Splat this from x->x+wide in two strides
|
||||
if (x <= -wide)
|
||||
return; // cutoffleft
|
||||
if (x > 96)
|
||||
return; // cutoff right
|
||||
|
||||
uint8_t visibleStart = 0;
|
||||
uint8_t visibleEnd = wide;
|
||||
|
||||
// trimming to draw partials
|
||||
if (x < 0) {
|
||||
visibleStart -= x; // subtract negative value == add absolute value
|
||||
}
|
||||
if (x + wide > 96) {
|
||||
visibleEnd = 96 - x;
|
||||
}
|
||||
|
||||
if (y == 0) {
|
||||
// Splat first line of data
|
||||
for (uint8_t xx = visibleStart; xx < visibleEnd; xx++) {
|
||||
firstStripPtr[xx + x] = value;
|
||||
}
|
||||
}
|
||||
if (y == 8 || height == 16) {
|
||||
// Splat the second line
|
||||
for (uint8_t xx = visibleStart; xx < visibleEnd; xx++) {
|
||||
secondStripPtr[x + xx] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OLED::drawFilledRect(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1,
|
||||
bool clear) {
|
||||
// Draw this in 3 sections
|
||||
// This is basically a N wide version of vertical line
|
||||
|
||||
// Step 1 : Draw in the top few pixels that are not /8 aligned
|
||||
// LSB is at the top of the screen
|
||||
uint8_t mask = 0xFF;
|
||||
if (y0) {
|
||||
mask = mask << (y0 % 8);
|
||||
for (uint8_t col = x0; col < x1; col++)
|
||||
if (clear)
|
||||
firstStripPtr[(y0 / 8) * 96 + col] &= ~mask;
|
||||
else
|
||||
firstStripPtr[(y0 / 8) * 96 + col] |= mask;
|
||||
}
|
||||
// Next loop down the line the total number of solids
|
||||
if (y0 / 8 != y1 / 8)
|
||||
for (uint8_t col = x0; col < x1; col++)
|
||||
for (uint8_t r = (y0 / 8); r < (y1 / 8); r++) {
|
||||
// This gives us the row index r
|
||||
if (clear)
|
||||
firstStripPtr[(r * 96) + col] = 0;
|
||||
else
|
||||
firstStripPtr[(r * 96) + col] = 0xFF;
|
||||
}
|
||||
|
||||
// Finally draw the tail
|
||||
mask = ~(mask << (y1 % 8));
|
||||
for (uint8_t col = x0; col < x1; col++)
|
||||
if (clear)
|
||||
firstStripPtr[(y1 / 8) * 96 + col] &= ~mask;
|
||||
else
|
||||
firstStripPtr[(y1 / 8) * 96 + col] |= mask;
|
||||
}
|
||||
|
||||
void OLED::drawHeatSymbol(uint8_t state) {
|
||||
// Draw symbol 14
|
||||
// Then draw over it, the bottom 5 pixels always stay. 8 pixels above that are
|
||||
// the levels masks the symbol nicely
|
||||
state /= 31; // 0-> 8 range
|
||||
// Then we want to draw down (16-(5+state)
|
||||
uint8_t cursor_x_temp = cursor_x;
|
||||
drawSymbol(14);
|
||||
drawFilledRect(cursor_x_temp, 0, cursor_x_temp + 12, 2 + (8 - state), true);
|
||||
}
|
||||
121
workspace/TS100/Core/Drivers/OLED.hpp
Normal file
121
workspace/TS100/Core/Drivers/OLED.hpp
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* OLED.hpp
|
||||
*
|
||||
* Created on: 20Jan.,2017
|
||||
* Author: Ben V. Brown <Ralim>
|
||||
* Designed for the SSD1307
|
||||
* Cleared for release for TS100 2017/08/20
|
||||
*/
|
||||
|
||||
#ifndef OLED_HPP_
|
||||
#define OLED_HPP_
|
||||
#include <BSP.h>
|
||||
#include "stm32f1xx_hal.h"
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include "FRToSI2C.hpp"
|
||||
#include "Font.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "FreeRTOS.h"
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#define DEVICEADDR_OLED (0x3c<<1)
|
||||
#define OLED_WIDTH 96
|
||||
#define OLED_HEIGHT 16
|
||||
#define FRAMEBUFFER_START 17
|
||||
|
||||
class OLED {
|
||||
public:
|
||||
|
||||
enum DisplayState : bool {
|
||||
OFF = false,
|
||||
ON = true
|
||||
};
|
||||
|
||||
static void initialize(); // Startup the I2C coms (brings screen out of reset etc)
|
||||
|
||||
// Draw the buffer out to the LCD using the DMA Channel
|
||||
static void refresh() {
|
||||
FRToSI2C::Transmit( DEVICEADDR_OLED, screenBuffer,
|
||||
FRAMEBUFFER_START + (OLED_WIDTH * 2));
|
||||
//DMA tx time is ~ 20mS Ensure after calling this you delay for at least 25ms
|
||||
//or we need to goto double buffering
|
||||
}
|
||||
|
||||
static void setDisplayState(DisplayState state) {
|
||||
displayState = state;
|
||||
screenBuffer[1] = (state == ON) ? 0xAF : 0xAE;
|
||||
}
|
||||
|
||||
static void setRotation(bool leftHanded); // Set the rotation for the screen
|
||||
// Get the current rotation of the LCD
|
||||
static bool getRotation() {
|
||||
return inLeftHandedMode;
|
||||
}
|
||||
static int16_t getCursorX() {
|
||||
return cursor_x;
|
||||
}
|
||||
static void print(const char* string);// Draw a string to the current location, with current font
|
||||
// Set the cursor location by pixels
|
||||
static void setCursor(int16_t x, int16_t y) {
|
||||
cursor_x = x;
|
||||
cursor_y = y;
|
||||
}
|
||||
//Set cursor location by chars in current font
|
||||
static void setCharCursor(int16_t x, int16_t y) {
|
||||
cursor_x = x * fontWidth;
|
||||
cursor_y = y * fontHeight;
|
||||
}
|
||||
static void setFont(uint8_t fontNumber); // (Future) Set the font that is being used
|
||||
static uint8_t getFont();
|
||||
static void drawImage(const uint8_t* buffer, uint8_t x, uint8_t width) {
|
||||
drawArea(x, 0, width, 16, buffer);
|
||||
}
|
||||
// Draws an image to the buffer, at x offset from top to bottom (fixed height renders)
|
||||
static void printNumber(uint16_t number, uint8_t places,bool noLeaderZeros=true);
|
||||
// Draws a number at the current cursor location
|
||||
// Clears the buffer
|
||||
static void clearScreen() {
|
||||
memset(firstStripPtr, 0, OLED_WIDTH * 2);
|
||||
}
|
||||
// Draws the battery level symbol
|
||||
static void drawBattery(uint8_t state) {
|
||||
drawSymbol(3 + (state > 10 ? 10 : state));
|
||||
}
|
||||
// Draws a checkbox
|
||||
static void drawCheckbox(bool state) {
|
||||
drawSymbol((state) ? 16 : 17);
|
||||
}
|
||||
static void debugNumber(int32_t val);
|
||||
static void drawSymbol(uint8_t symbolID);//Used for drawing symbols of a predictable width
|
||||
static void drawArea(int16_t x, int8_t y, uint8_t wide, uint8_t height,
|
||||
const uint8_t* ptr); //Draw an area, but y must be aligned on 0/8 offset
|
||||
static void drawAreaSwapped(int16_t x, int8_t y, uint8_t wide, uint8_t height,
|
||||
const uint8_t* ptr); //Draw an area, but y must be aligned on 0/8 offset
|
||||
static void fillArea(int16_t x, int8_t y, uint8_t wide, uint8_t height,
|
||||
const uint8_t value); //Fill an area, but y must be aligned on 0/8 offset
|
||||
static void drawFilledRect(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1,
|
||||
bool clear);
|
||||
static void drawHeatSymbol(uint8_t state);
|
||||
static void drawScrollIndicator(uint8_t p, uint8_t h); // Draws a scrolling position indicator
|
||||
static void transitionSecondaryFramebuffer(bool forwardNavigation);
|
||||
static void useSecondaryFramebuffer(bool useSecondary);
|
||||
private:
|
||||
static void drawChar(char c); // Draw a character to a specific location
|
||||
static void setFramebuffer(uint8_t *buffer);
|
||||
static const uint8_t* currentFont;// Pointer to the current font used for rendering to the buffer
|
||||
static uint8_t* firstStripPtr; // Pointers to the strips to allow for buffer having extra content
|
||||
static uint8_t* secondStripPtr; //Pointers to the strips
|
||||
static bool inLeftHandedMode; // Whether the screen is in left or not (used for offsets in GRAM)
|
||||
static DisplayState displayState;
|
||||
static uint8_t fontWidth, fontHeight;
|
||||
static int16_t cursor_x, cursor_y;
|
||||
static uint8_t displayOffset;
|
||||
static uint8_t screenBuffer[16 + (OLED_WIDTH * 2) + 10]; // The data buffer
|
||||
static uint8_t secondFrameBuffer[OLED_WIDTH * 2];
|
||||
};
|
||||
|
||||
#endif /* OLED_HPP_ */
|
||||
10
workspace/TS100/Core/Drivers/README.md
Normal file
10
workspace/TS100/Core/Drivers/README.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# Drivers
|
||||
|
||||
Drivers are the classes used to represent physical hardware on the board in a more abstract way, that are more complex than just an IO
|
||||
|
||||
* OLED Display
|
||||
* Accelerometers
|
||||
* Button handling logic
|
||||
* Tip thermo response modelling
|
||||
|
||||
All drivers should be written with minimal hardware assumptions, and defer hardware related logic to the BSP folder where possible
|
||||
124
workspace/TS100/Core/Drivers/TipThermoModel.cpp
Normal file
124
workspace/TS100/Core/Drivers/TipThermoModel.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* TipThermoModel.cpp
|
||||
*
|
||||
* Created on: 7 Oct 2019
|
||||
* Author: ralim
|
||||
*/
|
||||
|
||||
#include "TipThermoModel.h"
|
||||
#include "Settings.h"
|
||||
#include "BSP.h"
|
||||
#include "../../configuration.h"
|
||||
|
||||
/*
|
||||
* The hardware is laid out as a non-inverting op-amp
|
||||
* There is a pullup of 39k(TS100) from the +ve input to 3.9V (1M pulup on TS100)
|
||||
*
|
||||
* The simplest case to model this, is to ignore the pullup resistors influence, and assume that its influence is mostly constant
|
||||
* -> Tip resistance *does* change with temp, but this should be much less than the rest of the system.
|
||||
*
|
||||
* When a thermocouple is equal temperature at both sides (hot and cold junction), then the output should be 0uV
|
||||
* Therefore, by measuring the uV when both are equal, the measured reading is the offset value.
|
||||
* This is a mix of the pull-up resistor, combined with tip manufacturing differences.
|
||||
*
|
||||
* All of the thermocouple readings are based on this expired patent
|
||||
* - > https://patents.google.com/patent/US6087631A/en
|
||||
*
|
||||
* This was bought to my attention by <Kuba Sztandera>
|
||||
*/
|
||||
|
||||
|
||||
uint32_t TipThermoModel::convertTipRawADCTouV(uint16_t rawADC) {
|
||||
// This takes the raw ADC samples, converts these to uV
|
||||
// Then divides this down by the gain to convert to the uV on the input to the op-amp (A+B terminals)
|
||||
// Then remove the calibration value that is stored as a tip offset
|
||||
uint32_t vddRailmVX10 = 33000; //The vreg is +-2%, but we have no higher accuracy available
|
||||
// 4096 * 8 readings for full scale
|
||||
// Convert the input ADC reading back into mV times 10 format.
|
||||
uint32_t rawInputmVX10 = (rawADC * vddRailmVX10) / (4096 * 8);
|
||||
|
||||
uint32_t valueuV = rawInputmVX10 * 100; // shift into uV
|
||||
//Now to divide this down by the gain
|
||||
valueuV = (valueuV) / OP_AMP_GAIN_STAGE;
|
||||
//Remove uV tipOffset
|
||||
if (valueuV >= systemSettings.CalibrationOffset)
|
||||
valueuV -= systemSettings.CalibrationOffset;
|
||||
else
|
||||
valueuV = 0;
|
||||
|
||||
return valueuV;
|
||||
}
|
||||
|
||||
uint32_t TipThermoModel::convertTipRawADCToDegC(uint16_t rawADC) {
|
||||
return convertuVToDegC(convertTipRawADCTouV(rawADC));
|
||||
}
|
||||
#ifdef ENABLED_FAHRENHEIT_SUPPORT
|
||||
uint32_t TipThermoModel::convertTipRawADCToDegF(uint16_t rawADC) {
|
||||
return convertuVToDegF(convertTipRawADCTouV(rawADC));
|
||||
}
|
||||
#endif
|
||||
|
||||
//Table that is designed to be walked to find the best sample for the lookup
|
||||
|
||||
//Extrapolate between two points
|
||||
// [x1, y1] = point 1
|
||||
// [x2, y2] = point 2
|
||||
// x = input value
|
||||
// output is x's extrapolated y value
|
||||
int32_t LinearInterpolate(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
|
||||
int32_t x) {
|
||||
return y1 + (((((x - x1) * 1000) / (x2 - x1)) * (y2 - y1))) / 1000;
|
||||
}
|
||||
|
||||
uint32_t TipThermoModel::convertuVToDegC(uint32_t tipuVDelta) {
|
||||
//based on new measurements, tip is quite linear
|
||||
//
|
||||
tipuVDelta *= 10;
|
||||
tipuVDelta /= systemSettings.TipGain;
|
||||
|
||||
#ifdef MODEL_TS80
|
||||
tipuVDelta /= OP_AMP_GAIN_STAGE_TS100 / OP_AMP_GAIN_STAGE_TS80;
|
||||
#endif
|
||||
|
||||
return tipuVDelta;
|
||||
}
|
||||
|
||||
#ifdef ENABLED_FAHRENHEIT_SUPPORT
|
||||
uint32_t TipThermoModel::convertuVToDegF(uint32_t tipuVDelta) {
|
||||
return convertCtoF(convertuVToDegC(tipuVDelta));
|
||||
}
|
||||
|
||||
uint32_t TipThermoModel::convertCtoF(uint32_t degC) {
|
||||
//(Y °C × 9/5) + 32 =Y°F
|
||||
return 32 + ((degC * 9) / 5);
|
||||
}
|
||||
|
||||
uint32_t TipThermoModel::convertFtoC(uint32_t degF) {
|
||||
//(Y°F − 32) × 5/9 = Y°C
|
||||
if (degF < 32)
|
||||
return 0;
|
||||
return ((degF - 32) * 5) / 9;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t TipThermoModel::getTipInC(bool sampleNow) {
|
||||
uint32_t currentTipTempInC = TipThermoModel::convertTipRawADCToDegC(
|
||||
getTipRawTemp(sampleNow));
|
||||
currentTipTempInC += getHandleTemperature() / 10; //Add handle offset
|
||||
return currentTipTempInC;
|
||||
}
|
||||
#ifdef ENABLED_FAHRENHEIT_SUPPORT
|
||||
uint32_t TipThermoModel::getTipInF(bool sampleNow) {
|
||||
uint32_t currentTipTempInF = TipThermoModel::convertTipRawADCToDegF(
|
||||
getTipRawTemp(sampleNow));
|
||||
currentTipTempInF += convertCtoF(getHandleTemperature() / 10); //Add handle offset
|
||||
return currentTipTempInF;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t TipThermoModel::getTipMaxInC() {
|
||||
uint32_t maximumTipTemp = TipThermoModel::convertTipRawADCToDegC(
|
||||
0x7FFF - (80 * 5)); //back off approx 5 deg c from ADC max
|
||||
maximumTipTemp += getHandleTemperature() / 10; //Add handle offset
|
||||
return maximumTipTemp - 1;
|
||||
}
|
||||
42
workspace/TS100/Core/Drivers/TipThermoModel.h
Normal file
42
workspace/TS100/Core/Drivers/TipThermoModel.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* TipThermoModel.h
|
||||
*
|
||||
* Created on: 7 Oct 2019
|
||||
* Author: ralim
|
||||
*/
|
||||
|
||||
#ifndef SRC_TIPTHERMOMODEL_H_
|
||||
#define SRC_TIPTHERMOMODEL_H_
|
||||
#include "stdint.h"
|
||||
#include "BSP.h"
|
||||
#include "unit.h"
|
||||
class TipThermoModel {
|
||||
public:
|
||||
//These are the main two functions
|
||||
static uint32_t getTipInC(bool sampleNow = false);
|
||||
#ifdef ENABLED_FAHRENHEIT_SUPPORT
|
||||
static uint32_t getTipInF(bool sampleNow = false);
|
||||
#endif
|
||||
|
||||
//Calculates the maximum temperature can can be read by the ADC range
|
||||
static uint32_t getTipMaxInC();
|
||||
|
||||
static uint32_t convertTipRawADCToDegC(uint16_t rawADC);
|
||||
#ifdef ENABLED_FAHRENHEIT_SUPPORT
|
||||
static uint32_t convertTipRawADCToDegF(uint16_t rawADC);
|
||||
#endif
|
||||
//Returns the uV of the tip reading before the op-amp compensating for pullups
|
||||
static uint32_t convertTipRawADCTouV(uint16_t rawADC);
|
||||
#ifdef ENABLED_FAHRENHEIT_SUPPORT
|
||||
static uint32_t convertCtoF(uint32_t degC);
|
||||
static uint32_t convertFtoC(uint32_t degF);
|
||||
#endif
|
||||
|
||||
private:
|
||||
static uint32_t convertuVToDegC(uint32_t tipuVDelta);
|
||||
#ifdef ENABLED_FAHRENHEIT_SUPPORT
|
||||
static uint32_t convertuVToDegF(uint32_t tipuVDelta);
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* SRC_TIPTHERMOMODEL_H_ */
|
||||
Reference in New Issue
Block a user