├── Hardware └── Little Helper Rev 1.9.cop ├── Firmware ├── Appfruits_Debug.cpp ├── Appfruits_Debug.h ├── Animator.h ├── Object.cpp ├── Appfruits_Button.h ├── Appfruits_Transfer.cpp ├── Animator.cpp ├── Object.h ├── Timer.cpp ├── Timer.h ├── Appfruits_Transfer.h ├── WaveformView.h ├── PinDescriptionView.h ├── SceneController.h ├── MenuItemButtonView.h ├── StatusBarView.h ├── Icon.h ├── PWMPreviewView.h ├── ProgressBar.h ├── MenuItemButtonView.cpp ├── Appfruits_Button.cpp ├── LabelView.h ├── Buffer.h ├── SceneController.cpp ├── AnalogOutSceneController.h ├── ColorTheme.h ├── ClockOutSceneController.h ├── WaveformView.cpp ├── MenuItemWheelView.h ├── SoftI2CMaster.h ├── Buffer.cpp ├── fonts.h ├── Animation.h ├── MenuItemEnumView.h ├── Pins.h ├── TouchWheel.h ├── I2CScannerSceneController.h ├── ColorTheme.cpp ├── LabelView.cpp ├── Icon.cpp ├── MenuItemView.h ├── LightBoxSceneController.h ├── ProgressBar.cpp ├── ScopeView.h ├── StatusBarView.cpp ├── MenuView.h ├── AnalogOutSceneController.cpp ├── PinDescriptionView.cpp ├── MainMenuSceneController.h ├── ScopeView.cpp ├── View.h ├── PWMPreviewView.cpp ├── ScopeSceneController.h ├── ClockOutSceneController.cpp ├── Appfruits_QTouch.h ├── TouchWheel.cpp ├── Pins.cpp ├── Application.h ├── Adafruit_mfGFX.h ├── LittleHelper.ino ├── Animation.cpp ├── MenuItemView.cpp ├── View.cpp ├── MenuItemEnumView.cpp ├── MenuItemWheelView.cpp ├── LightBoxSceneController.cpp ├── I2CScannerSceneController.cpp ├── Application.cpp ├── MainMenuSceneController.cpp ├── MenuView.cpp ├── Appfruits_ST7735.h ├── Appfruits_QTouch.cpp ├── StackArray.h ├── SoftI2CMaster.cpp ├── ScopeSceneController.cpp └── Adafruit_mfGFX.cpp ├── LICENSE └── README.md /Hardware/Little Helper Rev 1.9.cop: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appfruits/LittleHelper/HEAD/Hardware/Little Helper Rev 1.9.cop -------------------------------------------------------------------------------- /Firmware/Appfruits_Debug.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Phillip Schuster on 27.03.15. 3 | // 4 | 5 | #include "Appfruits_Debug.h" 6 | 7 | Appfruits_Debug Debug; -------------------------------------------------------------------------------- /Firmware/Appfruits_Debug.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Phillip Schuster on 27.03.15. 3 | // 4 | 5 | #ifndef _TEENSYCMAKE_DEBUG_H_ 6 | #define _TEENSYCMAKE_DEBUG_H_ 7 | 8 | #include "Arduino.h" 9 | #include 10 | 11 | class Appfruits_Debug: public usb_serial_class 12 | { 13 | 14 | }; 15 | 16 | extern Appfruits_Debug Debug; 17 | 18 | 19 | #endif //_TEENSYCMAKE_DEBUG_H_ 20 | -------------------------------------------------------------------------------- /Firmware/Animator.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Phillip Schuster on 24.03.15. 3 | // 4 | 5 | #ifndef _TEENSYCMAKE_ANIMATOR_H_ 6 | #define _TEENSYCMAKE_ANIMATOR_H_ 7 | 8 | #include "Animation.h" 9 | 10 | class AnimatorClass 11 | { 12 | public: 13 | AnimatorClass(); 14 | Animation* getAnimationSlot(); 15 | 16 | void update(); 17 | 18 | private: 19 | Animation _animationSlots[10]; 20 | }; 21 | 22 | extern AnimatorClass Animator; 23 | 24 | 25 | #endif //_TEENSYCMAKE_ANIMATOR_H_ 26 | -------------------------------------------------------------------------------- /Firmware/Object.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #include "Object.h" 20 | -------------------------------------------------------------------------------- /Firmware/Appfruits_Button.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Phillip Schuster on 26.03.15. 3 | // 4 | 5 | #ifndef _TEENSYCMAKE_BUTTON_H_ 6 | #define _TEENSYCMAKE_BUTTON_H_ 7 | 8 | #include "Arduino.h" 9 | 10 | class Appfruits_Button 11 | { 12 | public: 13 | Appfruits_Button(uint8_t pin); 14 | 15 | bool buttonPressed(); 16 | bool buttonUp(); 17 | bool buttonClicked(); 18 | uint32_t getClickLength(); //TODO: uint32_t is a bit oversized 19 | uint32_t getButtonDownTime(); 20 | void begin(); 21 | 22 | void update(); 23 | 24 | private: 25 | uint32_t _buttonDownTime; 26 | uint8_t _pin; 27 | bool _clicked; 28 | bool _lastState; 29 | uint32_t _clickLength; 30 | }; 31 | 32 | 33 | #endif //_TEENSYCMAKE_BUTTON_H_ 34 | -------------------------------------------------------------------------------- /Firmware/Appfruits_Transfer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #include "Appfruits_Transfer.h" 20 | -------------------------------------------------------------------------------- /Firmware/Animator.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * 2014-2015 Phillip Schuster (@appfruits) 6 | * http://www.appfruits.com 7 | */ 8 | 9 | #include "Animator.h" 10 | 11 | AnimatorClass Animator; 12 | 13 | AnimatorClass::AnimatorClass() 14 | { 15 | 16 | } 17 | 18 | Animation* AnimatorClass::getAnimationSlot() 19 | { 20 | for (uint8_t i=0;i<10;i++) 21 | { 22 | if (!_animationSlots[i].isActive()) 23 | { 24 | _animationSlots[i].reset(); 25 | return &_animationSlots[i]; 26 | } 27 | } 28 | 29 | return NULL; 30 | } 31 | 32 | void AnimatorClass::update() 33 | { 34 | for (uint8_t i=0;i<10;i++) 35 | { 36 | if (_animationSlots[i].isActive()) 37 | { 38 | _animationSlots[i].update(); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /Firmware/Object.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #ifndef _TEENSYCMAKE_OBJECT_H_ 20 | #define _TEENSYCMAKE_OBJECT_H_ 21 | 22 | #include "Arduino.h" 23 | 24 | class Object 25 | { 26 | public: 27 | virtual String getDescription() = 0; 28 | }; 29 | 30 | 31 | #endif //_TEENSYCMAKE_OBJECT_H_ 32 | -------------------------------------------------------------------------------- /Firmware/Timer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #include "Timer.h" 20 | 21 | Timer::Timer(uint32_t timeOut) 22 | { 23 | _timeOut = timeOut; 24 | } 25 | 26 | void Timer::reset() 27 | { 28 | _startTime = millis(); 29 | } 30 | 31 | bool Timer::isTimedOut() 32 | { 33 | if ((millis() - _startTime) > _timeOut) 34 | { 35 | return true; 36 | } 37 | 38 | return false; 39 | } -------------------------------------------------------------------------------- /Firmware/Timer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #ifndef _TEENSYCMAKE_TIMER_H_ 20 | #define _TEENSYCMAKE_TIMER_H_ 21 | 22 | #include "Arduino.h" 23 | 24 | class Timer 25 | { 26 | public: 27 | Timer(uint32_t timeOut); 28 | void reset(); 29 | bool isTimedOut(); 30 | 31 | private: 32 | uint32_t _timeOut; 33 | uint32_t _startTime; 34 | }; 35 | 36 | 37 | #endif //_TEENSYCMAKE_TIMER_H_ 38 | -------------------------------------------------------------------------------- /Firmware/Appfruits_Transfer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #ifndef TEENSYCMAKE_APPFRUITS_TRANSFER_H 20 | #define TEENSYCMAKE_APPFRUITS_TRANSFER_H 21 | 22 | 23 | class Appfruits_Transfer 24 | { 25 | public: 26 | Appfruits_Transfer(int clkPin, int dataPin); 27 | void write(void* data, int size); 28 | 29 | private: 30 | int _clkPin; 31 | int _dataPin; 32 | }; 33 | 34 | 35 | #endif //TEENSYCMAKE_APPFRUITS_TRANSFER_H 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Appfruits 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Firmware/WaveformView.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #ifndef _TEENSYCMAKE_WAVEFORMVIEW_H_ 20 | #define _TEENSYCMAKE_WAVEFORMVIEW_H_ 21 | 22 | #include "View.h" 23 | 24 | class WaveformView: public View 25 | { 26 | public: 27 | WaveformView(uint16_t x, uint16_t y, uint16_t width, uint16_t height); 28 | 29 | virtual void draw(); 30 | void setXScale(float xScale); 31 | 32 | private: 33 | float _xScale; 34 | 35 | virtual String getDescription() override; 36 | }; 37 | 38 | #endif //_TEENSYCMAKE_WAVEFORMVIEW_H_ 39 | -------------------------------------------------------------------------------- /Firmware/PinDescriptionView.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #ifndef TEENSYCMAKE_PINDESCRIPTIONVIEW_H 20 | #define TEENSYCMAKE_PINDESCRIPTIONVIEW_H 21 | 22 | #include "View.h" 23 | 24 | class PinDescriptionView: public View 25 | { 26 | public: 27 | PinDescriptionView(); 28 | PinDescriptionView(uint16_t x, uint16_t y, uint16_t width, uint16_t height); 29 | 30 | void setText(String text); 31 | 32 | virtual void draw() override; 33 | 34 | private: 35 | String _text; 36 | }; 37 | 38 | 39 | #endif //TEENSYCMAKE_PINDESCRIPTIONVIEW_H 40 | -------------------------------------------------------------------------------- /Firmware/SceneController.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #ifndef __SCENECONTROLLER_H_ 20 | #define __SCENECONTROLLER_H_ 21 | 22 | #include "View.h" 23 | #include "Application.h" 24 | 25 | class SceneController 26 | { 27 | public: 28 | SceneController(); 29 | virtual ~SceneController(); 30 | 31 | virtual void setup(); 32 | virtual void loop(); 33 | 34 | virtual String getName() = 0; 35 | 36 | //Events 37 | virtual void onWillAppear(); 38 | virtual void onWillDisappear(); 39 | 40 | bool statusBarVisible(); 41 | }; 42 | 43 | 44 | #endif //__SCENECONTROLLER_H_ 45 | -------------------------------------------------------------------------------- /Firmware/MenuItemButtonView.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #ifndef _TEENSYCMAKE_MENUITEMBUTTONVIEW_H_ 20 | #define _TEENSYCMAKE_MENUITEMBUTTONVIEW_H_ 21 | 22 | #include "MenuItemView.h" 23 | 24 | class MenuItemButtonView: public MenuItemView 25 | { 26 | public: 27 | MenuItemButtonView(String title, MenuItemViewDelegate* delegate); 28 | MenuItemButtonView(String title, MenuItemViewDelegate* delegate, void* object); 29 | 30 | virtual void onClicked() override; 31 | 32 | public: 33 | virtual String getDescription() override; 34 | }; 35 | 36 | 37 | #endif //_TEENSYCMAKE_MENUITEMBUTTONVIEW_H_ 38 | -------------------------------------------------------------------------------- /Firmware/StatusBarView.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #ifndef _TEENSYCMAKE_STATUSBARVIEW_H_ 20 | #define _TEENSYCMAKE_STATUSBARVIEW_H_ 21 | 22 | #include "View.h" 23 | #include "Timer.h" 24 | 25 | class StatusBarView: public View 26 | { 27 | public: 28 | StatusBarView(); 29 | void draw(); 30 | 31 | void setCaption(String caption); 32 | 33 | private: 34 | Timer _timeOut; 35 | uint8_t _charge; 36 | String _caption; 37 | 38 | public: 39 | virtual String getDescription() override; 40 | 41 | virtual void update() override; 42 | }; 43 | 44 | 45 | #endif //_TEENSYCMAKE_STATUSBARVIEW_H_ 46 | -------------------------------------------------------------------------------- /Firmware/Icon.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #ifndef TEENSYCMAKE_ICONS_H 20 | #define TEENSYCMAKE_ICONS_H 21 | 22 | #include 23 | #include "Arduino.h" 24 | 25 | #define ICON_WIDTH 8 26 | #define ICON_HEIGHT 8 27 | 28 | class Icon 29 | { 30 | public: 31 | Icon(const uint8_t* pixelData); 32 | 33 | uint8_t getWidth(); 34 | uint8_t getHeight(); 35 | const uint8_t* getPixelData(); 36 | 37 | private: 38 | const uint8_t* _pixelData; 39 | }; 40 | 41 | extern Icon SlopeRaising; 42 | extern Icon SlopeFalling; 43 | extern Icon SlopeBoth; 44 | 45 | 46 | #endif //TEENSYCMAKE_ICONS_H 47 | -------------------------------------------------------------------------------- /Firmware/PWMPreviewView.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #ifndef _TEENSYCMAKE_PWMPREVIEWVIEW_H_ 20 | #define _TEENSYCMAKE_PWMPREVIEWVIEW_H_ 21 | 22 | #include "View.h" 23 | 24 | class PWMPreviewView: public View 25 | { 26 | public: 27 | PWMPreviewView(uint16_t x, uint16_t y, uint16_t width, uint16_t height); 28 | virtual void draw(); 29 | 30 | void setFrequency(float frequency); 31 | void setDuty(float duty); 32 | 33 | private: 34 | float _frequency; 35 | float _duty; 36 | 37 | public: 38 | virtual String getDescription() override; 39 | }; 40 | 41 | 42 | #endif //_TEENSYCMAKE_PWMPREVIEWVIEW_H_ 43 | -------------------------------------------------------------------------------- /Firmware/ProgressBar.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #ifndef TEENSYCMAKE_PROGRESSBAR_H 20 | #define TEENSYCMAKE_PROGRESSBAR_H 21 | 22 | #include "View.h" 23 | 24 | class ProgressBar: public View 25 | { 26 | public: 27 | ProgressBar(uint16_t x, uint16_t y, uint16_t width, uint16_t height); 28 | virtual void draw(); 29 | 30 | void setMinValue(float minValue); 31 | void setMaxValue(float maxValue); 32 | void setLimits(float minValue, float maxValue); 33 | float getValue(); 34 | void setValue(float value); 35 | 36 | virtual String getDescription() override; 37 | 38 | private: 39 | float _minValue; 40 | float _maxValue; 41 | float _value; 42 | }; 43 | 44 | 45 | #endif //TEENSYCMAKE_PROGRESSBAR_H 46 | -------------------------------------------------------------------------------- /Firmware/MenuItemButtonView.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #include "MenuItemButtonView.h" 20 | #include "Application.h" 21 | 22 | MenuItemButtonView::MenuItemButtonView(String title, MenuItemViewDelegate* delegate): 23 | MenuItemView(title) 24 | { 25 | _title = title; 26 | _delegate = delegate; 27 | }; 28 | 29 | MenuItemButtonView::MenuItemButtonView(String title, MenuItemViewDelegate* delegate, void *object): 30 | MenuItemButtonView(title, delegate) 31 | { 32 | _object = object; 33 | } 34 | 35 | void MenuItemButtonView::onClicked() 36 | { 37 | if (_delegate != NULL) 38 | { 39 | _delegate->menuItemViewTriggered(this); 40 | } 41 | } 42 | 43 | String MenuItemButtonView::getDescription() 44 | { 45 | return "MenuItemButtonView"; 46 | } 47 | -------------------------------------------------------------------------------- /Firmware/Appfruits_Button.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Phillip Schuster on 26.03.15. 3 | // 4 | 5 | #include "Appfruits_Button.h" 6 | #include "Application.h" 7 | 8 | Appfruits_Button::Appfruits_Button(uint8_t pin) 9 | { 10 | _pin = pin; 11 | } 12 | 13 | void Appfruits_Button::begin() 14 | { 15 | pinMode(_pin,INPUT); 16 | } 17 | 18 | void Appfruits_Button::update() 19 | { 20 | _clicked = false; 21 | _lastState = digitalRead(_pin); 22 | 23 | if (_lastState == LOW) 24 | { 25 | if (_buttonDownTime == 0) 26 | { 27 | _buttonDownTime = millis(); 28 | } 29 | } 30 | else 31 | { 32 | if (_buttonDownTime > 0) 33 | { 34 | LOG("Button clicked"); 35 | _clicked = true; 36 | _clickLength = millis() - _buttonDownTime; 37 | } 38 | 39 | _buttonDownTime = 0; 40 | } 41 | } 42 | 43 | bool Appfruits_Button::buttonClicked() 44 | { 45 | return _clicked; 46 | } 47 | 48 | bool Appfruits_Button::buttonPressed() 49 | { 50 | return (_lastState == LOW); 51 | } 52 | 53 | bool Appfruits_Button::buttonUp() 54 | { 55 | return (_lastState == HIGH); 56 | } 57 | 58 | uint32_t Appfruits_Button::getClickLength() 59 | { 60 | return _clickLength; 61 | } 62 | 63 | uint32_t Appfruits_Button::getButtonDownTime() 64 | { 65 | if (_buttonDownTime == 0) return 0; 66 | return millis() - _buttonDownTime; 67 | } -------------------------------------------------------------------------------- /Firmware/LabelView.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #ifndef TEENSYCMAKE_LABELVIEW_H 20 | #define TEENSYCMAKE_LABELVIEW_H 21 | 22 | #include "View.h" 23 | 24 | #define TEXTALIGN_LEFT 0 25 | #define TEXTALIGN_CENTERED 1 26 | #define TEXTALIGN_RIGHT 2 27 | 28 | class LabelView: public View 29 | { 30 | public: 31 | LabelView(String text, uint16_t x, uint16_t y, uint16_t width, uint16_t height); 32 | 33 | void setText(String text); 34 | void setTextAlign(uint8_t textAlign); 35 | void setTextColor(uint16_t color); 36 | void setFont(uint8_t font); 37 | 38 | private: 39 | String _text; 40 | uint8_t _textAlign; 41 | uint8_t _font; 42 | uint16_t _textColor; 43 | public: 44 | virtual void draw() override; 45 | }; 46 | 47 | 48 | #endif //TEENSYCMAKE_LABELVIEW_H 49 | -------------------------------------------------------------------------------- /Firmware/Buffer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #ifndef _BUFFER_H_ 20 | #define _BUFFER_H_ 21 | 22 | #if defined(ARDUINO) && ARDUINO >= 100 23 | #include "Arduino.h" 24 | #else 25 | #include "WProgram.h" 26 | #endif 27 | #include 28 | 29 | struct Line { 30 | public: 31 | char buffer[22]; 32 | 33 | Line() 34 | { 35 | memset(buffer,0,sizeof(buffer)); 36 | } 37 | 38 | Line(const char* line) 39 | { 40 | strcpy(buffer,line); 41 | } 42 | }; 43 | 44 | class History 45 | { 46 | public: 47 | History(); 48 | void addLine(const char* line); 49 | uint16_t numberOfLines(); 50 | const char* getLine(uint16_t index); 51 | 52 | private: 53 | Line _lines[500]; 54 | uint16_t _currentLine; 55 | uint16_t _numberOfLines; 56 | }; 57 | 58 | #endif 59 | 60 | -------------------------------------------------------------------------------- /Firmware/SceneController.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #include "SceneController.h" 20 | #include "Application.h" 21 | 22 | SceneController::SceneController() 23 | { 24 | 25 | } 26 | 27 | SceneController::~SceneController() 28 | { 29 | 30 | } 31 | 32 | void SceneController::setup() 33 | { 34 | 35 | } 36 | 37 | void SceneController::loop() 38 | { 39 | } 40 | 41 | void SceneController::onWillAppear() 42 | { 43 | //Clear display - override if you want a nice transition effect 44 | display.clear(ST7735_BLACK); 45 | } 46 | 47 | void SceneController::onWillDisappear() 48 | { 49 | Pins.resetPins(); 50 | Application.resetFocus(); 51 | } 52 | 53 | String SceneController::getName() 54 | { 55 | return "SceneController"; 56 | } 57 | 58 | bool SceneController::statusBarVisible() 59 | { 60 | return true; 61 | } -------------------------------------------------------------------------------- /Firmware/AnalogOutSceneController.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #ifndef _TEENSYCMAKE_ANALOGOUTSCENECONTROLLER_H_ 20 | #define _TEENSYCMAKE_ANALOGOUTSCENECONTROLLER_H_ 21 | 22 | #include "SceneController.h" 23 | #include "StatusBarView.h" 24 | #include "WaveformView.h" 25 | #include "MenuView.h" 26 | #include "MenuItemView.h" 27 | 28 | class AnalogOutSceneController: public SceneController, MenuItemViewDelegate 29 | { 30 | public: 31 | AnalogOutSceneController(); 32 | 33 | private: 34 | WaveformView _waveformView; 35 | MenuView _menuView; 36 | 37 | virtual void loop() override; 38 | 39 | virtual void menuItemViewValueChanged(MenuItemView *menuItemView, float value) override; 40 | 41 | public: 42 | virtual void onWillAppear() override; 43 | 44 | virtual String getName() override; 45 | }; 46 | 47 | 48 | #endif //_TEENSYCMAKE_ANALOGOUTSCENECONTROLLER_H_ 49 | -------------------------------------------------------------------------------- /Firmware/ColorTheme.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #ifndef _TEENSYCMAKE_COLORTHEME_H_ 20 | #define _TEENSYCMAKE_COLORTHEME_H_ 21 | 22 | 23 | #include 24 | 25 | class ColorTheme 26 | { 27 | public: 28 | typedef enum Shade { 29 | Default = 0, 30 | Light = 1, 31 | Lighter = 2, 32 | Darker = 3, 33 | Dark = 4 34 | } Shade; 35 | 36 | ColorTheme(); 37 | 38 | uint16_t getPrimaryColor(Shade shade=Shade::Default); 39 | uint16_t getSecondaryColor1(Shade shade=Shade::Default); 40 | uint16_t getSecondaryColor2(Shade shade=Shade::Default); 41 | uint16_t getComplementColor(Shade shade=Shade::Default); 42 | uint16_t getBackgroundColor(Shade shade=Shade::Default); 43 | uint16_t getTextColor(Shade shade=Shade::Default); 44 | 45 | private: 46 | uint16_t _colors[4][5]; 47 | uint16_t _textColors[5]; 48 | uint16_t _backgroundColor; 49 | }; 50 | 51 | 52 | #endif //_TEENSYCMAKE_COLORTHEME_H_ 53 | -------------------------------------------------------------------------------- /Firmware/ClockOutSceneController.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #ifndef _TEENSYCMAKE_CLOCKOUTSCENECONTROLLER_H_ 20 | #define _TEENSYCMAKE_CLOCKOUTSCENECONTROLLER_H_ 21 | 22 | #include "SceneController.h" 23 | #include "StatusBarView.h" 24 | #include "MenuView.h" 25 | #include "MenuItemView.h" 26 | #include "PWMPreviewView.h" 27 | 28 | class ClockOutSceneController: public SceneController, MenuItemViewDelegate 29 | { 30 | public: 31 | ClockOutSceneController(); 32 | 33 | private: 34 | MenuView _menuView; 35 | PWMPreviewView _pwmPreviewView; 36 | bool _firstUpdate; 37 | float _duty; 38 | uint32_t _frequency; 39 | 40 | virtual void loop() override; 41 | 42 | virtual void menuItemViewValueChanged(MenuItemView *menuItemView, float value) override; 43 | 44 | public: 45 | virtual void onWillAppear() override; 46 | 47 | virtual String getName() override; 48 | }; 49 | 50 | 51 | #endif //_TEENSYCMAKE_CLOCKOUTSCENECONTROLLER_H_ 52 | -------------------------------------------------------------------------------- /Firmware/WaveformView.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #include "WaveformView.h" 20 | #include "Application.h" 21 | 22 | WaveformView::WaveformView(uint16_t x, uint16_t y, uint16_t width, uint16_t height): View(x,y,width,height) 23 | { 24 | _xScale = 0.1f; 25 | } 26 | 27 | void WaveformView::draw() 28 | { 29 | // uint16_t color = RGB565(12,61,94); 30 | // if (_selected) color = RGB565(24,122,189); 31 | display.fillRect(_frame.x,_frame.y,_frame.width,_frame.height,Application.getTheme()->getBackgroundColor()); 32 | 33 | int lx,ly; 34 | for (int x=0;x<128;x++) 35 | { 36 | int y = sin((x+64)*_xScale) * 20; 37 | if (x == 0) 38 | { 39 | lx = x; 40 | ly = y; 41 | } 42 | 43 | display.drawLine(_frame.x + lx,_frame.y + ly + 20,_frame.x + x,_frame.y + y + 20,Application.getTheme()->getSecondaryColor1()); 44 | 45 | lx = x; 46 | ly = y; 47 | } 48 | } 49 | 50 | String WaveformView::getDescription() 51 | { 52 | return "WaveformView"; 53 | } 54 | 55 | void WaveformView::setXScale(float xScale) 56 | { 57 | if (_xScale == xScale) return; 58 | _xScale = xScale; 59 | setNeedsDisplay(); 60 | } -------------------------------------------------------------------------------- /Firmware/MenuItemWheelView.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #ifndef _TEENSYCMAKE_MENUITEMWHEELVIEW_H_ 20 | #define _TEENSYCMAKE_MENUITEMWHEELVIEW_H_ 21 | 22 | #include "MenuItemView.h" 23 | 24 | class MenuItemWheelView: public MenuItemView 25 | { 26 | public: 27 | MenuItemWheelView(String title, MenuItemViewDelegate* delegate); 28 | MenuItemWheelView(String title, MenuItemViewDelegate* delegate, void* object); 29 | 30 | virtual void handleEvents() override; 31 | 32 | void setMinValue(float minValue); 33 | void setMaxValue(float maxValue); 34 | void setScale(float scale); 35 | void setLimits(float minValue, float maxValue); 36 | float getValue(); 37 | void setValue(float value); 38 | void setTitle(String title); 39 | 40 | private: 41 | float _touchWheelOffset; 42 | bool _lastButtonState; 43 | float _minValue; 44 | float _maxValue; 45 | float _scale; 46 | float _value; 47 | 48 | public: 49 | virtual void draw() override; 50 | 51 | virtual bool needsFocus() override; 52 | 53 | virtual void onClicked() override; 54 | 55 | public: 56 | virtual String getDescription() override; 57 | }; 58 | 59 | 60 | #endif //_TEENSYCMAKE_MENUITEMWHEELVIEW_H_ 61 | -------------------------------------------------------------------------------- /Firmware/SoftI2CMaster.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SoftI2CMaster.h -- Multi-instance software I2C Master library 3 | * 4 | * 2010-2012 Tod E. Kurt, http://todbot.com/blog/ 5 | * 2014, by Testato: update library and examples for follow Wire’s API of Arduino IDE 1.x 6 | * 7 | */ 8 | 9 | #ifndef SoftI2CMaster_h 10 | #define SoftI2CMaster_h 11 | 12 | #include 13 | 14 | #define _SOFTI2CMASTER_VERSION 13 // software version of this library 15 | 16 | 17 | class SoftI2CMaster 18 | { 19 | 20 | private: 21 | // per object data 22 | uint8_t _sclPin; 23 | uint8_t _sdaPin; 24 | uint8_t _sclBitMask; 25 | uint8_t _sdaBitMask; 26 | volatile uint8_t *_sclPortReg; 27 | volatile uint8_t *_sdaPortReg; 28 | volatile uint8_t *_sclDirReg; 29 | volatile uint8_t *_sdaDirReg; 30 | 31 | uint8_t usePullups; 32 | 33 | // private methods 34 | 35 | void i2c_writebit( uint8_t c ); 36 | uint8_t i2c_readbit(void); 37 | void i2c_init(void); 38 | void i2c_start(void); 39 | void i2c_repstart(void); 40 | void i2c_stop(void); 41 | uint8_t i2c_write( uint8_t c ); 42 | uint8_t i2c_read( uint8_t ack ); 43 | 44 | public: 45 | // public methods 46 | SoftI2CMaster(); 47 | SoftI2CMaster(uint8_t sclPin, uint8_t sdaPin); 48 | SoftI2CMaster(uint8_t sclPin, uint8_t sdaPin, uint8_t usePullups); 49 | 50 | void setPins(uint8_t sclPin, uint8_t sdaPin, uint8_t usePullups); 51 | 52 | uint8_t beginTransmission(uint8_t address); 53 | uint8_t beginTransmission(int address); 54 | uint8_t endTransmission(void); 55 | uint8_t write(uint8_t); 56 | void write(uint8_t*, uint8_t); 57 | void write(int); 58 | void write(char*); 59 | 60 | uint8_t requestFrom(int address); 61 | uint8_t requestFrom(uint8_t address); 62 | uint8_t read( uint8_t ack ); 63 | uint8_t read(); 64 | uint8_t readLast(); 65 | 66 | }; 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /Firmware/Buffer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #include "Buffer.h" 20 | 21 | History::History() 22 | { 23 | _currentLine = 0; 24 | _numberOfLines = 0; 25 | } 26 | 27 | void History::addLine(const char* message) 28 | { 29 | uint16_t len = strlen(message); 30 | uint16_t numberOfLines = (uint16_t)len/21; 31 | for (uint16_t i=0;i<=numberOfLines;i++) 32 | { 33 | Line* line = &_lines[_currentLine]; 34 | memset(line->buffer,0,sizeof(line->buffer)); 35 | 36 | const char* start = message+(i*sizeof(char)*21); 37 | const char* end = start + (sizeof(char)*21); 38 | uint16_t length = (int)end - (int)start; 39 | if (((int)end-(int)message) > len) 40 | { 41 | length = ((int)end-(int)message) - len; 42 | } 43 | 44 | memcpy(line->buffer,start,length); 45 | 46 | _currentLine++; 47 | if (_currentLine > 499) 48 | { 49 | _currentLine = 0; 50 | } 51 | else 52 | { 53 | _numberOfLines++; 54 | } 55 | } 56 | } 57 | 58 | uint16_t History::numberOfLines() 59 | { 60 | return _numberOfLines; 61 | } 62 | 63 | const char* History::getLine(uint16_t index) 64 | { 65 | if (index > _numberOfLines) return ""; 66 | return _lines[index].buffer; 67 | } 68 | -------------------------------------------------------------------------------- /Firmware/fonts.h: -------------------------------------------------------------------------------- 1 | // 2 | // fonts.h 3 | // 4 | 5 | #ifndef _fonts_h 6 | #define _fonts_h 7 | 8 | #include "Arduino.h" 9 | 10 | // Font selection descriptors - Add an entry for each new font and number sequentially 11 | #define TIMESNR_8 0 12 | #define CENTURY_8 1 13 | #define ARIAL_8 2 14 | #define COMICS_8 3 15 | #define GLCDFONT 4 16 | #define TEST 5 17 | #define SEGOE_8 6 18 | #define SEGOE_16 7 19 | #define ARIAL_16 8 20 | #define CALIBRI_16 9 21 | 22 | #define FONT_START 0 23 | #define FONT_END 1 24 | 25 | struct FontDescriptor 26 | { 27 | uint8_t width; // width in bits 28 | uint8_t height; // char height in bits 29 | uint16_t offset; // offset of char into char array 30 | }; 31 | 32 | // Font references - add pair of references for each new font 33 | extern const uint8_t timesNewRoman_8ptBitmaps[]; 34 | extern const FontDescriptor timesNewRoman_8ptDescriptors[]; 35 | 36 | extern const uint8_t centuryGothic_8ptBitmaps[]; 37 | extern const FontDescriptor centuryGothic_8ptDescriptors[]; 38 | 39 | extern const uint8_t arial_8ptBitmaps[]; 40 | extern const FontDescriptor arial_8ptDescriptors[]; 41 | 42 | extern const uint8_t comicSansMS_8ptBitmaps[]; 43 | extern const FontDescriptor comicSansMS_8ptDescriptors[]; 44 | 45 | extern const uint8_t glcdfontBitmaps[]; 46 | extern const FontDescriptor glcdfontDescriptors[]; 47 | 48 | extern const uint8_t testBitmaps[]; 49 | extern const FontDescriptor testDescriptors[]; 50 | 51 | extern const uint8_t segoeUI_8ptBitmaps[]; 52 | extern const FontDescriptor segoeUI_8ptDescriptors[]; 53 | 54 | extern const uint8_t segoeUI_16ptBitmaps[]; 55 | extern const FontDescriptor segoeUI_16ptDescriptors[]; 56 | 57 | extern const uint8_t arial_16ptBitmaps[]; 58 | extern const FontDescriptor arial_16ptDescriptors[]; 59 | 60 | extern const uint8_t calibri_16ptBitmaps[]; 61 | extern const FontDescriptor calibri_16ptDescriptors[]; 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LittleHelper 2 | This is the Arduino compatible firmware running Little Helper, a little device that is useful in electronic labs. The firmware also shows how to build a more complex LCD based application, featuring a few standard controls. 3 | 4 | This software should compile and run on a Teensy 3.1 although you will need a few hardware components to make use of it. Have a look at http://www.appfruits.com/littlehelper. We provide everything from PCB schematics and layout, even enclosings to build your own Little Helper or getting inspired building your own little, useful device. 5 | 6 | Copyright 2014-2015 by Phillip Schuster 7 | http://www.appfruits.com 8 | 9 | ## Hardware 10 | We also added the Eagle PCBs Design, layout and schematics. We also added the Copper file. Copper is a Mac applications that makes it easy to generate 3D models of your Eagle based PCBs and also helps in building a BOM and keeping it up to date. Have a look at http://www.copper-app.com. 11 | 12 | ## Structure 13 | This software is C++ and shows how to build a nice, stack based application runloop and User Interface that is easily expandable by providing standard controls and protocols and uses the good old MVC structure. 14 | 15 | Running such code on a small 8-bit AVR is overkill, but with all those new ARM MCUs offering a lot of performance, and more importantly offering more RAM allows such code to be written and run even on small devices. This makes it easier to write structured software that you can read in a couple of months from now. 16 | 17 | ## License 18 | We provide this in a MIT-License. You may use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software but you must include this copyright notice and this permission in all copies or substantial portions of the Software. 19 | 20 | We invest time and resources making this open source. Please support us by spreading your word and purchasing our products. 21 | -------------------------------------------------------------------------------- /Firmware/Animation.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * Animation.h -- Class for animating scalar values 6 | * 7 | * 2014-2015 Phillip Schuster (@appfruits) 8 | * http://www.appfruits.com 9 | */ 10 | 11 | #ifndef _TEENSYCMAKE_ANIMATION_H_ 12 | #define _TEENSYCMAKE_ANIMATION_H_ 13 | 14 | #include "Arduino.h" 15 | 16 | class AnimatableObject; 17 | 18 | class Animation 19 | { 20 | public: 21 | Animation(); 22 | Animation(String key); 23 | Animation(String key, float initialValue); 24 | Animation(String key, float initialValue, float targetValue); 25 | Animation(String key, float initialValue, float targetValue, float duration); 26 | 27 | void init(String key, float initialValue, float targetValue); 28 | void init(String key, float initialValue, float targetValue, float duration); 29 | void init(String key, float initialValue, float targetValue, float duration, float delay); 30 | 31 | void setDelay(float delay); 32 | void setDuration(float duration); 33 | void setInitialValue(float initialValue); 34 | void setTargetValue(float targetValue); 35 | void setKey(String key); 36 | void setObject(AnimatableObject* object); 37 | 38 | String getKey(); 39 | 40 | bool isActive(); 41 | void reset(); 42 | void update(); 43 | void start(); 44 | 45 | private: 46 | float _initialValue; 47 | float _currentValue; 48 | float _targetValue; 49 | float _duration; 50 | float _animationStart; 51 | float _delay; 52 | String _key; 53 | AnimatableObject* _object; 54 | }; 55 | 56 | class AnimatableObject 57 | { 58 | public: 59 | virtual void animationUpdated(Animation* animation, float currentValue, float timeLeft) 60 | { 61 | 62 | }; 63 | 64 | virtual void animationFinished(Animation* animation) 65 | { 66 | 67 | }; 68 | 69 | void addAnimation(Animation* animation) 70 | { 71 | animation->setObject(this); 72 | animation->start(); 73 | }; 74 | }; 75 | 76 | 77 | #endif //_TEENSYCMAKE_ANIMATION_H_ 78 | -------------------------------------------------------------------------------- /Firmware/MenuItemEnumView.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #ifndef _TEENSYCMAKE_MENUITEMENUMVIEW_H_ 20 | #define _TEENSYCMAKE_MENUITEMENUMVIEW_H_ 21 | 22 | #include "MenuItemView.h" 23 | 24 | class Enumerable 25 | { 26 | virtual uint32_t getValue() = 0; 27 | virtual String getTitle() = 0; 28 | }; 29 | 30 | struct EnumViewItem 31 | { 32 | EnumViewItem(int32_t value, String caption) { this->value = value; this->caption = caption; }; 33 | int32_t value; 34 | String caption; 35 | }; 36 | 37 | class MenuItemEnumView: public MenuItemView 38 | { 39 | public: 40 | MenuItemEnumView(String title, MenuItemViewDelegate* delegate); 41 | MenuItemEnumView(String title, MenuItemViewDelegate* delegate, void* object); 42 | 43 | virtual void handleEvents() override; 44 | 45 | int32_t getValue(); 46 | void setValue(int32_t value); 47 | uint8_t getSelectedItemIndex(); 48 | void setSelectedItemIndex(uint8_t selectedItemIndex); 49 | 50 | void addItem(int32_t value, String caption); 51 | 52 | private: 53 | float _touchWheelOffset; 54 | StackArray _items; 55 | uint8_t _selectedItemIndex; 56 | 57 | public: 58 | virtual void draw() override; 59 | virtual bool needsFocus() override; 60 | virtual void onClicked() override; 61 | 62 | public: 63 | virtual String getDescription() override; 64 | }; 65 | 66 | 67 | #endif //_TEENSYCMAKE_MENUITEMENUMVIEW_H_ 68 | -------------------------------------------------------------------------------- /Firmware/Pins.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #ifndef TEENSYCMAKE_PINS_H 20 | #define TEENSYCMAKE_PINS_H 21 | 22 | #include 23 | #include "Arduino.h" 24 | 25 | #define EXT_PIN_3 3 26 | #define EXT_PIN_2 24 27 | #define EXT_PIN_1 A14 28 | #define EXT_PIN_DAC A14 29 | 30 | #define PIN_3V3 4 31 | #define PIN_DAC 3 32 | #define PIN_GND 0 33 | 34 | class Pin 35 | { 36 | public: 37 | Pin(String name, uint16_t color, uint8_t hardwareId) { 38 | this->_name = name; 39 | this->_color = color; 40 | this->_hardwareId = hardwareId; 41 | this->_active = false; 42 | } 43 | 44 | bool isActive(); 45 | void setActive(bool active); 46 | void setName(String name); 47 | String getName(); 48 | uint8_t getHardwareId(); 49 | uint16_t getColor(); 50 | 51 | void setPinMode(uint8_t thePinMode); 52 | int analogRead(); 53 | 54 | private: 55 | String _name; 56 | uint16_t _color; 57 | uint8_t _hardwareId; 58 | bool _active; 59 | }; 60 | 61 | 62 | class PinsClass 63 | { 64 | public: 65 | PinsClass(); 66 | 67 | Pin* getPin(int8_t pos); 68 | void setPinName(int8_t pos, String name); 69 | void activatePin(int8_t pos, String name); 70 | void setPinActive(int8_t pos, bool active); 71 | bool isPinActive(int8_t pos); 72 | uint8_t getPinId(int8_t pos); 73 | void resetPins(); 74 | 75 | private: 76 | Pin _pins[5]; 77 | }; 78 | 79 | extern PinsClass Pins; 80 | 81 | 82 | #endif //TEENSYCMAKE_PINS_H 83 | -------------------------------------------------------------------------------- /Firmware/TouchWheel.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #ifndef _TEENSYCMAKE_TOUCHWHEEL_H_ 20 | #define _TEENSYCMAKE_TOUCHWHEEL_H_ 21 | 22 | #include 23 | #include 24 | #include "Appfruits_QTouch.h" 25 | 26 | class TouchWheel: public Appfruits_QTouch_Delegate 27 | { 28 | public: 29 | typedef enum Direction { 30 | Left = 0, 31 | Top = 1, 32 | Right = 2, 33 | Bottom = 3 34 | } Direction; 35 | 36 | TouchWheel(Appfruits_QTouch* driver); 37 | 38 | void begin(); 39 | void update(); 40 | bool isButtonReleased(Direction direction); 41 | bool isSliding(); 42 | int8_t getSliderDelta(); 43 | uint8_t getSliderPosition(); 44 | 45 | private: 46 | bool _sliding; 47 | bool _touching; 48 | uint8_t _sliderDelta; 49 | uint8_t _sliderPos; 50 | Appfruits_QTouch* _driver; 51 | 52 | void resetStates(); 53 | 54 | uint32_t _button[4]; 55 | uint32_t _touchStart; 56 | 57 | virtual void onTouchLeftButtonPressed(uint32_t duration) override; 58 | virtual void onTouchTopButtonPressed(uint32_t duration) override; 59 | virtual void onTouchRightButtonPressed(uint32_t duration) override; 60 | virtual void onTouchBottomButtonPressed(uint32_t duration) override; 61 | virtual void onSlider(uint8_t sliderPos, int8_t sliderDelta) override; 62 | virtual void onTouchDown() override; 63 | virtual void onTouchUp(uint32_t duration) override; 64 | }; 65 | 66 | 67 | #endif //_TEENSYCMAKE_TOUCHWHEEL_H_ 68 | -------------------------------------------------------------------------------- /Firmware/I2CScannerSceneController.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #ifndef TEENSYCMAKE_I2CSCANNER_H 20 | #define TEENSYCMAKE_I2CSCANNER_H 21 | 22 | #include "SceneController.h" 23 | #include "ProgressBar.h" 24 | #include "PinDescriptionView.h" 25 | #include "MenuView.h" 26 | #include "MenuItemView.h" 27 | #include "LabelView.h" 28 | #include "MenuItemButtonView.h" 29 | 30 | class I2CScannerSceneController: public SceneController, MenuItemViewDelegate 31 | { 32 | public: 33 | I2CScannerSceneController(); 34 | ~I2CScannerSceneController(); 35 | 36 | virtual void loop() override; 37 | 38 | public: 39 | virtual void onWillAppear() override; 40 | virtual String getName() override; 41 | 42 | private: 43 | typedef enum State { 44 | PinInfo = 0, 45 | Scanning = 1, 46 | Results = 2 47 | } State; 48 | 49 | ProgressBar _progressBar; 50 | PinDescriptionView _pinDescriptionView; 51 | MenuView _menuView; 52 | LabelView _scanningLabel; 53 | MenuItemButtonView _button; 54 | uint8_t _currentAddress; 55 | LabelView _devicesFoundLabel; 56 | uint8_t _devicesFound[8]; 57 | uint8_t _numDevicesFound; 58 | MenuView _resultList; 59 | I2CScannerSceneController::State _state; 60 | 61 | virtual void menuItemViewTriggered(MenuItemView *menuItemView) override; 62 | void startScan(); 63 | void endScan(); 64 | bool scanAddress(uint8_t address); 65 | void setState(I2CScannerSceneController::State state); 66 | 67 | void updateUI(); 68 | }; 69 | 70 | 71 | #endif //TEENSYCMAKE_I2CSCANNER_H 72 | -------------------------------------------------------------------------------- /Firmware/ColorTheme.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #include 20 | #include 21 | #include "ColorTheme.h" 22 | #include "Application.h" 23 | 24 | ColorTheme::ColorTheme(): 25 | _colors({{RGB565(255,111,9),RGB565(255,182,131),RGB565(255,161, 94),RGB565(255,106,0),RGB565(255,106,0)}, 26 | {RGB565(193,179,128),RGB565(146,143,132),RGB565(167,159,131),RGB565(237,214,132),RGB565(254,218, 86)}, 27 | {RGB565(183,181,193),RGB565( 80, 65,186),RGB565(132,123,192),RGB565(114,112,133),RGB565( 83, 81,102)}, 28 | {RGB565( 59,138,127),RGB565(135,164,160),RGB565(107,158,151),RGB565( 28,131,117),RGB565( 6,115,100)} 29 | }), 30 | _textColors({RGB565(255,255,255),RGB565(255,255,255),RGB565(240,240,240),RGB565(40,40,40),RGB565(0,0,0)}), 31 | _backgroundColor(RGB565(0,0,0)) 32 | { 33 | } 34 | 35 | uint16_t ColorTheme::getPrimaryColor(ColorTheme::Shade shade) 36 | { 37 | return _colors[0][shade]; 38 | } 39 | 40 | uint16_t ColorTheme::getSecondaryColor1(ColorTheme::Shade shade) 41 | { 42 | return _colors[1][shade]; 43 | } 44 | 45 | uint16_t ColorTheme::getSecondaryColor2(ColorTheme::Shade shade) 46 | { 47 | return _colors[2][shade]; 48 | } 49 | 50 | uint16_t ColorTheme::getComplementColor(ColorTheme::Shade shade) 51 | { 52 | return _colors[3][shade]; 53 | } 54 | 55 | uint16_t ColorTheme::getBackgroundColor(ColorTheme::Shade shade) 56 | { 57 | return _backgroundColor; 58 | } 59 | 60 | uint16_t ColorTheme::getTextColor(ColorTheme::Shade shade) 61 | { 62 | return _textColors[shade]; 63 | } 64 | -------------------------------------------------------------------------------- /Firmware/LabelView.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #include "LabelView.h" 20 | #include "Application.h" 21 | 22 | LabelView::LabelView(String text, uint16_t x, uint16_t y, uint16_t width, uint16_t height): View(x,y,width,height) 23 | { 24 | _font = ARIAL_8; 25 | _textColor = RGB565(255,255,255); 26 | _textAlign = TEXTALIGN_LEFT; 27 | _text = text; 28 | } 29 | 30 | void LabelView::setText(String text) 31 | { 32 | _text = text; 33 | setNeedsDisplay(); 34 | } 35 | 36 | void LabelView::draw() 37 | { 38 | display.fillRect(_frame,RGB565(0,0,0)); 39 | 40 | display.setTextColor(_textColor); 41 | display.setFont(_font); 42 | 43 | int x = _frame.x; 44 | int y = _frame.y + ((_frame.height - display.calcTextHeight(_text,_font)) / 2); 45 | 46 | if (_textAlign == TEXTALIGN_CENTERED) 47 | { 48 | x = _frame.x + ((_frame.width - display.calcTextWidth(_text,_font)) / 2); 49 | } 50 | else if (_textAlign == TEXTALIGN_RIGHT) 51 | { 52 | x = _frame.right() - display.calcTextWidth(_text,_font); 53 | } 54 | 55 | display.setCursor(x,y); 56 | display.print(_text); 57 | } 58 | 59 | void LabelView::setTextAlign(uint8_t textAlign) 60 | { 61 | if (_textAlign == textAlign) return; 62 | _textAlign = textAlign; 63 | setNeedsDisplay(); 64 | } 65 | 66 | void LabelView::setTextColor(uint16_t color) 67 | { 68 | if (_textColor == color) return; 69 | _textColor = color; 70 | setNeedsDisplay(); 71 | } 72 | 73 | void LabelView::setFont(uint8_t font) 74 | { 75 | if (_font == font) return; 76 | _font = font; 77 | setNeedsDisplay(); 78 | } 79 | -------------------------------------------------------------------------------- /Firmware/Icon.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #include "Icon.h" 20 | 21 | Icon::Icon(const uint8_t* pixelData): 22 | _pixelData(pixelData) 23 | { 24 | 25 | } 26 | 27 | 28 | uint8_t Icon::getWidth() 29 | { 30 | return ICON_WIDTH; 31 | } 32 | 33 | uint8_t Icon::getHeight() 34 | { 35 | return ICON_HEIGHT; 36 | } 37 | 38 | 39 | const uint8_t *Icon::getPixelData() 40 | { 41 | return _pixelData; 42 | } 43 | 44 | const uint8_t pixelDataSlopeRaising[] = { 45 | 0,0,0,0,0,1,0,0, 46 | 0,0,0,0,1,1,1,0, 47 | 0,0,0,1,0,1,0,1, 48 | 0,0,0,0,0,1,0,0, 49 | 0,0,0,0,0,1,0,0, 50 | 0,0,0,0,0,1,0,0, 51 | 1,1,1,1,1,1,0,0, 52 | 0,0,0,0,0,0,0,0 53 | }; 54 | Icon SlopeRaising(&pixelDataSlopeRaising[0]); 55 | 56 | const uint8_t pixelDataSlopeFalling[] = { 57 | 0,0,0,0,0,0,0,0, 58 | 1,1,1,1,1,1,0,0, 59 | 0,0,0,0,0,1,0,0, 60 | 0,0,0,0,0,1,0,0, 61 | 0,0,0,0,0,1,0,0, 62 | 0,0,0,1,0,1,0,1, 63 | 0,0,0,0,1,1,1,0, 64 | 0,0,0,0,0,1,0,0 65 | }; 66 | Icon SlopeFalling(&pixelDataSlopeFalling[0]); 67 | 68 | const uint8_t pixelDataSlopeBoth[] = { 69 | 0,0,0,0,0,0,0,0, 70 | 0,0,0,0,0,0,0,0, 71 | 1,0,0,1,1,0,0,1, 72 | 0,1,1,0,0,1,1,0, 73 | 0,1,1,0,0,1,1,0, 74 | 1,0,0,1,1,0,0,1, 75 | 0,0,0,0,0,0,0,0, 76 | 0,0,0,0,0,0,0,0 77 | }; 78 | Icon SlopeBoth(&pixelDataSlopeBoth[0]); 79 | 80 | /* 81 | const uint8_t[8][8] Dummy = { 82 | {0,0,0,0,0,0,0,0}, 83 | {0,0,0,0,0,0,0,0}, 84 | {0,0,0,0,0,0,0,0}, 85 | {0,0,0,0,0,0,0,0}, 86 | {0,0,0,0,0,0,0,0}, 87 | {0,0,0,0,0,0,0,0}, 88 | {0,0,0,0,0,0,0,0}, 89 | {0,0,0,0,0,0,0,0} 90 | };*/ -------------------------------------------------------------------------------- /Firmware/MenuItemView.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #ifndef _TEENSYCMAKE_MENUITEMVIEW_H_ 20 | #define _TEENSYCMAKE_MENUITEMVIEW_H_ 21 | 22 | #include "View.h" 23 | #include "Animation.h" 24 | #include "MenuView.h" 25 | 26 | class MenuItemView; 27 | 28 | class MenuItemViewDelegate 29 | { 30 | public: 31 | virtual void menuItemViewTriggered(MenuItemView* menuItemView) {}; 32 | 33 | virtual void menuItemViewValueChanged(MenuItemView* menuItemView, float value) {}; 34 | }; 35 | 36 | class MenuItemView: public View 37 | { 38 | public: 39 | MenuItemView(); 40 | MenuItemView(String title); 41 | ~MenuItemView() {}; 42 | 43 | virtual void draw(); 44 | void popLeft(bool animated); 45 | void pushLeft(bool animated); 46 | String getTitle(); 47 | void setTitle(String title); 48 | 49 | uint8_t getTag(); 50 | void setTag(uint8_t tag); 51 | void* getObject(); 52 | void setObject(void* object); 53 | 54 | void setSelected(bool selected); 55 | bool isSelected(); 56 | 57 | virtual bool needsFocus(); 58 | virtual void onClicked(); 59 | 60 | void setMenuView(MenuView* menuView); 61 | MenuView* getMenuView(); 62 | 63 | MenuItemViewDelegate* getDelegate(); 64 | void setDelegate(MenuItemViewDelegate* delegate); 65 | 66 | protected: 67 | MenuItemViewDelegate* _delegate; 68 | String _title; 69 | void* _object; 70 | int _tag; 71 | bool _selected; 72 | MenuView* _menuView; 73 | 74 | public: 75 | virtual String getDescription() override; 76 | 77 | virtual void setNeedsDisplay() override; 78 | }; 79 | 80 | 81 | #endif //_TEENSYCMAKE_MENUITEMVIEW_H_ 82 | -------------------------------------------------------------------------------- /Firmware/LightBoxSceneController.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #ifndef TEENSYCMAKE_LIGHTBOXSCENECONTROLLER_H 20 | #define TEENSYCMAKE_LIGHTBOXSCENECONTROLLER_H 21 | 22 | #include "SceneController.h" 23 | #include "MenuItemView.h" 24 | #include "PinDescriptionView.h" 25 | #include "MenuItemButtonView.h" 26 | #include "MenuItemWheelView.h" 27 | #include "SoftI2CMaster.h" 28 | 29 | class LightBoxSceneController : public SceneController, MenuItemViewDelegate 30 | { 31 | typedef struct LightboxSettings { 32 | uint8_t r; 33 | uint8_t g; 34 | uint8_t b; 35 | uint8_t currentSlot; 36 | float scale; 37 | } LightboxSettings; 38 | 39 | public: 40 | LightBoxSceneController(); 41 | ~LightBoxSceneController(); 42 | 43 | virtual void loop() override; 44 | 45 | public: 46 | virtual void onWillAppear() override; 47 | virtual String getName() override; 48 | 49 | private: 50 | PinDescriptionView _pinDescriptionView; 51 | MenuView _menuView; 52 | bool _intro; 53 | MenuView _settingsMenuView; 54 | MenuItemButtonView _button; 55 | LightboxSettings _settings; 56 | MenuItemWheelView* _scaleMenuItem; 57 | MenuItemWheelView* _rMenuItem; 58 | MenuItemWheelView* _gMenuItem; 59 | MenuItemWheelView* _bMenuItem; 60 | MenuItemWheelView* _currentSlotMenuItem; 61 | SoftI2CMaster _i2c; 62 | 63 | virtual void menuItemViewTriggered(MenuItemView *menuItemView) override; 64 | 65 | void updateUI(); 66 | void sendData(); 67 | 68 | virtual void menuItemViewValueChanged(MenuItemView *menuItemView, float value) override; 69 | }; 70 | 71 | 72 | #endif //TEENSYCMAKE_LIGHTBOXSCENECONTROLLER_H 73 | -------------------------------------------------------------------------------- /Firmware/ProgressBar.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #include "ProgressBar.h" 20 | #include "Application.h" 21 | 22 | ProgressBar::ProgressBar(uint16_t x, uint16_t y, uint16_t width, uint16_t height): 23 | View(x,y,width,height) 24 | { 25 | setMinValue(0); 26 | setMaxValue(1); 27 | _value = 0; 28 | } 29 | 30 | void ProgressBar::draw() 31 | { 32 | display.drawRoundRect(_frame.x,_frame.y,_frame.width,_frame.height,3,Application.getTheme()->getPrimaryColor()); 33 | 34 | float width = (_frame.width * this->_value)-1; 35 | if (width > _frame.width) width = _frame.width; 36 | if (width < 6) width = 6; 37 | LOG_VALUE("Progress-Bar Width",width); 38 | display.fillRoundRect(_frame.x+1,_frame.y,(uint8_t)width,_frame.height,3,Application.getTheme()->getPrimaryColor()); 39 | //display.fillRect(x+1,_frame.y+1,4,_frame.height-2,ST7735_CYAN); 40 | } 41 | 42 | String ProgressBar::getDescription() 43 | { 44 | return "Progressbar"; 45 | } 46 | 47 | void ProgressBar::setMinValue(float minValue) 48 | { 49 | _minValue = minValue; 50 | } 51 | 52 | void ProgressBar::setMaxValue(float maxValue) 53 | { 54 | _maxValue = maxValue; 55 | } 56 | 57 | float ProgressBar::getValue() 58 | { 59 | return _value; 60 | } 61 | 62 | void ProgressBar::setValue(float value) 63 | { 64 | if (this->_value == value) return; 65 | if (value > _maxValue) value = _maxValue; 66 | if (value < _minValue) value = _minValue; 67 | 68 | this->_value = value; 69 | 70 | setNeedsDisplay(); 71 | } 72 | 73 | void ProgressBar::setLimits(float minValue, float maxValue) 74 | { 75 | setMinValue(minValue); 76 | setMaxValue(maxValue); 77 | } 78 | -------------------------------------------------------------------------------- /Firmware/ScopeView.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #ifndef TEENSYCMAKE_SCOPEVIEW_H 20 | #define TEENSYCMAKE_SCOPEVIEW_H 21 | 22 | #include "View.h" 23 | 24 | //TODO: 16-bit might be too less for larger memories (numSamples, cursor) 25 | 26 | class Record 27 | { 28 | public: 29 | Record() { 30 | memset(samples,0,sizeof(int)*128); 31 | state = 0; 32 | } 33 | 34 | void reset() { endPos = 0; startPos = 0; triggerPos = 0; state = 0; todo = 0;}; 35 | 36 | int samples[128]; 37 | int startPos; 38 | int triggerPos; 39 | int endPos; 40 | int todo; 41 | int state; 42 | }; 43 | 44 | class ScopeView; 45 | 46 | class ScopeViewDelegate 47 | { 48 | public: 49 | virtual void onPause(ScopeView* scopeView) = 0; 50 | virtual uint16_t getNumberOfSamples() = 0; 51 | virtual int getSampleAtIndex(uint16_t index) = 0; 52 | virtual bool copySamples(uint16_t start, uint16_t length, int* buffer) = 0; 53 | virtual float getSamplesPerSecond() = 0; 54 | virtual Record* getRecord() = 0; 55 | }; 56 | 57 | class ScopeView: public View 58 | { 59 | public: 60 | ScopeView(ScopeViewDelegate* delegate, uint16_t x, uint16_t y, uint16_t width, uint16_t height); 61 | 62 | void setCursor(uint16_t cursor); 63 | uint16_t getCursor(); 64 | 65 | void setDelegate(ScopeViewDelegate* delegate); 66 | void setRecord(Record record); 67 | 68 | private: 69 | uint16_t _cursor; 70 | float _yScale; 71 | ScopeViewDelegate* _delegate; 72 | int _samples[200]; 73 | Record _record; 74 | 75 | public: 76 | Record* _currentRecord; 77 | 78 | public: 79 | virtual void draw() override; 80 | virtual String getDescription() override; 81 | }; 82 | 83 | 84 | #endif //TEENSYCMAKE_SCOPEVIEW_H 85 | -------------------------------------------------------------------------------- /Firmware/StatusBarView.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #include "StatusBarView.h" 20 | #include "Application.h" 21 | #include "Timer.h" 22 | 23 | StatusBarView::StatusBarView() : View(MINX,0,MAXW,25), _timeOut(1000) 24 | { 25 | _charge = 0; 26 | } 27 | 28 | void StatusBarView::setCaption(String caption) 29 | { 30 | _caption = caption; 31 | setNeedsDisplay(); 32 | } 33 | 34 | void StatusBarView::draw() 35 | { 36 | float chargeLevel = battery.stateOfCharge(); 37 | LOG_VALUE("Battery charge level",chargeLevel); 38 | 39 | _charge = 15; 40 | 41 | display.fillRect(_frame.x,_frame.y,_frame.width,_frame.height,ST7735_BLACK); 42 | //display.drawRect(_frame.x + _frame.width - 30 - 2,_frame.y + 2,_frame.x + _frame.width - 2 - 2,_frame.y + _frame.height - 2, ST7735_WHITE); 43 | display.drawRect(104,1,21,8,ST7735_WHITE); 44 | display.drawRect(125,3,1,3,ST7735_WHITE); 45 | display.fillRect(105,2,_charge,6,ST7735_WHITE); 46 | 47 | display.setFont(ARIAL_16); 48 | display.setTextSize(1); 49 | display.setTextColor(ST7735_WHITE); 50 | display.setCursor(2,2); 51 | display.print(_caption); 52 | 53 | int width = 10; 54 | int begin = 64 - (width * 1.5); 55 | 56 | Rect pinMarkFrame = Rect(begin,0,width-1,2); 57 | for (int i=0;i<3;i++) 58 | { 59 | Pin* pin = Pins.getPin(i+1); 60 | if (pin->isActive()) 61 | { 62 | display.fillRect(pinMarkFrame,pin->getColor()); 63 | } 64 | pinMarkFrame.x += width; 65 | } 66 | } 67 | 68 | 69 | void StatusBarView::update() 70 | { 71 | /* if (_timeOut.isTimedOut()) 72 | { 73 | setNeedsDisplay(); 74 | _timeOut.reset(); 75 | }*/ 76 | 77 | View::update(); 78 | } 79 | 80 | String StatusBarView::getDescription() 81 | { 82 | return "StatusBarView"; 83 | } 84 | -------------------------------------------------------------------------------- /Firmware/MenuView.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #ifndef _TEENSYCMAKE_MENUVIEW_H_ 20 | #define _TEENSYCMAKE_MENUVIEW_H_ 21 | 22 | #include 23 | #include "View.h" 24 | #include "StackArray.h" 25 | 26 | class MenuItemView; 27 | 28 | class MenuViewDelegate 29 | { 30 | public: 31 | virtual void menuViewItemClicked(MenuItemView* menuItemView) = 0; 32 | }; 33 | 34 | class MenuView: public View 35 | { 36 | public: 37 | MenuView(); 38 | MenuView(String name, uint16_t x, uint16_t y, uint16_t width, uint16_t height, bool vertical=true); 39 | ~MenuView(); 40 | virtual void draw(); 41 | void layout(); 42 | 43 | virtual void handleEvents() override; 44 | 45 | void addMenuItem(MenuItemView* view); 46 | void setSelectedItemIndex(uint8_t selectedItemIndex); 47 | uint8_t getSelectedItemIndex(); 48 | 49 | String getName(); 50 | void setName(String name); 51 | 52 | void popLeft(bool animated); 53 | void pushLeft(bool animated); 54 | void popRight(bool animated); 55 | void pushRight(bool animated); 56 | 57 | int getNumberOfItems(); 58 | 59 | void setDelegate(MenuViewDelegate* delegate); 60 | MenuViewDelegate* getDelegate(); 61 | 62 | private: 63 | StackArray _menuItems; 64 | int32_t _scrollOffset; 65 | uint8_t _selectedItemIndex; 66 | String _name; 67 | float _touchWheelOffset; 68 | MenuViewDelegate* _delegate; 69 | bool _vertical; 70 | 71 | public: 72 | virtual String getDescription() override; 73 | 74 | protected: 75 | virtual void animationUpdated(Animation *animation, float currentValue, float timeLeft) override; 76 | virtual void setScrollOffset(int32_t offset, bool animated=true); 77 | virtual Rect itemViewRect(int itemIndex); 78 | }; 79 | 80 | 81 | #endif //_TEENSYCMAKE_MENUVIEW_H_ 82 | -------------------------------------------------------------------------------- /Firmware/AnalogOutSceneController.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #include "AnalogOutSceneController.h" 20 | #include "MenuItemEnumView.h" 21 | #include "MenuItemWheelView.h" 22 | 23 | AnalogOutSceneController::AnalogOutSceneController(): 24 | SceneController(), 25 | _waveformView(MINX,MINY,MAXW,55), 26 | _menuView("Options",MINX,MAXY-60,MAXW,58) 27 | { 28 | MenuItemEnumView* frequencyControl = new MenuItemEnumView("Waveform", this); 29 | frequencyControl->addItem(0,"Steady"); 30 | frequencyControl->addItem(1,"Sinus"); 31 | frequencyControl->addItem(2,"Cosinus"); 32 | frequencyControl->addItem(3,"Square"); 33 | 34 | MenuItemWheelView* dutyControl = new MenuItemWheelView("Frequency", this); 35 | dutyControl->setLimits(0,1000); 36 | dutyControl->setScale(0.1f); 37 | dutyControl->setValue(1); 38 | 39 | _menuView.addMenuItem(frequencyControl); 40 | _menuView.addMenuItem(dutyControl); 41 | _menuView.setVisible(true); 42 | _menuView.setSelectedItemIndex(1); 43 | } 44 | 45 | void AnalogOutSceneController::onWillAppear() 46 | { 47 | SceneController::onWillAppear(); 48 | 49 | _menuView.setFocus(); 50 | Application.getStatusBar()->setCaption("Analog Out"); 51 | _waveformView.setNeedsDisplay(); 52 | 53 | //Activate pin 54 | // pinMode(EXT_PIN_DAC, OUTPUT); 55 | // analogWrite(EXT_PIN_DAC, _duty * 255); 56 | 57 | Pins.activatePin(PIN_DAC,true); 58 | } 59 | 60 | void AnalogOutSceneController::loop() 61 | { 62 | SceneController::loop(); 63 | 64 | _waveformView.update(); 65 | _menuView.update(); 66 | } 67 | 68 | String AnalogOutSceneController::getName() 69 | { 70 | return "Analog-Out"; 71 | } 72 | 73 | void AnalogOutSceneController::menuItemViewValueChanged(MenuItemView *menuItemView, float value) 74 | { 75 | if (menuItemView->getTitle() == "Frequency") 76 | { 77 | _waveformView.setXScale(value); 78 | } 79 | } -------------------------------------------------------------------------------- /Firmware/PinDescriptionView.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #include "PinDescriptionView.h" 20 | #include "Application.h" 21 | 22 | PinDescriptionView::PinDescriptionView(): 23 | View(MINX,MINY,MAXW,MAXH) 24 | { 25 | 26 | } 27 | 28 | PinDescriptionView::PinDescriptionView(uint16_t x, uint16_t y, uint16_t width, uint16_t height): View (x,y,width,height) 29 | { 30 | 31 | } 32 | 33 | void PinDescriptionView::draw() 34 | { 35 | const int segmentWidth = 20; 36 | const int segmentHeight = 10; 37 | const int gap = 1; 38 | const int numPins = 5; 39 | const int pinHeight = 20; 40 | 41 | //Draw Intro Text 42 | display.setCursor(0,_frame.y); 43 | display.setFont(ARIAL_8); 44 | display.setTextColor(RGB565(255,255,255)); 45 | display.setTextWrap(true); 46 | display.print(_text); 47 | 48 | int x = (MAXW - ((segmentWidth * numPins) + (gap * (numPins-1)))) / 2; 49 | 50 | for (uint8_t i=0;i<5;i++) 51 | { 52 | Pin* pin = Pins.getPin(i); 53 | if (pin->getColor() == 0) 54 | { 55 | display.drawRoundRect(x,_frame.bottom()-segmentHeight,segmentWidth,segmentHeight,1,RGB565(255,255,255)); 56 | } 57 | else 58 | { 59 | display.fillRoundRect(x,_frame.bottom()-segmentHeight,segmentWidth,segmentHeight,1,pin->getColor()); 60 | } 61 | 62 | display.drawFastVLine(x+(segmentWidth/2),_frame.bottom()-segmentHeight-pinHeight,pinHeight,RGB565(249,209,106)); 63 | 64 | x += segmentWidth + gap; 65 | } 66 | 67 | //In Landscape X = Y and Y = X, therefore X-coords from before are now the Y coords 68 | display.setOrientation(LANDSCAPE_LEFT); 69 | display.setFont(ARIAL_8); 70 | x = (MAXH-_frame.height)+(segmentHeight + pinHeight + 5); 71 | int y = (MAXW - ((segmentWidth * numPins) + (gap * (numPins-1)))) / 2; 72 | y += 6; //Text height 73 | for (uint8_t i=0;i<5;i++) 74 | { 75 | Pin* pin = Pins.getPin(i); 76 | if (pin->isActive()) 77 | { 78 | display.setCursor(x,y); 79 | display.print(pin->getName()); 80 | } 81 | 82 | y += segmentWidth + gap; 83 | } 84 | display.setOrientation(PORTRAIT); 85 | } 86 | 87 | void PinDescriptionView::setText(String text) 88 | { 89 | _text = text; 90 | setNeedsDisplay(); 91 | } -------------------------------------------------------------------------------- /Firmware/MainMenuSceneController.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #ifndef _TEENSYCMAKE_MAINMENUSCENECONTROLLER_H_ 20 | #define _TEENSYCMAKE_MAINMENUSCENECONTROLLER_H_ 21 | 22 | #include "SceneController.h" 23 | #include "StatusBarView.h" 24 | #include "MenuView.h" 25 | #include "AnalogOutSceneController.h" 26 | #include "ClockOutSceneController.h" 27 | #include "I2CScannerSceneController.h" 28 | #include "ScopeSceneController.h" 29 | #include "LightBoxSceneController.h" 30 | 31 | class MenuAction 32 | { 33 | public: 34 | MenuAction(MenuView* nextMenu, bool forward) 35 | { 36 | _nextMenu = nextMenu; 37 | _forward = forward; 38 | } 39 | 40 | MenuAction(SceneController* nexScene) 41 | { 42 | _nextScene = _nextScene; 43 | _nextMenu = NULL; 44 | } 45 | 46 | MenuView* getNextMenu() { return _nextMenu; }; 47 | bool isForward() { return _forward; }; 48 | SceneController* getNextScene() { return _nextScene; }; 49 | 50 | private: 51 | MenuView* _nextMenu; 52 | bool _forward; 53 | SceneController* _nextScene; 54 | }; 55 | 56 | class MainMenuSceneController : public SceneController, MenuItemViewDelegate 57 | { 58 | public: 59 | MainMenuSceneController(); 60 | virtual void loop(); 61 | 62 | private: 63 | void setCurrentMenuView(MenuView* menuView, bool forward); 64 | MenuView* getCurrentMenuView(); 65 | 66 | private: 67 | MenuView _mainMenuView; 68 | MenuView _settingsMenuView; 69 | MenuView* _currentMenuView; 70 | View _menuBackgroundView; 71 | float _selectedItem; 72 | AnalogOutSceneController* _analogOutputSceneController; 73 | ClockOutSceneController* _clockOutSceneController; 74 | I2CScannerSceneController* _i2cScannerSceneController; 75 | ScopeSceneController* _scopeSceneController; 76 | LightBoxSceneController* _lightboxSceneController; 77 | 78 | virtual void menuItemViewTriggered(MenuItemView *menuItemView); 79 | 80 | public: 81 | virtual void onWillAppear() override; 82 | 83 | virtual String getName() override; 84 | 85 | private: 86 | virtual void menuItemViewValueChanged(MenuItemView *menuItemView, float value) override; 87 | }; 88 | 89 | 90 | #endif //_TEENSYCMAKE_MAINMENUSCENECONTROLLER_H_ 91 | -------------------------------------------------------------------------------- /Firmware/ScopeView.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #include "ScopeView.h" 20 | #include "Application.h" 21 | 22 | ScopeView::ScopeView(ScopeViewDelegate* delegate, uint16_t x, uint16_t y, uint16_t width, uint16_t height): 23 | View(x,y,width,height), 24 | _yScale(0.085f), 25 | _cursor(0), 26 | _delegate(delegate) 27 | { 28 | 29 | } 30 | 31 | void ScopeView::setCursor(uint16_t cursor) 32 | { 33 | if (_cursor == cursor) return; 34 | _cursor = cursor; 35 | 36 | setNeedsDisplay(); 37 | } 38 | 39 | uint16_t ScopeView::getCursor() 40 | { 41 | return _cursor; 42 | } 43 | 44 | void ScopeView::draw() 45 | { 46 | View::draw(); 47 | 48 | Record* record = this->_delegate->getRecord(); 49 | 50 | display.fillRect(_frame.x,_frame.y,_frame.width,_frame.height,Application.getTheme()->getBackgroundColor()); 51 | 52 | int yPos = _frame.bottom(); 53 | for (int s=0;s<=4;s++) 54 | { 55 | int y = (1023.0f/3.3f) * s * _yScale; 56 | display.drawFastHLine(_frame.x,yPos - y,_frame.width,Application.getTheme()->getSecondaryColor1()); 57 | } 58 | display.drawFastHLine(_frame.x,yPos+1,_frame.width,Application.getTheme()->getSecondaryColor1()); 59 | 60 | int x; 61 | int y; 62 | int lastY; 63 | int lastX; 64 | for (int i=0;i<128;i++) 65 | { 66 | x = i; 67 | y = record->samples[i] * _yScale; 68 | 69 | if (i > 0) 70 | { 71 | display.drawLine(lastX,yPos-lastY,x,yPos-y,Application.getTheme()->getPrimaryColor()); 72 | } 73 | 74 | lastY = y; 75 | lastX = x; 76 | } 77 | 78 | display.setFont(ARIAL_8); 79 | display.setCursor(0,MINY); 80 | display.print("Start:"); 81 | display.println(record->startPos); 82 | display.print("End:"); 83 | display.println(record->endPos); 84 | 85 | display.drawIcon(&SlopeFalling,40,40,ST7735_WHITE); 86 | } 87 | 88 | String ScopeView::getDescription() 89 | { 90 | return "ScopeView"; 91 | } 92 | 93 | void ScopeView::setDelegate(ScopeViewDelegate *delegate) 94 | { 95 | _delegate = delegate; 96 | } 97 | 98 | void ScopeView::setRecord(Record record) 99 | { 100 | _record = record; 101 | setNeedsDisplay(); 102 | } 103 | -------------------------------------------------------------------------------- /Firmware/View.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #ifndef _VIEW_H_ 20 | #define _VIEW_H_ 21 | 22 | #include "Arduino.h" 23 | #include "Animation.h" 24 | #include "Object.h" 25 | 26 | struct Rect 27 | { 28 | public: 29 | Rect() {}; 30 | Rect(int x, int y, int w, int h) { this->x=x; this->y=y; this->width=w; this->height=h;}; 31 | 32 | int midY() { return (y + height)/2; }; 33 | int midX() { return (x + width)/2; }; 34 | int right() { return (x + width); }; 35 | int bottom() { return (y + height); }; 36 | int top() { return (y); }; 37 | 38 | int x; 39 | int y; 40 | int width; 41 | int height; 42 | }; 43 | 44 | #define MINX 0 45 | #define MAXX 128 46 | #define MINY 25 47 | #define MAXY 160 48 | #define MAXH (MAXY-MINY) 49 | #define MAXW (MAXX-MINX) 50 | 51 | class View: public AnimatableObject, Object 52 | { 53 | public: 54 | View(); 55 | ~View(); 56 | View(uint16_t x, uint16_t y, uint16_t width, uint16_t height); 57 | View(Rect frame); 58 | 59 | //Dimensions 60 | void setFrame(Rect frame); 61 | void setFrame(uint16_t x, uint16_t y, uint16_t width, uint16_t height); 62 | Rect& getFrame(); 63 | Rect getScreenFrame(); 64 | 65 | //Display 66 | virtual void draw(); 67 | virtual void update(); 68 | virtual void layout(); 69 | void setBackgroundColor(uint16_t backgroundColor); 70 | void setOpaque(bool opaque); 71 | 72 | virtual void setNeedsDisplay(); 73 | void didDraw(); 74 | 75 | //Visibility 76 | bool isVisible(); 77 | void setVisible(bool visible=true); 78 | 79 | //Event handling 80 | void setFocus(); 81 | bool hasFocus(); 82 | virtual void handleEvents(); 83 | 84 | virtual void onTouchWheelLeftClicked(uint32_t duration); 85 | virtual void onTouchWheelTopClicked(uint32_t duration); 86 | virtual void onTouchWheelRightClicked(uint32_t duration); 87 | virtual void onTouchWheelBottomClicked(uint32_t duration); 88 | 89 | protected: 90 | virtual void animationUpdated(Animation *animation, float currentValue, float timeLeft) override; 91 | 92 | protected: 93 | Rect _frame; 94 | bool _visible; 95 | bool _opaque; 96 | uint16_t _backgroundColor; 97 | bool _needsDisplay; 98 | 99 | public: 100 | virtual String getDescription() override; 101 | }; 102 | 103 | #endif 104 | -------------------------------------------------------------------------------- /Firmware/PWMPreviewView.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #include "PWMPreviewView.h" 20 | #include "Application.h" 21 | 22 | #define paddingLeft 5 23 | #define paddingRight 5 24 | #define waveformColor RGB565(24,122,189) 25 | 26 | PWMPreviewView::PWMPreviewView(uint16_t x, uint16_t y, uint16_t width, uint16_t height): View(x,y,width,height) 27 | { 28 | _frequency = 4.0f; 29 | _duty = 0.5f; 30 | _needsDisplay = true; 31 | } 32 | 33 | void PWMPreviewView::draw() 34 | { 35 | LOG("Drawing PWM View"); 36 | 37 | display.fillRect(_frame.x,_frame.y,_frame.width,_frame.height,Application.getTheme()->getBackgroundColor()); 38 | 39 | //display.drawFastHLine(_frame.x,_frame.bottom(),_frame.width,ST7735_CYAN); 40 | 41 | uint16_t lineColor = Application.getTheme()->getSecondaryColor2(); 42 | 43 | if (_duty <= 0.0f) 44 | { 45 | display.drawFastHLine(_frame.x+paddingLeft,_frame.bottom()-1,_frame.width-paddingLeft-paddingRight,lineColor); 46 | } 47 | else if (_duty >= 1.0f) 48 | { 49 | display.drawFastVLine(_frame.x+paddingLeft,_frame.y,_frame.height-1,lineColor); 50 | display.drawFastHLine(_frame.x+paddingLeft,_frame.y,_frame.width-paddingLeft-paddingRight,lineColor); 51 | display.drawFastVLine(_frame.x+_frame.width-paddingRight,_frame.y,_frame.height-1,lineColor); 52 | } 53 | else 54 | { 55 | float segmentWidth = (float)(_frame.width-paddingLeft-paddingRight)/_frequency; 56 | for (float i=0;i<_frequency;i++) 57 | { 58 | int x = _frame.x + paddingLeft + (i*segmentWidth); 59 | int x1 = _frame.x + paddingLeft + (i*segmentWidth) + (segmentWidth*_duty); 60 | int x2 = x + segmentWidth; 61 | 62 | display.drawFastVLine(x,_frame.y,_frame.height-1,lineColor); 63 | display.drawFastHLine(x,_frame.y,x1-x,lineColor); 64 | if (x1 != x) 65 | { 66 | display.drawFastVLine(x1,_frame.y,_frame.height,lineColor); 67 | } 68 | display.drawFastHLine(x1,_frame.bottom()-1,x2-x1,lineColor); 69 | } 70 | } 71 | } 72 | 73 | void PWMPreviewView::setFrequency(float frequency) 74 | { 75 | if (_frequency == frequency) return; 76 | 77 | //_frequency = frequency; 78 | setNeedsDisplay(); 79 | } 80 | 81 | void PWMPreviewView::setDuty(float duty) 82 | { 83 | if (duty == _duty) return; 84 | 85 | _duty = duty; 86 | setNeedsDisplay(); 87 | } 88 | 89 | String PWMPreviewView::getDescription() 90 | { 91 | return "PWMPreviewView"; 92 | } 93 | -------------------------------------------------------------------------------- /Firmware/ScopeSceneController.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #ifndef TEENSYCMAKE_SCOPESCENECONTROLLER_H 20 | #define TEENSYCMAKE_SCOPESCENECONTROLLER_H 21 | 22 | #include "SceneController.h" 23 | #include "ScopeView.h" 24 | #include "LabelView.h" 25 | #include "MenuView.h" 26 | #include "MenuItemWheelView.h" 27 | #include "MenuItemEnumView.h" 28 | 29 | #define MAX_SAMPLES 1000 30 | 31 | class ScopeSceneController: public SceneController, ScopeViewDelegate, MenuItemViewDelegate 32 | { 33 | public: 34 | ScopeSceneController(); 35 | 36 | typedef enum Slope { 37 | Raising = 0, 38 | Falling = 1, 39 | Both = 2, 40 | Off = 3 41 | } Slope; 42 | 43 | private: 44 | ScopeView _scopeView; 45 | MenuView _menuView; 46 | MenuItemWheelView* _xScaleItemView; 47 | MenuItemWheelView* _xPosItemView; 48 | MenuItemEnumView* _triggerItemView; 49 | int _samples[MAX_SAMPLES]; 50 | uint16_t _numSamples; 51 | bool _paused; 52 | IntervalTimer _timer; 53 | float _samplesPerSecond; 54 | uint32_t _lastTick; 55 | Record _record; 56 | LabelView _labelView; 57 | int _numTriggers; 58 | int _triggerSlot; 59 | int _lastTriggerSlot; 60 | bool _triggered; 61 | int _samplesInTrigger; 62 | int _currentTriggerSlot; 63 | int _triggers[100]; 64 | int _previousSample; 65 | float _xScale; 66 | float _xPos; 67 | uint8_t _triggerSlope; 68 | 69 | public: 70 | virtual void loop() override; 71 | virtual String getName() override; 72 | virtual void onWillAppear() override; 73 | virtual void onWillDisappear() override; 74 | void copySamples(int start, int end, Record* record); 75 | bool isPaused(); 76 | 77 | void addSample(int value); 78 | 79 | private: 80 | virtual void onPause(ScopeView *scopeView); 81 | 82 | virtual uint16_t getNumberOfSamples(); 83 | 84 | virtual int getSampleAtIndex(uint16_t index); 85 | 86 | virtual bool copySamples(uint16_t start, uint16_t length, int *buffer); 87 | 88 | virtual float getSamplesPerSecond(); 89 | 90 | virtual void xSystemChanged(); 91 | 92 | virtual Record *getRecord(); 93 | 94 | virtual void menuItemViewTriggered(MenuItemView *menuItemView) override; 95 | 96 | virtual void menuItemViewValueChanged(MenuItemView *menuItemView, float value) override; 97 | }; 98 | 99 | 100 | #endif //TEENSYCMAKE_SCOPESCENECONTROLLER_H 101 | -------------------------------------------------------------------------------- /Firmware/ClockOutSceneController.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #include "ClockOutSceneController.h" 20 | #include "MenuItemWheelView.h" 21 | #include "MenuItemEnumView.h" 22 | 23 | ClockOutSceneController::ClockOutSceneController(): 24 | SceneController(), 25 | _menuView("Options",MINX,MAXY-60,MAXW,58), 26 | _pwmPreviewView(MINX,MINY,MAXW,55) 27 | { 28 | MenuItemEnumView* frequencyControl = new MenuItemEnumView("Frequency", this); 29 | frequencyControl->addItem(488,"488 Hz"); 30 | frequencyControl->addItem(1000,"1 KHz"); 31 | frequencyControl->addItem(1000000,"1 MHz"); 32 | frequencyControl->addItem(2000000,"2 MHz"); 33 | frequencyControl->addItem(4000000,"4 MHz"); 34 | frequencyControl->addItem(8000000,"8 MHz"); 35 | frequencyControl->addItem(12000000,"12 MHz"); 36 | 37 | _duty = 0.5f; 38 | MenuItemWheelView* dutyControl = new MenuItemWheelView("Duty", this); 39 | dutyControl->setLimits(0,1); 40 | dutyControl->setScale(0.1f); 41 | dutyControl->setValue(_duty); 42 | 43 | _menuView.addMenuItem(frequencyControl); 44 | _menuView.addMenuItem(dutyControl); 45 | _menuView.setVisible(true); 46 | _menuView.setSelectedItemIndex(1); 47 | 48 | _pwmPreviewView.setFrequency(2); 49 | _pwmPreviewView.setDuty(_duty); 50 | 51 | _firstUpdate = true; 52 | } 53 | 54 | void ClockOutSceneController::onWillAppear() 55 | { 56 | SceneController::onWillAppear(); 57 | 58 | _menuView.setFocus(); 59 | Application.getStatusBar()->setCaption("PWM"); 60 | _pwmPreviewView.setNeedsDisplay(); 61 | 62 | //Activate pin 63 | pinMode(EXT_PIN_3, OUTPUT); 64 | analogWrite(EXT_PIN_3, _duty * 255); 65 | 66 | Pins.activatePin(1,true); 67 | } 68 | 69 | void ClockOutSceneController::loop() 70 | { 71 | SceneController::loop(); 72 | 73 | _pwmPreviewView.update(); 74 | _menuView.update(); 75 | } 76 | 77 | void ClockOutSceneController::menuItemViewValueChanged(MenuItemView *menuItemView, float value) 78 | { 79 | if (menuItemView->getTitle() == "Frequency") 80 | { 81 | _pwmPreviewView.setFrequency(value); 82 | analogWriteFrequency(EXT_PIN_3,value); 83 | analogWrite(EXT_PIN_3,_duty*255); 84 | _frequency = value; 85 | } 86 | else if (menuItemView->getTitle() == "Duty") 87 | { 88 | _pwmPreviewView.setDuty(value); 89 | analogWrite(EXT_PIN_3,value*255); 90 | _duty = value; 91 | } 92 | } 93 | 94 | String ClockOutSceneController::getName() 95 | { 96 | return "Clock-Out"; 97 | } 98 | -------------------------------------------------------------------------------- /Firmware/Appfruits_QTouch.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This is a library for the Atmel QTouch AT42QT2120 3 | * But it should work with other QTouch Devices as well 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #ifndef _APPFRUITS_QTOUCH_ 20 | #define _APPFRUITS_QTOUCH_ 21 | 22 | #if defined(ARDUINO) && ARDUINO >= 100 23 | #include "Arduino.h" 24 | #else 25 | #include "WProgram.h" 26 | #endif 27 | #include 28 | 29 | #define QT2120_I2C_ADDRESS 0x1C 30 | #define QT2120_DETECTION_STATUS 2 31 | #define QT2120_KEYSTATUS_1 3 32 | #define QT2120_KEYSTATUS_2 4 33 | #define QT2120_SLIDERPOS 5 34 | #define QT2120_SLIDER_OPTIONS 14 35 | #define QT2120_DETECT_THRESHOLD 16 36 | #define QT2120_DETECTION_INTEGRATOR 11 37 | 38 | #define QT2120_NUMBER_OF_SAMPLES 1 39 | 40 | class Appfruits_QTouch_Delegate 41 | { 42 | public: 43 | virtual void onTouchLeftButtonPressed(uint32_t duration) {}; 44 | virtual void onTouchTopButtonPressed(uint32_t duration) {}; 45 | virtual void onTouchRightButtonPressed(uint32_t duration) {}; 46 | virtual void onTouchBottomButtonPressed(uint32_t duration) {}; 47 | 48 | virtual void onSlider(uint8_t sliderPos, int8_t sliderDelta) {}; 49 | virtual void onTouchDown() {}; 50 | virtual void onTouchUp(uint32_t duration) {}; 51 | }; 52 | 53 | class Appfruits_QTouch 54 | { 55 | public: 56 | Appfruits_QTouch(uint8_t changePin); 57 | void begin(); 58 | 59 | void enableSlider(void); 60 | void enableWheel(void); 61 | 62 | bool touchDetected(); 63 | bool sliderDetected(); 64 | bool wheelDetected(); 65 | uint8_t sliderPosition(); 66 | int8_t sliderDelta(); 67 | uint8_t wheelPosition(); 68 | int8_t wheelDelta(); 69 | bool isKeyPressed(uint8_t index); 70 | void setDetectThreshold(uint8_t index, uint8_t value); 71 | void setDetectionIntegrator(uint8_t value); 72 | uint8_t getDetectThreshold(uint8_t index); 73 | uint8_t getDetectionIntegrator(); 74 | void setDragging(bool dragging); 75 | bool isDragging(); 76 | uint8_t getLastSliderPos(); 77 | 78 | bool eventAvailable(); 79 | void setDelegate(Appfruits_QTouch_Delegate* delegate); 80 | 81 | private: 82 | Appfruits_QTouch_Delegate* _delegate; 83 | uint8_t _lastSliderPos; 84 | bool _dragging; 85 | uint32_t _dragStartTime; 86 | uint8_t _maxDelta; 87 | uint8_t _changePin; 88 | float _deltas[QT2120_NUMBER_OF_SAMPLES]; 89 | uint8_t _currentDelta; 90 | 91 | bool isBitSet(uint8_t b, uint8_t n); 92 | void writeRegister(uint8_t reg, uint8_t value); 93 | uint16_t readRegister16(uint8_t reg); 94 | uint8_t readRegister8(uint8_t reg); 95 | 96 | }; 97 | 98 | #endif -------------------------------------------------------------------------------- /Firmware/TouchWheel.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #include "TouchWheel.h" 20 | #include "Application.h" 21 | 22 | TouchWheel::TouchWheel(Appfruits_QTouch* driver) 23 | { 24 | this->_driver = driver; 25 | this->_driver->setDelegate(this); 26 | this->resetStates(); 27 | } 28 | 29 | void TouchWheel::begin() 30 | { 31 | this->_driver->begin(); 32 | this->_driver->enableWheel(); 33 | this->_driver->setDetectThreshold(0,41); 34 | this->_driver->setDetectThreshold(1,41); 35 | this->_driver->setDetectThreshold(2,41); 36 | this->_driver->setDetectionIntegrator(3); 37 | } 38 | 39 | void TouchWheel::update() 40 | { 41 | this->resetStates(); 42 | 43 | if (this->_driver->eventAvailable()) 44 | { 45 | if (this->_driver->wheelDetected()) 46 | { 47 | this->_sliderDelta = this->_driver->sliderDelta(); 48 | } 49 | } 50 | } 51 | 52 | void TouchWheel::resetStates() 53 | { 54 | for (int i=0;i<4;i++) 55 | { 56 | this->_button[i] = 0; 57 | } 58 | 59 | this->_sliderDelta = 0; 60 | this->_sliderPos = 0; 61 | } 62 | 63 | bool TouchWheel::isButtonReleased(Direction direction) 64 | { 65 | return (this->_button[direction] > 0); 66 | } 67 | 68 | bool TouchWheel::isSliding() 69 | { 70 | return this->_sliding; 71 | } 72 | 73 | int8_t TouchWheel::getSliderDelta() 74 | { 75 | return this->_sliderDelta; 76 | } 77 | 78 | uint8_t TouchWheel::getSliderPosition() 79 | { 80 | return this->_sliderPos; 81 | } 82 | 83 | void TouchWheel::onTouchLeftButtonPressed(uint32_t duration) 84 | { 85 | _button[Direction::Left] = duration; 86 | } 87 | 88 | void TouchWheel::onTouchTopButtonPressed(uint32_t duration) 89 | { 90 | _button[Direction::Top] = duration; 91 | } 92 | 93 | void TouchWheel::onTouchRightButtonPressed(uint32_t duration) 94 | { 95 | _button[Direction::Right] = duration; 96 | } 97 | 98 | void TouchWheel::onTouchBottomButtonPressed(uint32_t duration) 99 | { 100 | _button[Direction::Bottom] = duration; 101 | } 102 | 103 | void TouchWheel::onSlider(uint8_t sliderPos, int8_t sliderDelta) 104 | { 105 | //LOG_VALUE("Slider detected",sliderDelta); 106 | this->_sliderPos = sliderPos; 107 | this->_sliderDelta = sliderDelta; 108 | 109 | this->_sliding = true; 110 | } 111 | 112 | void TouchWheel::onTouchDown() 113 | { 114 | this->_touching = true; 115 | } 116 | 117 | void TouchWheel::onTouchUp(uint32_t duration) 118 | { 119 | this->_touching = false; 120 | } 121 | -------------------------------------------------------------------------------- /Firmware/Pins.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #include "Pins.h" 20 | #include "Application.h" 21 | 22 | PinsClass Pins; 23 | 24 | bool Pin::isActive() 25 | { 26 | return _active; 27 | } 28 | 29 | void Pin::setActive(bool active) 30 | { 31 | if (_active == active) return; 32 | _active = active; 33 | 34 | Application.onPinChanged(); 35 | } 36 | 37 | String Pin::getName() 38 | { 39 | return _name; 40 | } 41 | 42 | void Pin::setName(String name) 43 | { 44 | _name = name; 45 | Application.onPinChanged(); 46 | } 47 | 48 | uint8_t Pin::getHardwareId() 49 | { 50 | return _hardwareId; 51 | } 52 | 53 | uint16_t Pin::getColor() 54 | { 55 | return _color; 56 | } 57 | 58 | void Pin::setPinMode(uint8_t thePinMode) 59 | { 60 | pinMode(this->getHardwareId(),thePinMode); 61 | } 62 | 63 | int Pin::analogRead() 64 | { 65 | return ::analogRead(this->getHardwareId()); 66 | } 67 | 68 | PinsClass::PinsClass(): 69 | _pins({ 70 | Pin("GND",RGB565(0,0,0),0), 71 | Pin("",Application.getTheme()->getComplementColor(ColorTheme::Shade::Darker),A14), 72 | Pin("",Application.getTheme()->getSecondaryColor2(ColorTheme::Shade::Darker),24), 73 | Pin("",Application.getTheme()->getSecondaryColor1(ColorTheme::Shade::Darker),3), 74 | Pin("3V3",RGB565(255,0,0),0) 75 | }) 76 | { 77 | } 78 | 79 | Pin* PinsClass::getPin(int8_t pos) 80 | { 81 | if (pos < 0) pos = 0; 82 | if (pos > 4) pos = 4; 83 | 84 | return &_pins[pos]; 85 | } 86 | 87 | void PinsClass::activatePin(int8_t pos, String name) 88 | { 89 | Pin* pin = this->getPin(pos); 90 | pin->setActive(true); 91 | pin->setName(name); 92 | } 93 | 94 | void PinsClass::setPinActive(int8_t pos, bool active) 95 | { 96 | Pin* pin = this->getPin(pos); 97 | pin->setActive(active); 98 | } 99 | 100 | void PinsClass::setPinName(int8_t pos, String name) 101 | { 102 | Pin* pin = this->getPin(pos); 103 | pin->setName(name); 104 | } 105 | 106 | bool PinsClass::isPinActive(int8_t pos) 107 | { 108 | Pin* pin = this->getPin(pos); 109 | return pin->isActive(); 110 | } 111 | 112 | uint8_t PinsClass::getPinId(int8_t pos) 113 | { 114 | return this->getPin(pos)->getHardwareId(); 115 | } 116 | 117 | void PinsClass::resetPins() 118 | { 119 | for (uint8_t i=0;i<5;i++) 120 | { 121 | _pins[i].setActive(false); 122 | } 123 | } -------------------------------------------------------------------------------- /Firmware/Application.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #ifndef _APPLICATION_H_ 20 | #define _APPLICATION_H_ 21 | 22 | #include "Arduino.h" 23 | #include 24 | #include "Appfruits_ST7735.h" 25 | #include "Appfruits_QTouch.h" 26 | #include "StackArray.h" 27 | #include "SceneController.h" 28 | #include "Appfruits_Button.h" 29 | #include "Appfruits_Debug.h" 30 | #include 31 | #include "StatusBarView.h" 32 | #include "Pins.h" 33 | #include "ColorTheme.h" 34 | #include "TouchWheel.h" 35 | #include "Icon.h" 36 | 37 | // If using software SPI (the default case): 38 | #define sclk 13 // SCLK can also use pin 14 39 | #define mosi 11 // MOSI can also use pin 7 40 | #define cs 10 // CS & DC can use pins 2, 6, 9, 10, 15, 20, 21, 22, 23 41 | #define dc 21 // but certain pairs must NOT be used: 2+10, 6+9, 20+23, 21+22 42 | #define rst 9 // RST can use any pin 43 | #define sdcs 4 // CS for SD card, can use any pin 44 | 45 | #define buttonPin 1 46 | #define neoPixelPin 22 47 | #define numPixels 3 48 | 49 | #define ledPin 28 50 | 51 | #define killPin 31 52 | #define lcdBacklightPin 6 53 | 54 | #define chargeAlertPin 2 55 | 56 | #define EXT_PIN_3 3 57 | #define EXT_PIN_2 24 58 | #define EXT_PIN_1 A14 59 | #define EXT_PIN_DAC A14 60 | 61 | #define LOG(m) if (Serial.available()) {Serial.println(m);} 62 | #define LOG_VALUE(m,v) if (Serial.available()) {Serial.print(m);Serial.print(": ");Serial.println(v);} 63 | 64 | class SceneController; 65 | class View; 66 | 67 | class ApplicationClass 68 | { 69 | public: 70 | ApplicationClass(); 71 | ~ApplicationClass(); 72 | 73 | void loop(); 74 | void pushScene(SceneController* scene); 75 | void dismissScene(); 76 | 77 | StatusBarView* getStatusBar(); 78 | 79 | void setFocusedView(View* focusView); 80 | View* getFocusedView(); 81 | void resetFocus(); 82 | 83 | void onPinChanged(); 84 | 85 | void sendScreenshot(); 86 | 87 | ColorTheme* getTheme(); 88 | 89 | private: 90 | StackArray _scenes; 91 | bool _firstSceneLoop; 92 | View* _focusedView; 93 | StatusBarView _statusBarView; 94 | uint32_t _buttonDownStartTime; 95 | ColorTheme _theme; 96 | uint8_t _currentLed; 97 | }; 98 | 99 | extern ApplicationClass Application; 100 | extern Appfruits_ST7735 display; 101 | extern TouchWheel touchWheel; 102 | extern Adafruit_NeoPixel leds; 103 | extern Appfruits_Button button; 104 | extern MAX1704 battery; 105 | extern Appfruits_QTouch qtouch; 106 | 107 | #endif //_APPLICATION_H_ 108 | -------------------------------------------------------------------------------- /Firmware/Adafruit_mfGFX.h: -------------------------------------------------------------------------------- 1 | #ifndef _ADAFRUIT_GFX_H 2 | #define _ADAFRUIT_GFX_H 3 | 4 | #include "fonts.h" 5 | 6 | 7 | #define swap(a, b) { int16_t t = a; a = b; b = t; } 8 | 9 | class Adafruit_GFX : public Print { 10 | 11 | public: 12 | 13 | Adafruit_GFX(int16_t w, int16_t h); // Constructor 14 | 15 | // This MUST be defined by the subclass: 16 | virtual void drawPixel(int16_t x, int16_t y, uint16_t color) = 0; 17 | 18 | // These MAY be overridden by the subclass to provide device-specific 19 | // optimized code. Otherwise 'generic' versions are used. 20 | virtual void 21 | drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color), 22 | drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color), 23 | drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color), 24 | drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color), 25 | fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color), 26 | fillScreen(uint16_t color), 27 | invertDisplay(boolean i), 28 | drawFastChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg, uint8_t size); 29 | 30 | // These exist only with Adafruit_GFX (no subclass overrides) 31 | void 32 | drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color), 33 | drawCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername, 34 | uint16_t color), 35 | fillCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color), 36 | fillCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername, 37 | int16_t delta, uint16_t color), 38 | drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, 39 | int16_t x2, int16_t y2, uint16_t color), 40 | fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, 41 | int16_t x2, int16_t y2, uint16_t color), 42 | drawRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, 43 | int16_t radius, uint16_t color), 44 | fillRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, 45 | int16_t radius, uint16_t color), 46 | drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, 47 | int16_t w, int16_t h, uint16_t color), 48 | drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, 49 | uint16_t bg, uint8_t size), 50 | setCursor(int16_t x, int16_t y), 51 | setTextColor(uint16_t c), 52 | setTextColor(uint16_t c, uint16_t bg), 53 | setTextSize(uint8_t s), 54 | setTextWrap(boolean w), 55 | setRotation(uint8_t r), 56 | setFont(uint8_t f); 57 | 58 | virtual size_t write(uint8_t); 59 | 60 | 61 | int16_t 62 | height(void), 63 | width(void); 64 | 65 | uint8_t getRotation(void); 66 | 67 | protected: 68 | const int16_t 69 | WIDTH, HEIGHT; // This is the 'raw' display w/h - never changes 70 | int16_t 71 | _width, _height, // Display w/h as modified by current rotation 72 | cursor_x, cursor_y; 73 | uint16_t 74 | textcolor, textbgcolor; 75 | uint8_t 76 | textsize, 77 | rotation, 78 | font, 79 | fontStart, 80 | fontEnd; 81 | int8_t 82 | fontKern; 83 | const uint8_t* fontData; 84 | const FontDescriptor* fontDesc; 85 | boolean 86 | wrap; // If set, 'wrap' text at right edge of display 87 | }; 88 | 89 | #endif // _ADAFRUIT_GFX_H -------------------------------------------------------------------------------- /Firmware/LittleHelper.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #include "Application.h" 20 | #include "MainMenuSceneController.h" 21 | 22 | Appfruits_ST7735 display = Appfruits_ST7735(cs, dc, rst); 23 | Appfruits_QTouch qtouch = Appfruits_QTouch(14); 24 | TouchWheel touchWheel(&qtouch); 25 | Adafruit_NeoPixel leds = Adafruit_NeoPixel(numPixels, neoPixelPin, NEO_GRB + NEO_KHZ800); 26 | Appfruits_Button button = Appfruits_Button(buttonPin); 27 | MAX1704 battery = MAX1704(); 28 | 29 | MainMenuSceneController* mainMenu; 30 | 31 | void selfCheck() 32 | { 33 | byte error, address; 34 | int nDevices; 35 | 36 | Serial.println("Scanning..."); 37 | 38 | nDevices = 0; 39 | for(address = 1; address < 127; address++ ) 40 | { 41 | // The i2c_scanner uses the return value of 42 | // the Write.endTransmisstion to see if 43 | // a device did acknowledge to the address. 44 | Wire.beginTransmission(address); 45 | error = Wire.endTransmission(); 46 | 47 | if (error == 0) 48 | { 49 | Serial.print("I2C device found at address 0x"); 50 | if (address<16) 51 | Serial.print("0"); 52 | Serial.print(address,HEX); 53 | Serial.println(" !"); 54 | 55 | nDevices++; 56 | } 57 | else if (error==4) 58 | { 59 | Serial.print("Unknow error at address 0x"); 60 | if (address<16) 61 | Serial.print("0"); 62 | Serial.println(address,HEX); 63 | } 64 | } 65 | if (nDevices == 0) 66 | Serial.println("No I2C devices found\n"); 67 | else 68 | Serial.println("done\n"); 69 | } 70 | 71 | void setup() 72 | { 73 | //Neopixels 74 | LOG("Initializing pixels"); 75 | leds.begin(); 76 | leds.setBrightness(40); 77 | leds.setPixelColor(0,0); 78 | leds.setPixelColor(1,255,255,255); 79 | leds.setPixelColor(2,0); 80 | leds.show(); 81 | 82 | //Initialize Serial 83 | Serial.begin(230400); 84 | 85 | //Initialize I2C 86 | Wire.begin(); 87 | 88 | //Display on 89 | LOG("Activating LCD-Backlight"); 90 | pinMode(lcdBacklightPin,OUTPUT); 91 | digitalWrite(lcdBacklightPin,HIGH); 92 | 93 | //Turn device on 94 | LOG("Setting Kill pin"); 95 | pinMode(killPin,OUTPUT); 96 | digitalWrite(killPin,HIGH); 97 | 98 | leds.setPixelColor(1,0); 99 | leds.show(); 100 | 101 | //LED 102 | LOG("Configuring built in LED"); 103 | pinMode(ledPin,OUTPUT); 104 | 105 | //Init display 106 | LOG("Initializing display"); 107 | display.initR(INITR_BLACKTAB); 108 | display.setRotation(2); 109 | display.clear(ST7735_BLACK); 110 | 111 | //Setup chargealert 112 | //pinMode(chargeAlertPin,INPUT_PULLUP); 113 | 114 | //Setup button 115 | LOG("Initializing Wheel-Button"); 116 | button.begin(); 117 | 118 | //Init touch 119 | LOG("Initializing touch wheel"); 120 | touchWheel.begin(); 121 | 122 | LOG("Starting MainMenu"); 123 | mainMenu = new MainMenuSceneController(); 124 | Application.pushScene(mainMenu); 125 | } 126 | 127 | void loop() 128 | { 129 | Application.loop(); 130 | } -------------------------------------------------------------------------------- /Firmware/Animation.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * Animation.cpp -- Class for animating scalar values 6 | * 7 | * 2014-2015 Phillip Schuster (@appfruits) 8 | * http://www.appfruits.com 9 | */ 10 | 11 | #include "Animation.h" 12 | 13 | Animation::Animation() 14 | { 15 | reset(); 16 | } 17 | 18 | Animation::Animation(String key) 19 | { 20 | reset(); 21 | setKey(key); 22 | } 23 | 24 | void Animation::reset() 25 | { 26 | _initialValue = 0; 27 | _currentValue = 0; 28 | _targetValue = 0; 29 | _duration = 0.25; 30 | _delay = 0; 31 | _animationStart = 0; 32 | _key = ""; 33 | _object = NULL; 34 | } 35 | 36 | Animation::Animation(String key, float initialValue) : Animation(key) 37 | { 38 | setInitialValue(initialValue); 39 | } 40 | 41 | Animation::Animation(String key, float initialValue, float targetValue): Animation(key,initialValue) 42 | { 43 | setTargetValue(targetValue); 44 | } 45 | 46 | Animation::Animation(String key, float initialValue, float targetValue, float duration): Animation(key,initialValue,targetValue) 47 | { 48 | setDuration(duration); 49 | } 50 | 51 | void Animation::init(String key, float initialValue, float targetValue, float duration) 52 | { 53 | setKey(key); 54 | setInitialValue(initialValue); 55 | setTargetValue(targetValue); 56 | setDuration(duration); 57 | } 58 | 59 | void Animation::init(String key, float initialValue, float targetValue, float duration, float delay) 60 | { 61 | setKey(key); 62 | setInitialValue(initialValue); 63 | setTargetValue(targetValue); 64 | setDuration(duration); 65 | setDelay(delay); 66 | } 67 | 68 | void Animation::init(String key, float initialValue, float targetValue) 69 | { 70 | setKey(key); 71 | setInitialValue(initialValue); 72 | setTargetValue(targetValue); 73 | } 74 | 75 | void Animation::setDuration(float duration) 76 | { 77 | _duration = duration; 78 | } 79 | 80 | void Animation::setDelay(float delay) 81 | { 82 | _delay = delay; 83 | } 84 | 85 | void Animation::setInitialValue(float initialValue) 86 | { 87 | _initialValue = initialValue; 88 | _currentValue = _initialValue; 89 | } 90 | 91 | void Animation::setTargetValue(float targetValue) 92 | { 93 | _targetValue = targetValue; 94 | } 95 | 96 | bool Animation::isActive() 97 | { 98 | return (_animationStart != 0); 99 | } 100 | 101 | void Animation::setKey(String key) 102 | { 103 | _key = key; 104 | } 105 | 106 | void Animation::setObject(AnimatableObject *object) 107 | { 108 | _object = object; 109 | } 110 | 111 | void Animation::start() 112 | { 113 | _animationStart = (float)(millis()/1000.0f) + _delay; 114 | } 115 | 116 | void Animation::update() 117 | { 118 | if (_animationStart == 0) return; 119 | if (_targetValue == _initialValue) return; 120 | if (_object == NULL) return; 121 | 122 | uint32_t currentTime = millis(); 123 | float difference = (float)(currentTime/1000.0f) - _animationStart; 124 | if (difference < 0) 125 | { 126 | //Animation did not start yet (waiting for delay) 127 | return; 128 | } 129 | 130 | if (difference >= _duration) 131 | { 132 | _currentValue = _targetValue; 133 | _animationStart = 0; 134 | } 135 | else 136 | { 137 | float factor = difference / _duration; 138 | _currentValue = _initialValue + (factor * (_targetValue - _initialValue)); 139 | } 140 | 141 | _object->animationUpdated(this,_currentValue,(_duration - difference)); 142 | 143 | //If the animation finished in this iteration 144 | if (_animationStart == 0) 145 | { 146 | _object->animationFinished(this); 147 | } 148 | } 149 | 150 | String Animation::getKey() 151 | { 152 | return _key; 153 | } -------------------------------------------------------------------------------- /Firmware/MenuItemView.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #include 20 | #include "MenuItemView.h" 21 | #include "Animator.h" 22 | #include "MenuView.h" 23 | #include "Application.h" 24 | 25 | MenuItemView::MenuItemView() 26 | { 27 | _delegate = NULL; 28 | _tag = 0; 29 | _object = NULL; 30 | _title = ""; 31 | _menuView = NULL; 32 | } 33 | 34 | MenuItemView::MenuItemView(String title): 35 | _title(title) 36 | { 37 | _delegate = NULL; 38 | _tag = 0; 39 | _object = NULL; 40 | _menuView = NULL; 41 | } 42 | 43 | void MenuItemView::draw() 44 | { 45 | uint16_t color = Application.getTheme()->getPrimaryColor(ColorTheme::Shade::Lighter); 46 | display.setTextColor(Application.getTheme()->getTextColor(ColorTheme::Shade::Dark)); 47 | 48 | if (isSelected()) 49 | { 50 | color = Application.getTheme()->getPrimaryColor(); 51 | display.setTextColor(Application.getTheme()->getTextColor()); 52 | } 53 | display.fillRect(_frame.x,_frame.y,_frame.width,_frame.height,color); 54 | display.setFont(ARIAL_8); 55 | display.setTextSize(1); 56 | 57 | display.setCursor(_frame.x + 4,_frame.y+((_frame.height-8)/2)); 58 | display.setTextWrap(false); 59 | display.print(_title); 60 | } 61 | 62 | void MenuItemView::popLeft(bool animated) 63 | { 64 | Animation* animation = Animator.getAnimationSlot(); 65 | if (!animation || !animated) 66 | { 67 | _frame.x = -MAXX; 68 | return; 69 | } 70 | 71 | float delay = 0 ; 72 | if (isSelected()) delay = 0.1; 73 | animation->init("frame.x",_frame.x,-MAXX,1,delay); 74 | addAnimation(animation); 75 | } 76 | 77 | void MenuItemView::pushLeft(bool animated) 78 | { 79 | _frame.x = MAXX; 80 | Animation* animation = Animator.getAnimationSlot(); 81 | if (!animation || !animated) 82 | { 83 | _frame.x = MINX; 84 | return; 85 | } 86 | 87 | animation->init("frame.x",_frame.x,-MINX,1,0.2); 88 | addAnimation(animation); 89 | } 90 | 91 | String MenuItemView::getTitle() 92 | { 93 | return _title; 94 | } 95 | 96 | void MenuItemView::setTitle(String title) 97 | { 98 | _title = title; 99 | setNeedsDisplay(); 100 | } 101 | 102 | MenuItemViewDelegate* MenuItemView::getDelegate() 103 | { 104 | return _delegate; 105 | } 106 | 107 | void MenuItemView::setDelegate(MenuItemViewDelegate *delegate) 108 | { 109 | _delegate = delegate; 110 | } 111 | 112 | uint8_t MenuItemView::getTag() 113 | { 114 | return _tag; 115 | } 116 | 117 | void MenuItemView::setTag(uint8_t tag) 118 | { 119 | _tag = tag; 120 | } 121 | 122 | void *MenuItemView::getObject() 123 | { 124 | return _object; 125 | } 126 | 127 | void MenuItemView::setObject(void *object) 128 | { 129 | _object = object; 130 | } 131 | 132 | void MenuItemView::setSelected(bool selected) 133 | { 134 | _selected = selected; 135 | } 136 | 137 | bool MenuItemView::isSelected() 138 | { 139 | return _selected; 140 | } 141 | 142 | void MenuItemView::setMenuView(MenuView *menuView) 143 | { 144 | _menuView = menuView; 145 | } 146 | 147 | MenuView* MenuItemView::getMenuView() 148 | { 149 | return _menuView; 150 | } 151 | 152 | bool MenuItemView::needsFocus() 153 | { 154 | return false; 155 | } 156 | 157 | void MenuItemView::onClicked() 158 | { 159 | } 160 | 161 | String MenuItemView::getDescription() 162 | { 163 | return "MenuItemView"; 164 | } 165 | 166 | void MenuItemView::setNeedsDisplay() 167 | { 168 | View::setNeedsDisplay(); 169 | 170 | if (_menuView != NULL) 171 | { 172 | _menuView->setNeedsDisplay(); 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /Firmware/View.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #include "View.h" 20 | #include "Application.h" 21 | 22 | View::View() 23 | { 24 | _opaque = false; 25 | _needsDisplay = true; 26 | } 27 | 28 | View::~View() 29 | { 30 | } 31 | 32 | View::View(uint16_t x, uint16_t y, uint16_t width, uint16_t height) 33 | { 34 | _frame = Rect(x,y,width,height); 35 | _opaque = false; 36 | _needsDisplay = true; 37 | _visible = true; 38 | } 39 | 40 | View::View(Rect frame) 41 | { 42 | _frame = frame; 43 | } 44 | 45 | Rect& View::getFrame() 46 | { 47 | return _frame; 48 | } 49 | 50 | void View::setFrame(Rect frame) 51 | { 52 | _frame = frame; 53 | layout(); 54 | } 55 | 56 | void View::setFrame(uint16_t x, uint16_t y, uint16_t width, uint16_t height) 57 | { 58 | _frame = Rect(x,y,width,height); 59 | } 60 | 61 | void View::draw() 62 | { 63 | //LOG_VALUE("Draw",this->getDescription()); 64 | 65 | if (_needsDisplay && _opaque) 66 | { 67 | display.fillRect(_frame.x,_frame.y,_frame.width,_frame.height,_backgroundColor); 68 | } 69 | } 70 | 71 | void View::update() 72 | { 73 | if (isVisible()) 74 | { 75 | if (this->_needsDisplay) 76 | { 77 | //LOG_VALUE("Draw",this->getDescription()); 78 | draw(); 79 | } 80 | } 81 | else 82 | { 83 | //LOG_VALUE("Draw skipped, invisible",this->getDescription()); 84 | } 85 | 86 | didDraw(); 87 | } 88 | 89 | bool View::isVisible() 90 | { 91 | return _visible; 92 | } 93 | 94 | void View::setVisible(bool visible) 95 | { 96 | if (_visible == visible) return; 97 | _visible = visible; 98 | 99 | //Check Focus 100 | if (this->hasFocus()) 101 | { 102 | Application.resetFocus(); 103 | } 104 | 105 | if (!visible) 106 | { 107 | display.fillRect(_frame,Application.getTheme()->getBackgroundColor()); 108 | } 109 | 110 | setNeedsDisplay(); 111 | } 112 | 113 | void View::handleEvents() 114 | { 115 | } 116 | 117 | void View::animationUpdated(Animation *animation, float currentValue, float timeLeft) 118 | { 119 | if (animation->getKey() == "frame.x") 120 | { 121 | display.fillRect(_frame,Application.getTheme()->getBackgroundColor()); 122 | _frame.x = currentValue; 123 | layout(); 124 | } 125 | } 126 | 127 | void View::layout() 128 | { 129 | setNeedsDisplay(); 130 | } 131 | 132 | void View::didDraw() 133 | { 134 | if (this->_needsDisplay == false) return; 135 | 136 | //LOG_VALUE("Did draw",this->getDescription()); 137 | 138 | this->_needsDisplay = false; 139 | } 140 | 141 | void View::setBackgroundColor(uint16_t backgroundColor) 142 | { 143 | _backgroundColor = backgroundColor; 144 | } 145 | 146 | void View::setOpaque(bool opaque) 147 | { 148 | _opaque = opaque; 149 | } 150 | 151 | void View::setFocus() 152 | { 153 | View* currentFocusView = Application.getFocusedView(); 154 | 155 | Application.setFocusedView(this); 156 | setNeedsDisplay(); 157 | 158 | if (currentFocusView != NULL) 159 | { 160 | currentFocusView->setNeedsDisplay(); 161 | } 162 | } 163 | 164 | bool View::hasFocus() 165 | { 166 | return (this == Application.getFocusedView()); 167 | } 168 | 169 | void View::setNeedsDisplay() 170 | { 171 | //LOG_VALUE("Needs display",this->getDescription()); 172 | this->_needsDisplay = true; 173 | } 174 | 175 | String View::getDescription() 176 | { 177 | return "View"; 178 | } 179 | 180 | void View::onTouchWheelLeftClicked(uint32_t duration) 181 | { 182 | 183 | } 184 | 185 | void View::onTouchWheelTopClicked(uint32_t duration) 186 | { 187 | Application.dismissScene(); 188 | } 189 | 190 | void View::onTouchWheelRightClicked(uint32_t duration) 191 | { 192 | 193 | } 194 | 195 | void View::onTouchWheelBottomClicked(uint32_t duration) 196 | { 197 | 198 | } 199 | -------------------------------------------------------------------------------- /Firmware/MenuItemEnumView.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #include "MenuItemEnumView.h" 20 | #include "Application.h" 21 | 22 | MenuItemEnumView::MenuItemEnumView(String title, MenuItemViewDelegate* delegate): 23 | MenuItemView(title) 24 | { 25 | _title = title; 26 | _delegate = delegate; 27 | _touchWheelOffset = 0.0f; 28 | _selectedItemIndex = 0; 29 | }; 30 | 31 | MenuItemEnumView::MenuItemEnumView(String title, MenuItemViewDelegate* delegate, void *object): 32 | MenuItemEnumView(title, delegate) 33 | { 34 | _object = object; 35 | _touchWheelOffset = 0.0f; 36 | } 37 | 38 | void MenuItemEnumView::handleEvents() 39 | { 40 | View::handleEvents(); 41 | 42 | if (hasFocus()) 43 | { 44 | if (button.buttonClicked()) 45 | { 46 | _menuView->setFocus(); 47 | return; 48 | } 49 | 50 | if (touchWheel.isSliding()) 51 | { 52 | _touchWheelOffset += ((float)touchWheel.getSliderDelta() * 0.1f); 53 | if (_touchWheelOffset < 0) _touchWheelOffset = 0; 54 | if (_touchWheelOffset > _items.count()-1) _touchWheelOffset = _items.count()-1; 55 | setSelectedItemIndex(_touchWheelOffset); 56 | 57 | if (_delegate) 58 | { 59 | _delegate->menuItemViewValueChanged(this,getValue()); 60 | } 61 | 62 | setNeedsDisplay(); 63 | } 64 | } 65 | } 66 | 67 | void MenuItemEnumView::draw() 68 | { 69 | uint16_t color = Application.getTheme()->getPrimaryColor(ColorTheme::Shade::Lighter); 70 | display.setTextColor(Application.getTheme()->getTextColor(ColorTheme::Shade::Dark)); 71 | 72 | if (isSelected()) 73 | { 74 | color = Application.getTheme()->getPrimaryColor(); 75 | display.setTextColor(Application.getTheme()->getTextColor()); 76 | } 77 | 78 | display.fillRect(_frame.x,_frame.y,_frame.width,_frame.height,color); 79 | if (hasFocus()) 80 | { 81 | display.drawRect(_frame.x,_frame.y,_frame.width,_frame.height,Application.getTheme()->getPrimaryColor(ColorTheme::Shade::Light)); 82 | } 83 | 84 | display.setFont(ARIAL_8); 85 | display.setTextSize(1); 86 | display.setCursor(_frame.x + 4,_frame.y+((_frame.height-8)/2)); 87 | display.setTextWrap(false); 88 | display.print(_title); 89 | 90 | if (_items.count() > 0) 91 | { 92 | String caption = _items.at(_selectedItemIndex)->caption; 93 | int textWidth = display.calcTextWidth(caption,ARIAL_8); 94 | display.setCursor(_frame.x + _frame.width - 4 - 4 - textWidth, _frame.y+((_frame.height-8)/2)); 95 | display.print(caption); 96 | } 97 | } 98 | 99 | int32_t MenuItemEnumView::getValue() 100 | { 101 | if (_items.count() <= 0) return 0; 102 | return _items.at(_selectedItemIndex)->value; 103 | } 104 | 105 | void MenuItemEnumView::setValue(int32_t value) 106 | { 107 | for (int i=0;i<_items.count();i++) 108 | { 109 | EnumViewItem* item = _items.at(i); 110 | if (item->value == value) 111 | { 112 | setSelectedItemIndex(i); 113 | return; 114 | } 115 | } 116 | } 117 | 118 | bool MenuItemEnumView::needsFocus() 119 | { 120 | return true; 121 | } 122 | 123 | void MenuItemEnumView::onClicked() 124 | { 125 | if (hasFocus()) 126 | { 127 | _menuView->setFocus(); 128 | } 129 | else 130 | { 131 | this->setFocus(); 132 | } 133 | } 134 | 135 | 136 | String MenuItemEnumView::getDescription() 137 | { 138 | return "MenuItemEnumView"; 139 | } 140 | 141 | void MenuItemEnumView::addItem(int32_t value, String caption) 142 | { 143 | _items.push(new EnumViewItem(value,caption)); 144 | } 145 | 146 | void MenuItemEnumView::setSelectedItemIndex(uint8_t selectedItemIndex) 147 | { 148 | if (_selectedItemIndex == selectedItemIndex) return; 149 | _selectedItemIndex = selectedItemIndex; 150 | 151 | setNeedsDisplay(); 152 | } 153 | 154 | uint8_t MenuItemEnumView::getSelectedItemIndex() 155 | { 156 | return _selectedItemIndex; 157 | } -------------------------------------------------------------------------------- /Firmware/MenuItemWheelView.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #include "MenuItemWheelView.h" 20 | #include "Application.h" 21 | 22 | MenuItemWheelView::MenuItemWheelView(String title, MenuItemViewDelegate* delegate): 23 | MenuItemView(title) 24 | { 25 | _title = title; 26 | _delegate = delegate; 27 | _touchWheelOffset = 0.0f; 28 | 29 | _minValue = 0; 30 | _maxValue = 100; 31 | _value = _minValue; 32 | _scale = 1.0f; 33 | }; 34 | 35 | MenuItemWheelView::MenuItemWheelView(String title, MenuItemViewDelegate* delegate, void *object): 36 | MenuItemWheelView(title, delegate) 37 | { 38 | _object = object; 39 | _touchWheelOffset = 0.0f; 40 | } 41 | 42 | void MenuItemWheelView::handleEvents() 43 | { 44 | View::handleEvents(); 45 | 46 | if (hasFocus()) 47 | { 48 | if (button.buttonClicked()) 49 | { 50 | _menuView->setFocus(); 51 | return; 52 | } 53 | 54 | if (touchWheel.isSliding()) 55 | { 56 | float oldValue = _value; 57 | float oldTouchWheelOffset = _touchWheelOffset; 58 | _touchWheelOffset += ((float)touchWheel.getSliderDelta() * 0.1f); 59 | _value = _touchWheelOffset * _scale; 60 | if (_value < _minValue) 61 | { 62 | _value = _minValue; 63 | _touchWheelOffset = oldTouchWheelOffset; 64 | } 65 | if (_value > _maxValue) 66 | { 67 | _value = _maxValue; 68 | _touchWheelOffset = oldTouchWheelOffset; 69 | } 70 | 71 | if (_delegate) 72 | { 73 | if (_value != oldValue) 74 | { 75 | _delegate->menuItemViewValueChanged(this,getValue()); 76 | } 77 | } 78 | 79 | setNeedsDisplay(); 80 | } 81 | } 82 | } 83 | 84 | void MenuItemWheelView::draw() 85 | { 86 | uint16_t color = Application.getTheme()->getPrimaryColor(ColorTheme::Shade::Lighter); 87 | display.setTextColor(Application.getTheme()->getTextColor(ColorTheme::Shade::Dark)); 88 | 89 | if (isSelected()) 90 | { 91 | color = Application.getTheme()->getPrimaryColor(); 92 | display.setTextColor(Application.getTheme()->getTextColor()); 93 | } 94 | 95 | display.fillRect(_frame.x,_frame.y,_frame.width,_frame.height,color); 96 | if (hasFocus()) 97 | { 98 | display.drawRect(_frame.x,_frame.y,_frame.width,_frame.height,Application.getTheme()->getPrimaryColor(ColorTheme::Shade::Light)); 99 | } 100 | 101 | display.setFont(ARIAL_8); 102 | display.setTextSize(1); 103 | display.setCursor(_frame.x + 4,_frame.y+((_frame.height-8)/2)); 104 | display.setTextWrap(false); 105 | display.print(_title); 106 | 107 | int textWidth = display.calcTextWidth(_touchWheelOffset,ARIAL_8); 108 | display.setCursor(_frame.x + _frame.width - 4 - 4 - textWidth, _frame.y+((_frame.height-8)/2)); 109 | display.print(getValue()); 110 | } 111 | 112 | void MenuItemWheelView::setMinValue(float minValue) 113 | { 114 | _minValue = minValue; 115 | } 116 | 117 | void MenuItemWheelView::setMaxValue(float maxValue) 118 | { 119 | _maxValue = maxValue; 120 | } 121 | 122 | void MenuItemWheelView::setScale(float scale) 123 | { 124 | if (scale <= 0) scale = 0.01f; 125 | _scale = scale; 126 | } 127 | 128 | float MenuItemWheelView::getValue() 129 | { 130 | return _value; 131 | } 132 | 133 | void MenuItemWheelView::setValue(float value) 134 | { 135 | if (this->_value == value) return; 136 | 137 | this->_value = value; 138 | this->_touchWheelOffset = this->_value / this->_scale; 139 | 140 | setNeedsDisplay(); 141 | } 142 | 143 | void MenuItemWheelView::setLimits(float minValue, float maxValue) 144 | { 145 | setMinValue(minValue); 146 | setMaxValue(maxValue); 147 | } 148 | 149 | 150 | bool MenuItemWheelView::needsFocus() 151 | { 152 | return true; 153 | } 154 | 155 | void MenuItemWheelView::onClicked() 156 | { 157 | if (hasFocus()) 158 | { 159 | _menuView->setFocus(); 160 | } 161 | else 162 | { 163 | this->setFocus(); 164 | } 165 | } 166 | 167 | 168 | String MenuItemWheelView::getDescription() 169 | { 170 | return "MenuItemWheelView"; 171 | } 172 | 173 | void MenuItemWheelView::setTitle(String title) 174 | { 175 | _title = title; 176 | setNeedsDisplay(); 177 | } -------------------------------------------------------------------------------- /Firmware/LightBoxSceneController.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #include "LightBoxSceneController.h" 20 | #include "MenuItemWheelView.h" 21 | 22 | LightBoxSceneController::LightBoxSceneController(): 23 | _pinDescriptionView(MINX,MINY,MAXW,MAXH-40), 24 | _menuView("Options",MINX,MAXY-26,MAXW,26), 25 | _intro(true), 26 | _settingsMenuView("Settings",MINX,MINY,MAXW,MAXY-35), 27 | _button("Let's go",this), 28 | _i2c(24,3) 29 | { 30 | LOG("LightBoxSceneController Constructor"); 31 | _menuView.addMenuItem(&_button); 32 | 33 | _settings.r = _settings.b = _settings.g = 128; 34 | _settings.currentSlot = 10; 35 | _settings.scale = 0.1f; 36 | 37 | MenuItemWheelView* currentSlot = new MenuItemWheelView("Slot", this); 38 | currentSlot->setLimits(0,31); 39 | currentSlot->setScale(0.1f); 40 | 41 | _currentSlotMenuItem = new MenuItemWheelView("Slot",this); 42 | _currentSlotMenuItem->setLimits(0,31); 43 | _currentSlotMenuItem->setScale(1); 44 | _settingsMenuView.addMenuItem(_currentSlotMenuItem); 45 | 46 | _rMenuItem = new MenuItemWheelView("Red",this); 47 | _rMenuItem->setLimits(0,255); 48 | _rMenuItem->setScale(1); 49 | _settingsMenuView.addMenuItem(_rMenuItem); 50 | 51 | _gMenuItem = new MenuItemWheelView("Green",this); 52 | _gMenuItem->setLimits(0,255); 53 | _gMenuItem->setScale(1); 54 | _settingsMenuView.addMenuItem(_gMenuItem); 55 | 56 | _bMenuItem = new MenuItemWheelView("Blue",this); 57 | _bMenuItem->setLimits(0,255); 58 | _bMenuItem->setScale(1); 59 | _settingsMenuView.addMenuItem(_bMenuItem); 60 | 61 | _scaleMenuItem = new MenuItemWheelView("Scale",this); 62 | _scaleMenuItem->setLimits(0,10); 63 | _scaleMenuItem->setScale(0.1); 64 | _settingsMenuView.addMenuItem(_scaleMenuItem); 65 | 66 | //Setup Pins 67 | Pins.activatePin(PIN_GND,"GND"); 68 | Pins.activatePin(3,"A4 (SDA)"); 69 | Pins.activatePin(2,"A5 (SCL)"); 70 | 71 | //_i2c.setPins(Pins.getPin(3)->getHardwareId(),Pins.getPin(2)->getHardwareId()); 72 | 73 | updateUI(); 74 | } 75 | 76 | LightBoxSceneController::~LightBoxSceneController() 77 | { 78 | } 79 | 80 | void LightBoxSceneController::loop() 81 | { 82 | SceneController::loop(); 83 | 84 | _pinDescriptionView.update(); 85 | _menuView.update(); 86 | _settingsMenuView.update(); 87 | } 88 | 89 | void LightBoxSceneController::updateUI() 90 | { 91 | if (_intro) 92 | { 93 | _pinDescriptionView.setVisible(true); 94 | _settingsMenuView.setVisible(false); 95 | _menuView.setVisible(true); 96 | 97 | _menuView.setFocus(); 98 | } 99 | else 100 | { 101 | _currentSlotMenuItem->setValue(_settings.currentSlot); 102 | _rMenuItem->setValue(_settings.r); 103 | _gMenuItem->setValue(_settings.g); 104 | _bMenuItem->setValue(_settings.b); 105 | _scaleMenuItem->setValue(_settings.scale); 106 | 107 | _pinDescriptionView.setVisible(false); 108 | _settingsMenuView.setVisible(true); 109 | _menuView.setVisible(false); 110 | 111 | _settingsMenuView.setFocus(); 112 | } 113 | } 114 | 115 | void LightBoxSceneController::onWillAppear() 116 | { 117 | SceneController::onWillAppear(); 118 | 119 | Application.getStatusBar()->setCaption("Lightbox"); 120 | this->updateUI(); 121 | } 122 | 123 | String LightBoxSceneController::getName() 124 | { 125 | return "Lightbox"; 126 | } 127 | 128 | void LightBoxSceneController::menuItemViewTriggered(MenuItemView *menuItemView) 129 | { 130 | if (_intro) 131 | { 132 | _intro = false; 133 | updateUI(); 134 | } 135 | else 136 | { 137 | 138 | } 139 | } 140 | 141 | void LightBoxSceneController::sendData() 142 | { 143 | LOG("Sending data"); 144 | LOG_VALUE("Current-Slot",_settings.currentSlot); 145 | _i2c.beginTransmission(4); 146 | _i2c.write((uint8_t*)&_settings,sizeof(LightboxSettings)); 147 | _i2c.endTransmission(); 148 | 149 | /* pinMode(3,OUTPUT); 150 | for (int i=0;i<100;i++) 151 | { 152 | digitalWrite(3,HIGH); 153 | delay(1); 154 | digitalWrite(3,LOW); 155 | delay(3); 156 | }*/ 157 | } 158 | 159 | void LightBoxSceneController::menuItemViewValueChanged(MenuItemView *menuItemView, float value) 160 | { 161 | if (menuItemView == _currentSlotMenuItem) 162 | { 163 | _settings.currentSlot = value; 164 | } 165 | else if (menuItemView == _rMenuItem) 166 | { 167 | _settings.r = value; 168 | } 169 | else if (menuItemView == _gMenuItem) 170 | { 171 | _settings.g = value; 172 | } 173 | else if (menuItemView == _bMenuItem) 174 | { 175 | _settings.b = value; 176 | } 177 | else if (menuItemView == _scaleMenuItem) 178 | { 179 | _settings.scale = value; 180 | } 181 | 182 | sendData(); 183 | } 184 | -------------------------------------------------------------------------------- /Firmware/I2CScannerSceneController.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #include "I2CScannerSceneController.h" 20 | #include "MenuItemButtonView.h" 21 | #include "LabelView.h" 22 | 23 | #define PIN_INFO 0 24 | #define SCANNING 1 25 | #define SHOWRESULTS 2 26 | 27 | I2CScannerSceneController::I2CScannerSceneController(): 28 | _progressBar(MINX+20,MINY+25,MAXW-40,10), 29 | _scanningLabel("Scanning",MINX,MINY+10,MAXW,10), 30 | _pinDescriptionView(MINX,MINY,MAXW,MAXH-40), 31 | _menuView("Options",MINX,MAXY-26,MAXW,26), 32 | _button("Let's go",this), 33 | _state(State::PinInfo), 34 | _devicesFoundLabel("0",MINX+20,MINY+40,MAXW-40,20), 35 | _resultList("Results",MINX,MINY,MAXW,MAXH) 36 | { 37 | _scanningLabel.setTextAlign(TEXTALIGN_CENTERED); 38 | _devicesFoundLabel.setTextAlign(TEXTALIGN_CENTERED); 39 | _devicesFoundLabel.setFont(ARIAL_16); 40 | 41 | _progressBar.setValue(0.3); 42 | 43 | _menuView.addMenuItem(&_button); 44 | 45 | //Setup Pins 46 | Pins.activatePin(PIN_GND,"GND"); 47 | Pins.activatePin(1,"SCL"); 48 | Pins.activatePin(2,"SDA"); 49 | 50 | setState(State::PinInfo); 51 | } 52 | 53 | I2CScannerSceneController::~I2CScannerSceneController() 54 | { 55 | leds.setPixelColor(1,80,80,0); 56 | leds.show(); 57 | 58 | } 59 | 60 | bool I2CScannerSceneController::scanAddress(uint8_t address) 61 | { 62 | Wire.beginTransmission(address); 63 | byte error = Wire.endTransmission(); 64 | 65 | //TODO: Handle I2C error 66 | if (error == 0 || error == 4) 67 | { 68 | _devicesFound[_numDevicesFound] = address; 69 | _numDevicesFound++; 70 | } 71 | 72 | return true; 73 | } 74 | 75 | void I2CScannerSceneController::loop() 76 | { 77 | SceneController::loop(); 78 | 79 | if (_state == State::Scanning) 80 | { 81 | _progressBar.setValue((float)_currentAddress/127.0f); 82 | 83 | if (scanAddress(_currentAddress)) 84 | { 85 | _devicesFoundLabel.setText(_numDevicesFound); 86 | } 87 | 88 | _currentAddress++; 89 | if (_currentAddress > 127) 90 | { 91 | endScan(); 92 | } 93 | } 94 | 95 | _progressBar.update(); 96 | _scanningLabel.update(); 97 | _devicesFoundLabel.update(); 98 | 99 | _pinDescriptionView.update(); 100 | _menuView.update(); 101 | 102 | _resultList.update(); 103 | } 104 | 105 | void I2CScannerSceneController::updateUI() 106 | { 107 | if (_state == I2CScannerSceneController::State::PinInfo) 108 | { 109 | _pinDescriptionView.setVisible(true); 110 | _resultList.setVisible(false); 111 | 112 | _progressBar.setVisible(false); 113 | _scanningLabel.setVisible(false); 114 | _devicesFoundLabel.setVisible(false); 115 | 116 | _button.setTitle("Let's start"); 117 | 118 | _menuView.setVisible(true); 119 | _menuView.setFocus(); 120 | } 121 | else if (_state == I2CScannerSceneController::State::Scanning) 122 | { 123 | _pinDescriptionView.setVisible(false); 124 | _resultList.setVisible(false); 125 | 126 | _progressBar.setVisible(true); 127 | _scanningLabel.setVisible(true); 128 | _devicesFoundLabel.setVisible(true); 129 | 130 | _button.setTitle("Cancel"); 131 | 132 | _menuView.setVisible(true); 133 | _menuView.setFocus(); 134 | 135 | _progressBar.setValue(0); 136 | } 137 | else if (_state == I2CScannerSceneController::State::Results) 138 | { 139 | _pinDescriptionView.setVisible(false); 140 | _resultList.setVisible(true); 141 | 142 | _progressBar.setVisible(false); 143 | _scanningLabel.setVisible(false); 144 | _devicesFoundLabel.setVisible(false); 145 | 146 | _menuView.setVisible(false); 147 | 148 | _resultList.setFocus(); 149 | } 150 | } 151 | 152 | void I2CScannerSceneController::setState(I2CScannerSceneController::State state) 153 | { 154 | _state = state; 155 | 156 | updateUI(); 157 | } 158 | 159 | void I2CScannerSceneController::onWillAppear() 160 | { 161 | SceneController::onWillAppear(); 162 | 163 | Application.getStatusBar()->setCaption("I2C Scan"); 164 | setState(State::PinInfo); 165 | } 166 | 167 | String I2CScannerSceneController::getName() 168 | { 169 | return "I2CScanner"; 170 | } 171 | 172 | void I2CScannerSceneController::startScan() 173 | { 174 | _button.setTitle("Cancel"); 175 | 176 | setState(I2CScannerSceneController::State::Scanning); 177 | _currentAddress = 1; 178 | _numDevicesFound = 0; 179 | } 180 | 181 | void I2CScannerSceneController::endScan() 182 | { 183 | for (int i=0;i<_numDevicesFound;i++) 184 | { 185 | String itemText = String("0x") + String(_devicesFound[i],HEX) + String(" (") + _devicesFound[i] + String(")"); 186 | MenuItemButtonView* listItem = new MenuItemButtonView(itemText,this); 187 | listItem->setTag(_devicesFound[i]); 188 | 189 | _resultList.addMenuItem(listItem); 190 | } 191 | 192 | setState(State::Results); 193 | } 194 | 195 | void I2CScannerSceneController::menuItemViewTriggered(MenuItemView *menuItemView) 196 | { 197 | if (_state == State::PinInfo) 198 | { 199 | startScan(); 200 | } 201 | else if (_state == State::Scanning) 202 | { 203 | setState(State::PinInfo); 204 | } 205 | else if (_state == State::Results) 206 | { 207 | setState(State::PinInfo); 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /Firmware/Application.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #include "Application.h" 20 | #include "SceneController.h" 21 | #include "Animator.h" 22 | 23 | ApplicationClass Application; 24 | 25 | ApplicationClass::ApplicationClass() 26 | { 27 | _firstSceneLoop = true; 28 | _focusedView = NULL; 29 | _buttonDownStartTime = 0; 30 | _currentLed = 0; 31 | } 32 | 33 | ApplicationClass::~ApplicationClass() 34 | { 35 | 36 | } 37 | 38 | void ApplicationClass::sendScreenshot() 39 | { 40 | leds.setPixelColor(0,128,128,128); 41 | leds.setPixelColor(1,128,128,128); 42 | leds.setPixelColor(2,128,128,128); 43 | leds.show(); 44 | 45 | Serial.println(""); 46 | for (int y=0;y<160;y++) 47 | { 48 | for (int x=0;x<128;x++) 49 | { 50 | uint16_t color = display.backbuffer[x][y]; 51 | int r = ((((color >> 11) & 0x1F) * 527) + 23) >> 6; 52 | int g = ((((color >> 5) & 0x3F) * 259) + 33) >> 6; 53 | int b = (((color & 0x1F) * 527) + 23) >> 6; 54 | 55 | Serial.print(r); 56 | Serial.print(","); 57 | Serial.print(g); 58 | Serial.print(","); 59 | Serial.println(b); 60 | } 61 | } 62 | Serial.println(""); 63 | 64 | leds.setPixelColor(0,0,0,0); 65 | leds.setPixelColor(1,0,0,0); 66 | leds.setPixelColor(2,0,0,0); 67 | leds.show(); 68 | 69 | } 70 | 71 | void ApplicationClass::loop() 72 | { 73 | //Run Animations 74 | Animator.update(); 75 | 76 | //Update button state for next run loop 77 | button.update(); 78 | 79 | //Gather touch wheel events 80 | touchWheel.update(); 81 | 82 | if (button.getButtonDownTime() > 1000) 83 | { 84 | leds.setPixelColor(2,80,0,0); 85 | leds.show(); 86 | } 87 | 88 | if (button.getButtonDownTime() > 1300) 89 | { 90 | leds.setPixelColor(1,80,0,0); 91 | leds.show(); 92 | } 93 | 94 | if (button.getButtonDownTime() > 1600) 95 | { 96 | leds.setPixelColor(0,80,0,0); 97 | leds.show(); 98 | 99 | digitalWrite(killPin,LOW); 100 | while (true) { delay(100); }; 101 | } 102 | 103 | //Move up in controller hierarchy 104 | if (touchWheel.isButtonReleased(TouchWheel::Direction::Top)) 105 | { 106 | Application.dismissScene(); 107 | } 108 | 109 | if (touchWheel.isButtonReleased(TouchWheel::Direction::Bottom)) 110 | { 111 | this->sendScreenshot(); 112 | } 113 | 114 | //Handle Events of focused View 115 | if (Application.getFocusedView() != NULL) 116 | { 117 | Application.getFocusedView()->handleEvents(); 118 | } 119 | 120 | //Run current controller 121 | if (_scenes.count() > 0) 122 | { 123 | SceneController* sceneController = _scenes.peek(); 124 | 125 | //Call onWillAppear event handler if this is the first time the loop function is called by the scene 126 | //The default implementation will clear the display! 127 | if (_firstSceneLoop) 128 | { 129 | sceneController->onWillAppear(); 130 | _statusBarView.setNeedsDisplay(); 131 | _firstSceneLoop = false; 132 | } 133 | 134 | //Run the scenes loop function 135 | sceneController->loop(); 136 | 137 | //Update Statusbar 138 | if (sceneController->statusBarVisible()) 139 | { 140 | _statusBarView.update(); 141 | } 142 | 143 | digitalWrite(ledPin,!digitalRead(ledPin)); 144 | //delay(10); 145 | } 146 | else 147 | { 148 | digitalWrite(ledPin,!digitalRead(ledPin)); 149 | delay(50); 150 | } 151 | 152 | /* leds.setPixelColor(0,0,0,0); 153 | leds.setPixelColor(1,0,0,0); 154 | leds.setPixelColor(2,0,0,0); 155 | leds.setPixelColor(_currentLed,80,80,0); 156 | leds.show();*/ 157 | 158 | _currentLed++; 159 | if (_currentLed > 2) 160 | { 161 | _currentLed = 0; 162 | } 163 | 164 | //Update display 165 | display.display(); 166 | //sendScreenshot(); 167 | } 168 | 169 | void ApplicationClass::pushScene(SceneController *scene) 170 | { 171 | LOG_VALUE("Pushing scene",scene->getName()); 172 | 173 | _firstSceneLoop = true; 174 | _scenes.push(scene); 175 | 176 | _statusBarView.setNeedsDisplay(); 177 | } 178 | 179 | void ApplicationClass::dismissScene() 180 | { 181 | if (_scenes.count() <= 1) return; 182 | LOG_VALUE("Dismissing scene", _scenes.peek()->getName()); 183 | 184 | SceneController* sceneController = _scenes.pop(); 185 | sceneController->onWillDisappear(); 186 | 187 | _statusBarView.setNeedsDisplay(); 188 | 189 | leds.setPixelColor(0,80,80,0); 190 | leds.show(); 191 | 192 | leds.setPixelColor(2,80,80,0); 193 | leds.show(); 194 | 195 | _firstSceneLoop = true; 196 | 197 | 198 | } 199 | 200 | void ApplicationClass::setFocusedView(View *focusView) 201 | { 202 | LOG_VALUE("Setting focus to view",focusView->getDescription()); 203 | _focusedView = focusView; 204 | } 205 | 206 | View* ApplicationClass::getFocusedView() 207 | { 208 | return _focusedView; 209 | } 210 | 211 | void ApplicationClass::resetFocus() 212 | { 213 | _focusedView = NULL; 214 | } 215 | 216 | StatusBarView *ApplicationClass::getStatusBar() 217 | { 218 | return &_statusBarView; 219 | } 220 | 221 | void ApplicationClass::onPinChanged() 222 | { 223 | _statusBarView.setNeedsDisplay(); 224 | } 225 | 226 | ColorTheme* ApplicationClass::getTheme() 227 | { 228 | return &_theme; 229 | } -------------------------------------------------------------------------------- /Firmware/MainMenuSceneController.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #include "MainMenuSceneController.h" 20 | #include "MenuItemButtonView.h" 21 | #include "MenuItemWheelView.h" 22 | 23 | MainMenuSceneController::MainMenuSceneController() : 24 | SceneController(), 25 | _currentMenuView(NULL), 26 | _mainMenuView("Home",MINX,MINY,MAXW,MAXY-35), 27 | _settingsMenuView("Settings",MAXX,MINY,MAXW,MAXY-35), 28 | _menuBackgroundView(MINX,MINY,MAXW,MAXY-35) 29 | { 30 | _mainMenuView.addMenuItem(new MenuItemButtonView("Settings", this, new MenuAction(&_settingsMenuView, true))); 31 | _mainMenuView.addMenuItem(new MenuItemButtonView("Analog Out", this)); 32 | _mainMenuView.addMenuItem(new MenuItemButtonView("Clock Out", this)); 33 | _mainMenuView.addMenuItem(new MenuItemButtonView("I2C-Scanner", this)); 34 | _mainMenuView.addMenuItem(new MenuItemButtonView("Scope", this)); 35 | _mainMenuView.addMenuItem(new MenuItemButtonView("LightBox", this)); 36 | _mainMenuView.setVisible(true); 37 | 38 | //Touch-Wheel 39 | MenuItemWheelView* twThreshold = new MenuItemWheelView("Threshold",this); 40 | twThreshold->setLimits(0,127); 41 | twThreshold->setValue(qtouch.getDetectThreshold(0)); 42 | MenuItemWheelView* twIntegrator = new MenuItemWheelView("Integrator",this); 43 | twIntegrator->setLimits(0,127); 44 | twIntegrator->setValue(qtouch.getDetectionIntegrator()); 45 | 46 | _settingsMenuView.addMenuItem(new MenuItemButtonView("<- Back to Home", this, new MenuAction(&_mainMenuView, false))); 47 | _settingsMenuView.addMenuItem(new MenuItemButtonView("Brightness", this)); 48 | _settingsMenuView.addMenuItem(new MenuItemButtonView("Speed", this)); 49 | _settingsMenuView.addMenuItem(twThreshold); 50 | _settingsMenuView.addMenuItem(twIntegrator); 51 | _settingsMenuView.setVisible(true); 52 | 53 | //Create a background view that fixes animation bugs as we move the whole menu without erasing the background beneath it 54 | _menuBackgroundView.setBackgroundColor(ST7735_BLACK); 55 | _menuBackgroundView.setOpaque(true); 56 | 57 | _selectedItem = 0.0f; 58 | 59 | setCurrentMenuView(&_mainMenuView, true); 60 | } 61 | 62 | 63 | void MainMenuSceneController::onWillAppear() 64 | { 65 | SceneController::onWillAppear(); 66 | 67 | _currentMenuView->setFocus(); 68 | } 69 | 70 | void MainMenuSceneController::setCurrentMenuView(MenuView *menuView, bool forward) 71 | { 72 | if (_currentMenuView == menuView) return; 73 | 74 | //Move old view to left 75 | if (_currentMenuView != NULL) 76 | { 77 | if (forward) _currentMenuView->popLeft(true); else _currentMenuView->popRight(true); 78 | } 79 | 80 | //Activate new view, push to left and set status bar caption 81 | _currentMenuView = menuView; 82 | Application.getStatusBar()->setCaption(menuView->getName()); 83 | _currentMenuView->setSelectedItemIndex(0); 84 | _selectedItem = 0.0f; 85 | _currentMenuView->setVisible(true); 86 | _currentMenuView->setFocus(); 87 | if (forward) _currentMenuView->pushLeft(true); else _currentMenuView->pushRight(true); 88 | } 89 | 90 | MenuView* MainMenuSceneController::getCurrentMenuView() 91 | { 92 | return _currentMenuView; 93 | } 94 | 95 | void MainMenuSceneController::loop() 96 | { 97 | _menuBackgroundView.update(); 98 | _mainMenuView.update(); 99 | _settingsMenuView.update(); 100 | } 101 | 102 | void MainMenuSceneController::menuItemViewTriggered(MenuItemView *menuItemView) 103 | { 104 | MenuAction* menuAction = (MenuAction*)menuItemView->getObject(); 105 | if (menuAction != NULL) 106 | { 107 | MenuView* nextMenuView = menuAction->getNextMenu(); 108 | bool forward = menuAction->isForward(); 109 | 110 | if (nextMenuView != NULL) 111 | { 112 | setCurrentMenuView(nextMenuView, forward); 113 | return; 114 | } 115 | } 116 | else if (menuItemView->getTitle() == "Analog Out") 117 | { 118 | _analogOutputSceneController = new AnalogOutSceneController(); 119 | Application.pushScene(_analogOutputSceneController); 120 | } 121 | else if (menuItemView->getTitle() == "Clock Out") 122 | { 123 | _clockOutSceneController = new ClockOutSceneController(); 124 | Application.pushScene(_clockOutSceneController); 125 | } 126 | else if (menuItemView->getTitle() == "I2C-Scanner") 127 | { 128 | _i2cScannerSceneController = new I2CScannerSceneController(); 129 | Application.pushScene(_i2cScannerSceneController); 130 | } 131 | else if (menuItemView->getTitle() == "Scope") 132 | { 133 | _scopeSceneController = new ScopeSceneController(); 134 | Application.pushScene(_scopeSceneController); 135 | } 136 | else if (menuItemView->getTitle() == "LightBox") 137 | { 138 | _lightboxSceneController = new LightBoxSceneController(); 139 | Application.pushScene(_lightboxSceneController); 140 | } 141 | } 142 | 143 | 144 | void MainMenuSceneController::menuItemViewValueChanged(MenuItemView *menuItemView, float value) 145 | { 146 | if (menuItemView->getTitle() == "Threshold") 147 | { 148 | for (int i=0;i<3;i++) 149 | { 150 | qtouch.setDetectThreshold(i,(int)value); 151 | } 152 | LOG_VALUE("Touch-Wheel detection threshold",(int)value); 153 | } 154 | else if (menuItemView->getTitle() == "Integrator") 155 | { 156 | qtouch.setDetectionIntegrator((int)value); 157 | LOG_VALUE("Touch-Wheel integrator",(int)value); 158 | } 159 | } 160 | 161 | String MainMenuSceneController::getName() 162 | { 163 | return "Main-Menu"; 164 | } 165 | -------------------------------------------------------------------------------- /Firmware/MenuView.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #include "MenuView.h" 20 | #include "Animator.h" 21 | #include "MenuItemView.h" 22 | #include "Application.h" 23 | 24 | MenuView::MenuView() 25 | { 26 | _scrollOffset = 0; 27 | _selectedItemIndex = 0; 28 | _delegate = NULL; 29 | } 30 | 31 | MenuView::MenuView(String name, uint16_t x, uint16_t y, uint16_t width, uint16_t height, bool vertical) : View(x,y,width,height) 32 | { 33 | _selectedItemIndex = 0; 34 | setName(name); 35 | _touchWheelOffset = 0.0f; 36 | _delegate = NULL; 37 | _vertical = vertical; 38 | _scrollOffset = 0; 39 | } 40 | 41 | MenuView::~MenuView() 42 | { 43 | while (!_menuItems.isEmpty()) 44 | { 45 | MenuItemView* itemView = _menuItems.pop(); 46 | delete itemView; 47 | } 48 | } 49 | 50 | void MenuView::draw() 51 | { 52 | display.setClipRect(getFrame()); 53 | display.fillRect(_frame.x,_frame.y,_frame.width,_frame.height, ST7735_BLACK); 54 | for (uint16_t i=0;i<_menuItems.count();i++) 55 | { 56 | MenuItemView* itemView = _menuItems.at(i); 57 | itemView->setSelected((_selectedItemIndex == i)); 58 | itemView->draw(); 59 | } 60 | display.resetClipRect(); 61 | } 62 | 63 | 64 | Rect MenuView::itemViewRect(int itemIndex) 65 | { 66 | return Rect(_frame.x,_frame.y + (28*itemIndex),128,26); 67 | } 68 | 69 | void MenuView::layout() 70 | { 71 | View::layout(); 72 | 73 | if (_vertical) 74 | { 75 | Rect frame = Rect(_frame.x,_frame.y-_scrollOffset,128,26); 76 | for (uint16_t i=0;i<_menuItems.count();i++) 77 | { 78 | MenuItemView* itemView = _menuItems.at(i); 79 | if (itemView) 80 | { 81 | itemView->setFrame(frame); 82 | frame.y += 28; 83 | } 84 | } 85 | } 86 | else 87 | { 88 | int gap = 1; 89 | int itemWidth = (_frame.width - ((_menuItems.count()-1) * gap)) / _menuItems.count(); 90 | Rect frame = Rect(_frame.x,_frame.y,itemWidth,_frame.height); 91 | for (uint16_t i=0;i<_menuItems.count();i++) 92 | { 93 | MenuItemView* itemView = _menuItems.at(i); 94 | if (itemView) 95 | { 96 | itemView->setFrame(frame); 97 | frame.x += itemWidth + gap; 98 | } 99 | } 100 | } 101 | } 102 | 103 | void MenuView::addMenuItem(MenuItemView *view) 104 | { 105 | _menuItems.push(view); 106 | view->setMenuView(this); 107 | layout(); 108 | } 109 | 110 | uint8_t MenuView::getSelectedItemIndex() 111 | { 112 | return _selectedItemIndex; 113 | } 114 | 115 | 116 | void MenuView::setScrollOffset(int32_t offset, bool animated) 117 | { 118 | LOG_VALUE("Scroll-Offset",offset); 119 | 120 | Animation* animation = Animator.getAnimationSlot(); 121 | if (!animation || !animated) 122 | { 123 | _scrollOffset = offset; 124 | layout(); 125 | return; 126 | } 127 | 128 | animation->init("scrollOffset",_scrollOffset,offset,0.1); 129 | addAnimation(animation); 130 | 131 | layout(); 132 | } 133 | 134 | void MenuView::setSelectedItemIndex(uint8_t selectedItemIndex) 135 | { 136 | if (_selectedItemIndex == selectedItemIndex) return; 137 | 138 | _selectedItemIndex = selectedItemIndex; 139 | 140 | LOG_VALUE("Setting selected index",selectedItemIndex); 141 | 142 | //Check scrollOffset 143 | MenuItemView* itemView = _menuItems.at(_selectedItemIndex); 144 | if (itemView) 145 | { 146 | Rect itemRect = itemViewRect(_selectedItemIndex); 147 | if (itemView->getFrame().bottom() > _frame.bottom()) 148 | { 149 | setScrollOffset(itemRect.bottom() - _frame.bottom(), true); 150 | } 151 | else if (itemView->getFrame().top() < _frame.top()) 152 | { 153 | setScrollOffset(itemRect.top()-_frame.top(),true); 154 | } 155 | } 156 | 157 | setNeedsDisplay(); 158 | } 159 | 160 | void MenuView::popLeft(bool animated) 161 | { 162 | Animation* animation = Animator.getAnimationSlot(); 163 | if (!animation || !animated) 164 | { 165 | _frame.x = -MAXX; 166 | layout(); 167 | return; 168 | } 169 | 170 | animation->init("frame.x",_frame.x,-MAXX,0.3); 171 | addAnimation(animation); 172 | } 173 | 174 | void MenuView::pushLeft(bool animated) 175 | { 176 | //_frame.x = MAXX-30; 177 | Animation* animation = Animator.getAnimationSlot(); 178 | if (!animation || !animated) 179 | { 180 | _frame.x = MINX; 181 | layout(); 182 | return; 183 | } 184 | 185 | animation->init("frame.x",_frame.x,MINX,0.3,0.2); 186 | addAnimation(animation); 187 | } 188 | 189 | void MenuView::popRight(bool animated) 190 | { 191 | Animation* animation = Animator.getAnimationSlot(); 192 | if (!animation || !animated) 193 | { 194 | _frame.x = MAXX; 195 | layout(); 196 | return; 197 | } 198 | 199 | animation->init("frame.x",_frame.x,MAXX,0.3); 200 | addAnimation(animation); 201 | } 202 | 203 | void MenuView::pushRight(bool animated) 204 | { 205 | _frame.x = -MAXX; 206 | Animation* animation = Animator.getAnimationSlot(); 207 | if (!animation || !animated) 208 | { 209 | _frame.x = MINX; 210 | layout(); 211 | return; 212 | } 213 | 214 | animation->init("frame.x",_frame.x,MINX,0.3,0.2); 215 | addAnimation(animation); 216 | } 217 | 218 | 219 | void MenuView::animationUpdated(Animation *animation, float currentValue, float timeLeft) 220 | { 221 | View::animationUpdated(animation, currentValue, timeLeft); 222 | 223 | if (animation->getKey() == "scrollOffset") 224 | { 225 | _scrollOffset = currentValue; 226 | layout(); 227 | } 228 | } 229 | 230 | void MenuView::setName(String name) 231 | { 232 | _name = name; 233 | } 234 | 235 | String MenuView::getName() 236 | { 237 | return _name; 238 | } 239 | 240 | int MenuView::getNumberOfItems() 241 | { 242 | return _menuItems.count(); 243 | } 244 | 245 | void MenuView::handleEvents() 246 | { 247 | View::handleEvents(); 248 | 249 | if (touchWheel.isSliding()) 250 | { 251 | _touchWheelOffset += ((float)touchWheel.getSliderDelta() * 0.05f); 252 | if (_touchWheelOffset < 0) _touchWheelOffset = 0; 253 | if (_touchWheelOffset > _menuItems.count()-1) _touchWheelOffset = _menuItems.count()-1; 254 | setSelectedItemIndex(_touchWheelOffset); 255 | } 256 | 257 | if (button.buttonClicked()) 258 | { 259 | MenuItemView* selectedItemView = _menuItems.at(_selectedItemIndex); 260 | if (selectedItemView) 261 | { 262 | selectedItemView->onClicked(); 263 | } 264 | } 265 | } 266 | 267 | MenuViewDelegate* MenuView::getDelegate() 268 | { 269 | return _delegate; 270 | } 271 | 272 | void MenuView::setDelegate(MenuViewDelegate *delegate) 273 | { 274 | _delegate = delegate; 275 | } 276 | 277 | String MenuView::getDescription() 278 | { 279 | return "MenuView"; 280 | } 281 | -------------------------------------------------------------------------------- /Firmware/Appfruits_ST7735.h: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | This is a library for the Adafruit 1.8" SPI display. 3 | This library works with the Adafruit 1.8" TFT Breakout w/SD card 4 | ----> http://www.adafruit.com/products/358 5 | as well as Adafruit raw 1.8" TFT display 6 | ----> http://www.adafruit.com/products/618 7 | 8 | Check out the links above for our tutorials and wiring diagrams 9 | These displays use SPI to communicate, 4 or 5 pins are required to 10 | interface (RST is optional) 11 | Adafruit invests time and resources providing this open source code, 12 | please support Adafruit and open-source hardware by purchasing 13 | products from Adafruit! 14 | 15 | Written by Limor Fried/Ladyada for Adafruit Industries. 16 | MIT license, all text above must be included in any redistribution 17 | ****************************************************/ 18 | 19 | /* 20 | * We made changes and introduced a backbuffer (possible on Teensy as it 21 | * has more SRAM than typical AVR MCUs) that allows for much faster 22 | * refresh rates (only pixels that have changed are transferred via SPI) 23 | * We also added Portrait and Landscape modes. 24 | * 25 | * This is a drop-in replacement for the existing Adafruit_ST7735 library. 26 | * Give it a try if your hardware supports it. 27 | * 28 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 29 | * http://www.appfruits.com 30 | */ 31 | 32 | #ifndef _APPFRUITS_ST7735H_ 33 | #define _APPFRUITS_ST7735H_ 34 | 35 | #define DEBUG_DRAW_CYCLE 0 36 | 37 | #if ARDUINO >= 100 38 | #include "Arduino.h" 39 | #include "Print.h" 40 | #else 41 | #include "WProgram.h" 42 | #endif 43 | 44 | #include "Adafruit_mfGFX.h" 45 | 46 | #if defined(__SAM3X8E__) 47 | #include 48 | #define PROGMEM 49 | #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) 50 | #define pgm_read_word(addr) (*(const unsigned short *)(addr)) 51 | typedef unsigned char prog_uchar; 52 | #endif 53 | #ifdef __AVR__ 54 | #include 55 | #endif 56 | 57 | // some flags for initR() :( 58 | #define INITR_GREENTAB 0x0 59 | #define INITR_REDTAB 0x1 60 | #define INITR_BLACKTAB 0x2 61 | 62 | #define ST7735_TFTWIDTH 128 63 | #define ST7735_TFTHEIGHT 160 64 | 65 | #define ST7735_NOP 0x00 66 | #define ST7735_SWRESET 0x01 67 | #define ST7735_RDDID 0x04 68 | #define ST7735_RDDST 0x09 69 | 70 | #define ST7735_SLPIN 0x10 71 | #define ST7735_SLPOUT 0x11 72 | #define ST7735_PTLON 0x12 73 | #define ST7735_NORON 0x13 74 | 75 | #define ST7735_INVOFF 0x20 76 | #define ST7735_INVON 0x21 77 | #define ST7735_DISPOFF 0x28 78 | #define ST7735_DISPON 0x29 79 | #define ST7735_CASET 0x2A 80 | #define ST7735_RASET 0x2B 81 | #define ST7735_RAMWR 0x2C 82 | #define ST7735_RAMRD 0x2E 83 | 84 | #define ST7735_PTLAR 0x30 85 | #define ST7735_COLMOD 0x3A 86 | #define ST7735_MADCTL 0x36 87 | 88 | #define ST7735_FRMCTR1 0xB1 89 | #define ST7735_FRMCTR2 0xB2 90 | #define ST7735_FRMCTR3 0xB3 91 | #define ST7735_INVCTR 0xB4 92 | #define ST7735_DISSET5 0xB6 93 | 94 | #define ST7735_PWCTR1 0xC0 95 | #define ST7735_PWCTR2 0xC1 96 | #define ST7735_PWCTR3 0xC2 97 | #define ST7735_PWCTR4 0xC3 98 | #define ST7735_PWCTR5 0xC4 99 | #define ST7735_VMCTR1 0xC5 100 | 101 | #define ST7735_RDID1 0xDA 102 | #define ST7735_RDID2 0xDB 103 | #define ST7735_RDID3 0xDC 104 | #define ST7735_RDID4 0xDD 105 | 106 | #define ST7735_PWCTR6 0xFC 107 | 108 | #define ST7735_GMCTRP1 0xE0 109 | #define ST7735_GMCTRN1 0xE1 110 | 111 | // Color definitions 112 | #define ST7735_BLACK 0x0000 113 | #define ST7735_BLUE 0x001F 114 | #define ST7735_RED 0xF800 115 | #define ST7735_GREEN 0x07E0 116 | #define ST7735_CYAN 0x07FF 117 | #define ST7735_MAGENTA 0xF81F 118 | #define ST7735_YELLOW 0xFFE0 119 | #define ST7735_WHITE 0xFFFF 120 | 121 | #define PORTRAIT 0 122 | #define LANDSCAPE_LEFT 1 123 | #define LANDSCAPE_RIGHT 2 124 | #define PORTRAIT_UPSIDEDOWN 3 125 | 126 | /*uint16_t drawRGB24toRGB565(uint8_t r, uint8_t g, uint8_t b) 127 | { 128 | return ((r / 8) << 11) | ((g / 4) << 5) | (b / 8); 129 | }*/ 130 | 131 | #define RGB565(r,g,b) ((r / 8) << 11) | ((g / 4) << 5) | (b / 8) 132 | 133 | #include "View.h" 134 | 135 | class Rect; 136 | class Icon; 137 | 138 | class Appfruits_ST7735 : public Adafruit_GFX { 139 | 140 | public: 141 | 142 | Appfruits_ST7735(uint8_t CS, uint8_t RS, uint8_t SID, uint8_t SCLK, 143 | uint8_t RST); 144 | Appfruits_ST7735(uint8_t CS, uint8_t RS, uint8_t RST); 145 | 146 | void initB(void), // for ST7735B displays 147 | initR(uint8_t options = INITR_GREENTAB), // for ST7735R 148 | setAddrWindow(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1), 149 | pushColor(uint16_t color), 150 | fillScreen(uint16_t color), 151 | drawPixel(int16_t x, int16_t y, uint16_t color), 152 | drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color), 153 | drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color), 154 | fillRect(int16_t x, int16_t y, int16_t w, int16_t h, 155 | uint16_t color), 156 | fillRect(Rect frame, uint16_t color), 157 | setRotation(uint8_t r), 158 | invertDisplay(boolean i), 159 | setPixel(int16_t x, int16_t y, uint16_t color), 160 | setOrientation(uint8_t orientation), 161 | drawIcon(Icon* icon, uint8_t x, uint8_t y, uint16_t color), 162 | setClipRect(Rect rect), 163 | resetClipRect(); 164 | 165 | uint16_t calcTextWidth(String text, uint8_t font); 166 | uint8_t calcTextHeight(String text, uint8_t font); 167 | 168 | void display(void), 169 | clear(uint16_t color); 170 | 171 | // Pass 8-bit (each) R,G,B, get back 16-bit packed color 172 | inline uint16_t Color565(uint8_t r, uint8_t g, uint8_t b) { 173 | return ((b & 0xF8) << 8) | ((g & 0xFC) << 3) | (r >> 3); 174 | } 175 | void setBitrate(uint32_t n); 176 | 177 | /* These are not for current use, 8-bit protocol only! 178 | uint8_t readdata(void), 179 | readcommand8(uint8_t); 180 | uint16_t readcommand16(uint8_t); 181 | uint32_t readcommand32(uint8_t); 182 | void dummyclock(void); 183 | */ 184 | 185 | 186 | uint8_t tabcolor; 187 | uint16_t backbuffer[128][160]; 188 | Rect _clipRect; 189 | private: 190 | uint16_t _dirtyX; 191 | uint16_t _dirtyY; 192 | uint16_t _dirtyX1; 193 | uint16_t _dirtyY1; 194 | float _transform[2][2]; 195 | uint8_t _orientation; 196 | 197 | void writebegin(), 198 | spiwrite(uint8_t), 199 | writecommand(uint8_t c), 200 | writedata(uint8_t d), 201 | writedata16(uint16_t d), 202 | commandList(const uint8_t *addr), 203 | commonInit(const uint8_t *cmdList); 204 | //uint8_t spiread(void); 205 | 206 | public: 207 | boolean hwSPI; 208 | 209 | #if defined(__AVR__) 210 | volatile uint8_t *dataport, *clkport, *csport, *rsport; 211 | uint8_t _cs, _rs, _rst, _sid, _sclk, 212 | datapinmask, clkpinmask, cspinmask, rspinmask, 213 | colstart, rowstart; // some displays need this changed 214 | #endif // #ifdef __AVR__ 215 | 216 | #if defined(__SAM3X8E__) 217 | Pio *dataport, *clkport, *csport, *rsport; 218 | uint32_t _cs, _rs, _rst, _sid, _sclk, 219 | datapinmask, clkpinmask, cspinmask, rspinmask, 220 | colstart, rowstart; // some displays need this changed 221 | #endif // #if defined(__SAM3X8E__) 222 | 223 | #if defined(__MK20DX128__) || defined(__MK20DX256__) 224 | uint8_t _cs, _rs, _rst, _sid, _sclk; 225 | uint8_t colstart, rowstart; 226 | uint8_t pcs_data, pcs_command; 227 | uint32_t ctar; 228 | volatile uint8_t *datapin, *clkpin, *cspin, *rspin; 229 | #endif 230 | 231 | }; 232 | 233 | #endif 234 | -------------------------------------------------------------------------------- /Firmware/Appfruits_QTouch.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This is a library for the Atmel QTouch AT42QT2120 3 | * But it should work with other QTouch Devices as well 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #include "Appfruits_QTouch.h" 20 | #include "Application.h" 21 | 22 | #include 23 | #include 24 | 25 | Appfruits_QTouch::Appfruits_QTouch(uint8_t changePin) 26 | { 27 | _delegate = NULL; 28 | _changePin = changePin; 29 | 30 | for (int i=0;isetDragging(false); 95 | _lastSliderPos = 0; 96 | 97 | return false; 98 | } 99 | 100 | bool Appfruits_QTouch::isKeyPressed(uint8_t index) 101 | { 102 | if (index > 11) return false; 103 | 104 | uint8_t address = QT2120_KEYSTATUS_1; 105 | if (index > 7) 106 | { 107 | address = QT2120_KEYSTATUS_2; 108 | index -= 8; 109 | } 110 | 111 | uint8_t keyStatus = readRegister8(address); 112 | return isBitSet(keyStatus,index); 113 | } 114 | 115 | void Appfruits_QTouch::setDetectThreshold(uint8_t index, uint8_t value) 116 | { 117 | if (index > 11) return; 118 | 119 | uint8_t address = QT2120_DETECT_THRESHOLD + index; 120 | 121 | writeRegister(address,value); 122 | } 123 | 124 | 125 | uint8_t Appfruits_QTouch::getDetectThreshold(uint8_t index) 126 | { 127 | uint8_t address = QT2120_DETECT_THRESHOLD + index; 128 | return readRegister8(address); 129 | } 130 | 131 | void Appfruits_QTouch::setDetectionIntegrator(uint8_t value) 132 | { 133 | if (value <= 0) value = 1; 134 | if (value > 32) value = 32; 135 | 136 | writeRegister(QT2120_DETECTION_INTEGRATOR,value); 137 | } 138 | 139 | 140 | uint8_t Appfruits_QTouch::getDetectionIntegrator() 141 | { 142 | return readRegister8(QT2120_DETECTION_INTEGRATOR); 143 | } 144 | 145 | bool Appfruits_QTouch::touchDetected() 146 | { 147 | uint8_t detectionStatus = readRegister8(QT2120_DETECTION_STATUS); 148 | if (isBitSet(detectionStatus,0)) 149 | { 150 | return true; 151 | } 152 | 153 | return false; 154 | } 155 | 156 | bool Appfruits_QTouch::sliderDetected() 157 | { 158 | uint8_t detectionStatus = readRegister8(QT2120_DETECTION_STATUS); 159 | if (isBitSet(detectionStatus,1)) 160 | { 161 | return true; 162 | } 163 | 164 | this->setDragging(false); 165 | 166 | return false; 167 | } 168 | 169 | bool Appfruits_QTouch::wheelDetected() 170 | { 171 | return sliderDetected(); 172 | } 173 | 174 | uint8_t Appfruits_QTouch::sliderPosition() 175 | { 176 | uint8_t sliderPos = readRegister8(QT2120_SLIDERPOS); 177 | return sliderPos; 178 | } 179 | 180 | int8_t Appfruits_QTouch::sliderDelta() 181 | { 182 | if (sliderDetected()) 183 | { 184 | uint8_t sliderPos = sliderPosition(); 185 | if (this->_dragging == true) 186 | { 187 | int16_t delta = sliderPos - _lastSliderPos; 188 | 189 | if (delta < -128) 190 | { 191 | delta += 255; 192 | } 193 | if (delta > 128) 194 | { 195 | delta -= 255; 196 | } 197 | 198 | _deltas[_currentDelta++] = delta; 199 | if (_currentDelta > (QT2120_NUMBER_OF_SAMPLES-1)) _currentDelta = 0; 200 | 201 | delta = 0; 202 | for (int i=0;i this->_maxDelta) 213 | { 214 | this->_maxDelta = delta; 215 | } 216 | 217 | if (this->_delegate != NULL) 218 | { 219 | if (abs(this->_maxDelta) > 1) 220 | { 221 | this->_delegate->onSlider(sliderPos,delta); 222 | } 223 | else 224 | { 225 | this->_delegate->onTouchDown(); 226 | } 227 | } 228 | 229 | return delta; 230 | } 231 | 232 | _lastSliderPos = sliderPos; 233 | this->setDragging(true); 234 | } 235 | else 236 | { 237 | this->setDragging(false); 238 | } 239 | 240 | return 0; 241 | } 242 | 243 | uint8_t Appfruits_QTouch::wheelPosition() 244 | { 245 | return sliderPosition(); 246 | } 247 | 248 | int8_t Appfruits_QTouch::wheelDelta() 249 | { 250 | return sliderDelta(); 251 | } 252 | 253 | void Appfruits_QTouch::setDragging(bool dragging) 254 | { 255 | if (_dragging == dragging) return; 256 | 257 | if (dragging) 258 | { 259 | this->_dragStartTime = millis(); 260 | 261 | if (this->_delegate != NULL) 262 | { 263 | this->_delegate->onTouchDown(); 264 | } 265 | } 266 | else 267 | { 268 | uint32_t duration = millis()-this->_dragStartTime; 269 | 270 | if (this->_delegate != NULL) 271 | { 272 | this->_delegate->onTouchUp(duration); 273 | } 274 | 275 | if (this->_maxDelta <= 1) 276 | { 277 | if (_delegate != NULL) 278 | { 279 | //Just tapped and not dragged 280 | if (abs(_lastSliderPos-140) < 10) 281 | { 282 | this->_delegate->onTouchLeftButtonPressed(duration); 283 | } 284 | else if (abs(_lastSliderPos-220) < 10) 285 | { 286 | this->_delegate->onTouchTopButtonPressed(duration); 287 | } 288 | else if (abs(_lastSliderPos-35) < 10) 289 | { 290 | this->_delegate->onTouchRightButtonPressed(duration); 291 | } 292 | else if (abs(_lastSliderPos-90) < 10) 293 | { 294 | this->_delegate->onTouchBottomButtonPressed(duration); 295 | } 296 | } 297 | } 298 | } 299 | 300 | this->_dragging = dragging; 301 | this->_maxDelta = 0; 302 | } 303 | 304 | bool Appfruits_QTouch::isDragging() 305 | { 306 | return this->_dragging; 307 | } 308 | 309 | uint8_t Appfruits_QTouch::getLastSliderPos() 310 | { 311 | return this->_lastSliderPos; 312 | } 313 | 314 | void Appfruits_QTouch::setDelegate(Appfruits_QTouch_Delegate *delegate) 315 | { 316 | this->_delegate = delegate; 317 | } -------------------------------------------------------------------------------- /Firmware/StackArray.h: -------------------------------------------------------------------------------- 1 | /* 2 | * StackArray.h 3 | * 4 | * Library implementing a generic, dynamic stack (array version). 5 | * 6 | * --- 7 | * 8 | * Copyright (C) 2010 Efstathios Chatzikyriakidis (contact@efxa.org) 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation, either version 3 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program. If not, see . 22 | * 23 | * --- 24 | * 25 | * Version 1.0 26 | * 27 | * 2010-09-25 Efstathios Chatzikyriakidis 28 | * 29 | * - added resize(): for growing, shrinking the array size. 30 | * 31 | * 2010-09-23 Efstathios Chatzikyriakidis 32 | * 33 | * - added exit(), blink(): error reporting and handling methods. 34 | * 35 | * 2010-09-20 Alexander Brevig 36 | * 37 | * - added setPrinter(): indirectly reference a Serial object. 38 | * 39 | * 2010-09-15 Efstathios Chatzikyriakidis 40 | * 41 | * - initial release of the library. 42 | * 43 | * --- 44 | * 45 | * For the latest version see: http://www.arduino.cc/ 46 | */ 47 | 48 | // header defining the interface of the source. 49 | #ifndef _STACKARRAY_H 50 | #define _STACKARRAY_H 51 | 52 | // include Arduino basic header. 53 | #include 54 | 55 | // the definition of the stack class. 56 | template 57 | class StackArray { 58 | public: 59 | // init the stack (constructor). 60 | StackArray (); 61 | 62 | // clear the stack (destructor). 63 | ~StackArray (); 64 | 65 | // push an item to the stack. 66 | void push (const T i); 67 | 68 | // pop an item from the stack. 69 | T pop (); 70 | 71 | // get an item from the stack. 72 | T peek () const; 73 | 74 | // get an item at index n 75 | T at (uint16_t n) const; 76 | 77 | // check if the stack is empty. 78 | bool isEmpty () const; 79 | 80 | // get the number of items in the stack. 81 | int count () const; 82 | 83 | // check if the stack is full. 84 | bool isFull () const; 85 | 86 | // set the printer of the stack. 87 | void setPrinter (Print & p); 88 | 89 | private: 90 | // resize the size of the stack. 91 | void resize (const int s); 92 | 93 | // exit report method in case of error. 94 | void exit (const char * m) const; 95 | 96 | // led blinking method in case of error. 97 | void blink () const; 98 | 99 | // the initial size of the stack. 100 | static const int initialSize = 2; 101 | 102 | // the pin number of the on-board led. 103 | static const int ledPin = 13; 104 | 105 | Print * printer; // the printer of the stack. 106 | T * contents; // the array of the stack. 107 | int size; // the size of the stack. 108 | int top; // the top index of the stack. 109 | }; 110 | 111 | // init the stack (constructor). 112 | template 113 | StackArray::StackArray () { 114 | size = 0; // set the size of stack to zero. 115 | top = 0; // set the initial top index of the stack. 116 | printer = NULL; // set the printer of stack to point nowhere. 117 | 118 | // allocate enough memory for the array. 119 | contents = (T *) malloc (sizeof (T) * initialSize); 120 | 121 | // if there is a memory allocation error. 122 | if (contents == NULL) 123 | exit ("STACK: insufficient memory to initialize stack."); 124 | 125 | // set the initial size of the stack. 126 | size = initialSize; 127 | } 128 | 129 | // clear the stack (destructor). 130 | template 131 | StackArray::~StackArray () { 132 | free (contents); // deallocate the array of the stack. 133 | 134 | contents = NULL; // set stack's array pointer to nowhere. 135 | printer = NULL; // set the printer of stack to point nowhere. 136 | size = 0; // set the size of stack to zero. 137 | top = 0; // set the initial top index of the stack. 138 | } 139 | 140 | // resize the size of the stack. 141 | template 142 | void StackArray::resize (const int s) { 143 | // defensive issue. 144 | if (s <= 0) 145 | exit ("STACK: error due to undesirable size for stack size."); 146 | 147 | // reallocate enough memory for the array. 148 | contents = (T *) realloc (contents, sizeof (T) * s); 149 | 150 | // if there is a memory allocation error. 151 | if (contents == NULL) 152 | exit ("STACK: insufficient memory to resize stack."); 153 | 154 | // set the new size of the stack. 155 | size = s; 156 | } 157 | 158 | // push an item to the stack. 159 | template 160 | void StackArray::push (const T i) { 161 | // check if the stack is full. 162 | if (isFull ()) 163 | // double size of array. 164 | resize (size * 2); 165 | 166 | // store the item to the array. 167 | contents[top++] = i; 168 | } 169 | 170 | // pop an item from the stack. 171 | template 172 | T StackArray::pop () { 173 | // check if the stack is empty. 174 | if (isEmpty ()) 175 | exit ("STACK: can't pop item from stack: stack is empty."); 176 | 177 | // fetch the top item from the array. 178 | T item = contents[--top]; 179 | 180 | // shrink size of array if necessary. 181 | if (!isEmpty () && (top <= size / 4)) 182 | resize (size / 2); 183 | 184 | // return the top item from the array. 185 | return item; 186 | } 187 | 188 | // get an item from the stack. 189 | template 190 | T StackArray::peek () const { 191 | // check if the stack is empty. 192 | if (isEmpty ()) 193 | exit ("STACK: can't peek item from stack: stack is empty."); 194 | 195 | // get the top item from the array. 196 | return contents[top - 1]; 197 | } 198 | 199 | // get an item from the stack. 200 | template 201 | T StackArray::at(uint16_t n) const { 202 | if (isEmpty()) 203 | exit ("STACK is empty"); 204 | 205 | if (n < 0) 206 | exit("Out of range error, index < 0"); 207 | 208 | if (n > count()-1) 209 | exit("Out of range error, index > n"); 210 | 211 | return contents[n]; 212 | } 213 | 214 | // check if the stack is empty. 215 | template 216 | bool StackArray::isEmpty () const { 217 | return top == 0; 218 | } 219 | 220 | // check if the stack is full. 221 | template 222 | bool StackArray::isFull () const { 223 | return top == size; 224 | } 225 | 226 | // get the number of items in the stack. 227 | template 228 | int StackArray::count () const { 229 | return top; 230 | } 231 | 232 | // set the printer of the stack. 233 | template 234 | void StackArray::setPrinter (Print & p) { 235 | printer = &p; 236 | } 237 | 238 | // exit report method in case of error. 239 | template 240 | void StackArray::exit (const char * m) const { 241 | // print the message if there is a printer. 242 | if (printer) 243 | printer->println (m); 244 | 245 | // loop blinking until hardware reset. 246 | blink (); 247 | } 248 | 249 | // led blinking method in case of error. 250 | template 251 | void StackArray::blink () const { 252 | // set led pin as output. 253 | pinMode (ledPin, OUTPUT); 254 | 255 | // continue looping until hardware reset. 256 | while (true) { 257 | digitalWrite (ledPin, HIGH); // sets the LED on. 258 | delay (250); // pauses 1/4 of second. 259 | digitalWrite (ledPin, LOW); // sets the LED off. 260 | delay (250); // pauses 1/4 of second. 261 | } 262 | 263 | // solution selected due to lack of exit() and assert(). 264 | } 265 | 266 | #endif // _STACKARRAY_H 267 | -------------------------------------------------------------------------------- /Firmware/SoftI2CMaster.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SoftI2CMaster.cpp -- Multi-instance software I2C Master library 3 | * 4 | * 5 | * 2010-12 Tod E. Kurt, http://todbot.com/blog/ 6 | * 7 | * This code takes some tricks from: 8 | * http://codinglab.blogspot.com/2008/10/i2c-on-avr-using-bit-banging.html 9 | * 10 | * 2014, by Testato: update library and examples for follow Wire’s API of Arduino IDE 1.x 11 | * 12 | */ 13 | 14 | #if (ARDUINO >= 100) 15 | #include 16 | #else 17 | #include 18 | #endif 19 | 20 | #include "SoftI2CMaster.h" 21 | 22 | #include 23 | #include 24 | 25 | #define i2cbitdelay 15 26 | 27 | #define I2C_ACK 1 28 | #define I2C_NAK 0 29 | 30 | 31 | #define i2c_scl_release() pinMode(_sclPin,INPUT); 32 | #define i2c_sda_release() pinMode(_sdaPin,INPUT); 33 | 34 | // sets SCL low and drives output 35 | #define i2c_scl_lo() digitalWriteFast(_sclPin,LOW); 36 | 37 | // sets SDA low and drives output 38 | #define i2c_sda_lo() digitalWriteFast(_sdaPin,LOW); 39 | 40 | // set SCL high and to input (releases pin) (i.e. change to input,turnon pullup) 41 | #define i2c_scl_hi() digitalWriteFast(_sclPin,HIGH); 42 | 43 | // set SDA high and to input (releases pin) (i.e. change to input,turnon pullup) 44 | #define i2c_sda_hi() digitalWriteFast(_sdaPin,HIGH); 45 | 46 | 47 | // 48 | // Constructor 49 | // 50 | SoftI2CMaster::SoftI2CMaster() 51 | { 52 | // do nothing, use setPins() later 53 | } 54 | // 55 | SoftI2CMaster::SoftI2CMaster(uint8_t sclPin, uint8_t sdaPin) 56 | { 57 | setPins(sclPin, sdaPin, true); 58 | i2c_init(); 59 | } 60 | 61 | // 62 | SoftI2CMaster::SoftI2CMaster(uint8_t sclPin, uint8_t sdaPin, uint8_t pullups) 63 | { 64 | setPins(sclPin, sdaPin, pullups); 65 | i2c_init(); 66 | } 67 | 68 | // 69 | // Turn Arduino pin numbers into PORTx, DDRx, and PINx 70 | // 71 | void SoftI2CMaster::setPins(uint8_t sclPin, uint8_t sdaPin, uint8_t pullups) 72 | { 73 | uint8_t port; 74 | 75 | usePullups = pullups; 76 | 77 | _sclPin = sclPin; 78 | _sdaPin = sdaPin; 79 | 80 | /* _sclBitMask = digitalPinToBitMask(sclPin); 81 | _sdaBitMask = digitalPinToBitMask(sdaPin); 82 | 83 | port = digitalPinToPort(sclPin); 84 | _sclPortReg = portOutputRegister(port); 85 | _sclDirReg = portModeRegister(port); 86 | 87 | port = digitalPinToPort(sdaPin); 88 | _sdaPortReg = portOutputRegister(port); 89 | _sdaDirReg = portModeRegister(port);*/ 90 | 91 | pinMode(_sclPin,OUTPUT); 92 | pinMode(_sdaPin,OUTPUT); 93 | } 94 | 95 | // 96 | // 97 | // 98 | uint8_t SoftI2CMaster::beginTransmission(uint8_t address) 99 | { 100 | i2c_start(); 101 | uint8_t rc = i2c_write((address<<1) | 0); // clr read bit 102 | return rc; 103 | } 104 | 105 | // 106 | uint8_t SoftI2CMaster::requestFrom(uint8_t address) 107 | { 108 | i2c_start(); 109 | uint8_t rc = i2c_write((address<<1) | 1); // set read bit 110 | return rc; 111 | } 112 | // 113 | uint8_t SoftI2CMaster::requestFrom(int address) 114 | { 115 | return requestFrom( (uint8_t) address); 116 | } 117 | 118 | // 119 | uint8_t SoftI2CMaster::beginTransmission(int address) 120 | { 121 | return beginTransmission((uint8_t)address); 122 | } 123 | 124 | // 125 | // 126 | // 127 | uint8_t SoftI2CMaster::endTransmission(void) 128 | { 129 | i2c_stop(); 130 | //return ret; // FIXME 131 | return 0; 132 | } 133 | 134 | // must be called in: 135 | // slave tx event callback 136 | // or after beginTransmission(address) 137 | uint8_t SoftI2CMaster::write(uint8_t data) 138 | { 139 | return i2c_write(data); 140 | } 141 | 142 | // must be called in: 143 | // slave tx event callback 144 | // or after beginTransmission(address) 145 | void SoftI2CMaster::write(uint8_t* data, uint8_t quantity) 146 | { 147 | for(uint8_t i = 0; i < quantity; ++i){ 148 | write(data[i]); 149 | } 150 | } 151 | 152 | // must be called in: 153 | // slave tx event callback 154 | // or after beginTransmission(address) 155 | void SoftI2CMaster::write(char* data) 156 | { 157 | write((uint8_t*)data, strlen(data)); 158 | } 159 | 160 | // must be called in: 161 | // slave tx event callback 162 | // or after beginTransmission(address) 163 | void SoftI2CMaster::write(int data) 164 | { 165 | write((uint8_t)data); 166 | } 167 | 168 | //-------------------------------------------------------------------- 169 | 170 | 171 | void SoftI2CMaster::i2c_writebit( uint8_t c ) 172 | { 173 | if ( c > 0 ) { 174 | i2c_sda_hi(); 175 | } else { 176 | i2c_sda_lo(); 177 | } 178 | 179 | _delay_us(3); 180 | 181 | i2c_scl_hi(); 182 | _delay_us(6); 183 | 184 | i2c_scl_lo(); 185 | _delay_us(3); 186 | if ( c > 0 ) { 187 | i2c_sda_lo(); 188 | } 189 | } 190 | 191 | /* 192 | sclDelay(8); 193 | // Go to sda high Z mode for input. 194 | writeSda(HIGH); 195 | writeScl(HIGH); 196 | sclDelay(16); 197 | 198 | // Get ACK or NACK. 199 | uint8_t rtn = readSda(); 200 | 201 | // pull scl low. 202 | writeScl(LOW); 203 | 204 | // Pull sda low. 205 | writeSda(LOW); 206 | return rtn == 0; 207 | */ 208 | // 209 | uint8_t SoftI2CMaster::i2c_readbit(void) 210 | { 211 | //i2c_sda_lo(); //Set to ACK, has been NACK, stopping communication before 212 | pinMode(_sdaPin,INPUT); 213 | 214 | // i2c_sda_lo(); 215 | i2c_scl_hi(); 216 | _delay_us(6); 217 | 218 | uint8_t c = digitalReadFast(_sdaPin); 219 | pinMode(_sdaPin,OUTPUT); 220 | 221 | /* uint8_t port = digitalPinToPort(_sdaPin); 222 | volatile uint8_t* pinReg = portInputRegister(port); 223 | uint8_t c = *pinReg; // I2C_PIN;*/ 224 | 225 | // uint8_t c = digitalRead(_sdaPin); 226 | 227 | i2c_scl_lo(); 228 | _delay_us(3); 229 | i2c_sda_lo(); 230 | 231 | _delay_us(i2cbitdelay); 232 | 233 | return c == LOW; 234 | } 235 | 236 | // Inits bitbanging port, must be called before using the functions below 237 | // 238 | void SoftI2CMaster::i2c_init(void) 239 | { 240 | //I2C_PORT &=~ (_BV( I2C_SDA ) | _BV( I2C_SCL )); 241 | //*_sclPortReg &=~ (_sdaBitMask | _sclBitMask); 242 | i2c_sda_hi(); 243 | i2c_scl_hi(); 244 | 245 | _delay_us(i2cbitdelay); 246 | } 247 | 248 | // Send a START Condition 249 | // 250 | void SoftI2CMaster::i2c_start(void) 251 | { 252 | // set both to high at the same time 253 | //I2C_DDR &=~ (_BV( I2C_SDA ) | _BV( I2C_SCL )); 254 | //*_sclDirReg &=~ (_sdaBitMask | _sclBitMask); 255 | i2c_sda_hi(); 256 | i2c_scl_hi(); 257 | 258 | _delay_us(i2cbitdelay); 259 | 260 | i2c_sda_lo(); 261 | _delay_us(i2cbitdelay); 262 | 263 | i2c_scl_lo(); 264 | _delay_us(i2cbitdelay); 265 | } 266 | 267 | void SoftI2CMaster::i2c_repstart(void) 268 | { 269 | // set both to high at the same time (releases drive on both lines) 270 | //I2C_DDR &=~ (_BV( I2C_SDA ) | _BV( I2C_SCL )); 271 | //*_sclDirReg &=~ (_sdaBitMask | _sclBitMask); 272 | i2c_sda_hi(); 273 | i2c_scl_hi(); 274 | 275 | i2c_scl_lo(); // force SCL low 276 | _delay_us(i2cbitdelay); 277 | 278 | i2c_sda_release(); // release SDA 279 | _delay_us(i2cbitdelay); 280 | 281 | i2c_scl_release(); // release SCL 282 | _delay_us(i2cbitdelay); 283 | 284 | i2c_sda_lo(); // force SDA low 285 | _delay_us(i2cbitdelay); 286 | } 287 | 288 | // Send a STOP Condition 289 | // 290 | void SoftI2CMaster::i2c_stop(void) 291 | { 292 | i2c_scl_hi(); 293 | _delay_us(i2cbitdelay); 294 | 295 | i2c_sda_hi(); 296 | _delay_us(i2cbitdelay); 297 | } 298 | 299 | // write a byte to the I2C slave device 300 | // 301 | uint8_t SoftI2CMaster::i2c_write( uint8_t c ) 302 | { 303 | for ( uint8_t i=0;i<8;i++) { 304 | i2c_writebit( c & 128 ); 305 | c<<=1; 306 | } 307 | 308 | _delay_us(8); 309 | 310 | return i2c_readbit(); 311 | } 312 | 313 | // read a byte from the I2C slave device 314 | // 315 | uint8_t SoftI2CMaster::i2c_read( uint8_t ack ) 316 | { 317 | uint8_t res = 0; 318 | 319 | for ( uint8_t i=0;i<8;i++) { 320 | res <<= 1; 321 | res |= i2c_readbit(); 322 | } 323 | 324 | if ( ack ) 325 | i2c_writebit( 0 ); 326 | else 327 | i2c_writebit( 1 ); 328 | 329 | _delay_us(i2cbitdelay); 330 | 331 | return res; 332 | } 333 | 334 | // FIXME: this isn't right, surely 335 | uint8_t SoftI2CMaster::read( uint8_t ack ) 336 | { 337 | return i2c_read( ack ); 338 | } 339 | 340 | // 341 | uint8_t SoftI2CMaster::read() 342 | { 343 | return i2c_read( I2C_ACK ); 344 | } 345 | 346 | // 347 | uint8_t SoftI2CMaster::readLast() 348 | { 349 | return i2c_read( I2C_NAK ); 350 | } 351 | -------------------------------------------------------------------------------- /Firmware/ScopeSceneController.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Little Helper -- your best friend in your lab 3 | * http://www.appfruits.com/littlehelper 4 | * 5 | * This software is part of the firmware running Little Helper. You may use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software 7 | * but you must include this copyright notice and this permission in all copies or 8 | * substantial portions of the Software. 9 | * 10 | * Appfruits invests time and resources to make this open source. Please support us 11 | * and the open-source hardware initiative. 12 | * 13 | * Copyright 2014-2015 Phillip Schuster (@appfruits) 14 | * http://www.appfruits.com 15 | * 16 | * MIT-License 17 | */ 18 | 19 | #include "ScopeSceneController.h" 20 | 21 | static ScopeSceneController* _currentScopeSceneController = NULL; 22 | static bool inInterrupt = false; 23 | 24 | void onScopeTimerTick(void) 25 | { 26 | if (_currentScopeSceneController != NULL) 27 | { 28 | int sample = Pins.getPin(1)->analogRead(); 29 | _currentScopeSceneController->addSample(sample); 30 | } 31 | } 32 | 33 | ScopeSceneController::ScopeSceneController(): 34 | _scopeView(this,MINX,MINY,MAXW,MAXH-20), 35 | _menuView("Controls",MINX,MINY+MAXH-20,MAXW,20,false), 36 | _numSamples(0), 37 | _paused(false), 38 | _labelView("Hallo",MINX,MINY+40,MAXW,15) 39 | { 40 | _scopeView.setDelegate(this); 41 | _scopeView._currentRecord = &_record; 42 | _numTriggers = 0; 43 | _triggerSlot = 0; 44 | _triggered = false; 45 | _previousSample = 0; 46 | _triggerSlope = Slope::Raising; 47 | 48 | _xScaleItemView = new MenuItemWheelView("xS",this); 49 | //_xScaleItemView->setTitle("<*>"); 50 | _xScaleItemView->setLimits(0.1f,10.0f); 51 | 52 | _xPosItemView = new MenuItemWheelView("xP",this); 53 | //_xPosItemView->setTitle("<+>"); 54 | _xPosItemView->setLimits(-64,64); 55 | 56 | _triggerItemView = new MenuItemEnumView("T",this); 57 | _triggerItemView->addItem(0,"Raise"); 58 | _triggerItemView->addItem(1,"Fall"); 59 | _triggerItemView->addItem(2,"Both"); 60 | _triggerItemView->addItem(3,"Off"); 61 | 62 | _menuView.addMenuItem(_xScaleItemView); 63 | _menuView.addMenuItem(_xPosItemView); 64 | _menuView.addMenuItem(_triggerItemView); 65 | } 66 | 67 | 68 | String ScopeSceneController::getName() 69 | { 70 | return "ScopeSceneController"; 71 | } 72 | 73 | bool ScopeSceneController::isPaused() 74 | { 75 | return _paused; 76 | } 77 | 78 | void ScopeSceneController::onWillAppear() 79 | { 80 | SceneController::onWillAppear(); 81 | 82 | Pins.activatePin(1,"Channel 1"); 83 | //Pins.activatePin(2,"Channel 2"); 84 | Pins.activatePin(PIN_GND,"GND"); 85 | 86 | Pins.getPin(1)->setPinMode(INPUT); 87 | //Pins.getPin(2)->setPinMode(INPUT); 88 | 89 | Application.getStatusBar()->setCaption("Scope"); 90 | 91 | _menuView.setFocus(); 92 | 93 | _currentScopeSceneController = this; 94 | 95 | _timer.begin(onScopeTimerTick,500); 96 | } 97 | 98 | void ScopeSceneController::onWillDisappear() 99 | { 100 | SceneController::onWillDisappear(); 101 | 102 | _timer.end(); 103 | _currentScopeSceneController = NULL; 104 | } 105 | 106 | /* 107 | * 108 | * display.println(length+start); 109 | this->_delegate->copySamples(numSamples+start,abs(start),&_samples[0]); 110 | this->_delegate->copySamples(0,length + start,&_samples[abs(start)]); 111 | } 112 | else 113 | { 114 | if (end < numSamples) 115 | { 116 | display.print("S-Start:"); 117 | display.println(start); 118 | display.print("S-Length:"); 119 | display.println(length); 120 | display.println(length+start); 121 | 122 | this->_delegate->copySamples(start,length,&_samples[0]); 123 | } 124 | else 125 | { 126 | display.print("S1-Start:"); 127 | display.println(start); 128 | display.print("S2-Length:"); 129 | display.println(numSamples-start); 130 | display.print("S2-Start:"); 131 | display.println(0); 132 | display.print("S2-Length"); 133 | display.println(end-numSamples); 134 | 135 | this->_delegate->copySamples(start,numSamples-start,&_samples[0]); 136 | this->_delegate->copySamples(0,end-numSamples,&_samples[numSamples-start]); 137 | } 138 | } 139 | */ 140 | 141 | void ScopeSceneController::copySamples(int start, int end, Record *record) 142 | { 143 | int s = start; 144 | int l = end - start; 145 | if (start < 0) 146 | { 147 | s = MAX_SAMPLES + start; 148 | l = abs(start); 149 | 150 | memcpy(&record->samples[0],&_samples[s],sizeof(int)*l); 151 | memcpy(&record->samples[l],&_samples[0],sizeof(int)*end); 152 | } 153 | else 154 | { 155 | if (end < MAX_SAMPLES) 156 | { 157 | memcpy(&record->samples[0],&_samples[s],sizeof(int)*l); 158 | } 159 | else 160 | { 161 | l = MAX_SAMPLES - start; 162 | memcpy(&record->samples[0],&_samples[start],sizeof(int)*l); 163 | memcpy(&record->samples[l],&_samples[0],sizeof(int)*(end-MAX_SAMPLES)); 164 | } 165 | } 166 | } 167 | 168 | void ScopeSceneController::addSample(int value) 169 | { 170 | if (inInterrupt) return; 171 | inInterrupt = true; 172 | if (_paused) return; 173 | 174 | _samples[_numSamples] = value; 175 | 176 | if (_triggered == false) 177 | { 178 | //Check triggers 179 | bool triggered = false; 180 | if (_triggerSlope == Slope::Falling && (_previousSample-value > 500)) 181 | { 182 | triggered = true; 183 | } 184 | if (_triggerSlope == Slope::Raising && (value - _previousSample > 500)) 185 | { 186 | triggered = true; 187 | } 188 | if (_triggerSlope == Slope::Both && (abs(_previousSample-value) > 500)) 189 | { 190 | triggered = true; 191 | } 192 | 193 | if (triggered) 194 | { 195 | { 196 | _samplesInTrigger = 0; 197 | _currentTriggerSlot = _numSamples; 198 | _triggered = true; 199 | _numTriggers++; 200 | } 201 | } 202 | } 203 | else 204 | { 205 | _samplesInTrigger++; 206 | if (_samplesInTrigger > 64) 207 | { 208 | _triggered = false; 209 | _triggerSlot = _currentTriggerSlot; 210 | _triggers[_numTriggers] = _triggerSlot; 211 | } 212 | } 213 | 214 | //Advance memory position 215 | _numSamples++; 216 | if (_numSamples >= MAX_SAMPLES) 217 | { 218 | _numSamples = 0; 219 | 220 | /* _paused = true; 221 | 222 | Serial.println("Samples"); 223 | for (int i=0;i_lastTriggerSlot = this->_triggerSlot; 272 | interrupts(); 273 | } 274 | else if (_triggerSlope == Slope::Off) 275 | { 276 | _record.reset(); 277 | noInterrupts(); 278 | int numSamples = _numSamples; 279 | interrupts(); 280 | _record.startPos = numSamples - 1 - 128; 281 | _record.endPos = numSamples - 1; 282 | 283 | copySamples(_record.startPos,_record.endPos,&_record); 284 | _scopeView.setNeedsDisplay(); 285 | } 286 | } 287 | 288 | if (_paused) 289 | { 290 | //_scopeView.update(); 291 | } 292 | else 293 | { 294 | /* int sample = Pins.getPin(1)->analogRead(); 295 | //sample = random(-127,127); 296 | 297 | _samples[_numSamples] = sample; 298 | _numSamples++; 299 | if (_numSamples >= MAX_SAMPLES) 300 | { 301 | _numSamples = 0; 302 | _scopeView.setCursor(0); 303 | } 304 | 305 | _scopeView.setCursor(_scopeView.getCursor()+1);*/ 306 | 307 | //_scopeView.setNeedsDisplay(); 308 | //_scopeView.update(); 309 | } 310 | 311 | _scopeView.update(); 312 | _labelView.update(); 313 | _menuView.update(); 314 | } 315 | 316 | void ScopeSceneController::onPause(ScopeView *scopeView) 317 | { 318 | _paused = !_paused; 319 | 320 | if (_paused) { 321 | _timer.end(); 322 | leds.setPixelColor(0,128,0,0); 323 | leds.show(); 324 | } 325 | else 326 | { 327 | _timer.begin(onScopeTimerTick,250); 328 | leds.setPixelColor(0,0,128,0); 329 | leds.show(); 330 | } 331 | } 332 | 333 | uint16_t ScopeSceneController::getNumberOfSamples() 334 | { 335 | return MAX_SAMPLES; 336 | } 337 | 338 | int ScopeSceneController::getSampleAtIndex(uint16_t index) 339 | { 340 | noInterrupts(); 341 | int sample = _samples[index]; 342 | interrupts(); 343 | return sample; 344 | } 345 | 346 | bool ScopeSceneController::copySamples(uint16_t start, uint16_t length, int *buffer) 347 | { 348 | if (start+length >= MAX_SAMPLES-1) return false; 349 | if (start < 0) return false; 350 | 351 | noInterrupts(); 352 | memcpy(buffer,&_samples[start],length*sizeof(int)); 353 | interrupts(); 354 | return true; 355 | } 356 | 357 | float ScopeSceneController::getSamplesPerSecond() 358 | { 359 | noInterrupts(); 360 | float sps = _samplesPerSecond; 361 | interrupts(); 362 | return sps; 363 | } 364 | 365 | void ScopeSceneController::xSystemChanged() 366 | { 367 | int interval = _xScale * 1000; 368 | _timer.end(); 369 | _record.reset(); 370 | _timer.begin(onScopeTimerTick,interval); 371 | 372 | _scopeView.setNeedsDisplay(); 373 | } 374 | 375 | Record *ScopeSceneController::getRecord() 376 | { 377 | return &_record; 378 | } 379 | 380 | void ScopeSceneController::menuItemViewTriggered(MenuItemView *menuItemView) 381 | { 382 | 383 | } 384 | 385 | void ScopeSceneController::menuItemViewValueChanged(MenuItemView *menuItemView, float value) 386 | { 387 | if (menuItemView == _xScaleItemView) 388 | { 389 | _xScale = value; 390 | 391 | xSystemChanged(); 392 | } 393 | else if (menuItemView == _xPosItemView) 394 | { 395 | _xPos = value; 396 | 397 | xSystemChanged(); 398 | } 399 | else if (menuItemView == _triggerItemView) 400 | { 401 | _triggerSlope = value; 402 | } 403 | } 404 | -------------------------------------------------------------------------------- /Firmware/Adafruit_mfGFX.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This is the core graphics library for all our displays, providing a common 3 | set of graphics primitives (points, lines, circles, etc.). It needs to be 4 | paired with a hardware-specific library for each display device we carry 5 | (to handle the lower-level functions). 6 | 7 | Adafruit invests time and resources providing this open source code, please 8 | support Adafruit & open-source hardware by purchasing products from Adafruit! 9 | 10 | Copyright (c) 2013 Adafruit Industries. All rights reserved. 11 | 12 | Redistribution and use in source and binary forms, with or without 13 | modification, are permitted provided that the following conditions are met: 14 | 15 | - Redistributions of source code must retain the above copyright notice, 16 | this list of conditions and the following disclaimer. 17 | - Redistributions in binary form must reproduce the above copyright notice, 18 | this list of conditions and the following disclaimer in the documentation 19 | and/or other materials provided with the distribution. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 25 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include "Adafruit_mfGFX.h" 35 | #include "fonts.h" 36 | 37 | 38 | //#define pgm_read_byte(addr) (*(const uint8_t *)(addr)) 39 | 40 | 41 | Adafruit_GFX::Adafruit_GFX(int16_t w, int16_t h): 42 | WIDTH(w), HEIGHT(h) 43 | { 44 | _width = WIDTH; 45 | _height = HEIGHT; 46 | rotation = 0; 47 | cursor_y = cursor_x = 0; 48 | textsize = 1; 49 | textcolor = textbgcolor = 0xFFFF; 50 | wrap = true; 51 | // Default to GLCDFONT to be compatible with existing code 52 | setFont(GLCDFONT); // May also be set to TIMESNR_8, CENTURY_8, COMICS_8 or TEST (for testing candidate fonts) 53 | } 54 | 55 | void Adafruit_GFX::setFont(uint8_t f) { 56 | font = f; 57 | switch(font) { 58 | case TIMESNR_8: 59 | fontData = timesNewRoman_8ptBitmaps; 60 | fontDesc = timesNewRoman_8ptDescriptors; 61 | fontKern = 1; 62 | break; 63 | case CENTURY_8: 64 | fontData = centuryGothic_8ptBitmaps; 65 | fontDesc = centuryGothic_8ptDescriptors; 66 | fontKern = 1; 67 | break; 68 | case ARIAL_8: 69 | fontData = arial_8ptBitmaps; 70 | fontDesc = arial_8ptDescriptors; 71 | fontKern = 1; 72 | break; 73 | case ARIAL_16: 74 | fontData = arial_16ptBitmaps; 75 | fontDesc = arial_16ptDescriptors; 76 | fontKern = 1; 77 | break; 78 | case COMICS_8: 79 | fontData = comicSansMS_8ptBitmaps; 80 | fontDesc = comicSansMS_8ptDescriptors; 81 | fontKern = 1; 82 | break; 83 | case GLCDFONT: 84 | fontData = glcdfontBitmaps; 85 | fontDesc = glcdfontDescriptors; 86 | fontKern = 1; 87 | break; 88 | case TEST: 89 | fontData = testBitmaps; 90 | fontDesc = testDescriptors; 91 | fontKern = 1; 92 | break; 93 | case SEGOE_8: 94 | fontData = segoeUI_8ptBitmaps; 95 | fontDesc = segoeUI_8ptDescriptors; 96 | fontKern = 1; 97 | break; 98 | case SEGOE_16: 99 | fontData = segoeUI_16ptBitmaps; 100 | fontDesc = segoeUI_16ptDescriptors; 101 | fontKern = 1; 102 | break; 103 | case CALIBRI_16: 104 | fontData = calibri_16ptBitmaps; 105 | fontDesc = calibri_16ptDescriptors; 106 | fontKern = 1; 107 | break; 108 | default: 109 | font = ARIAL_8; 110 | fontData = arial_8ptBitmaps; 111 | fontDesc = arial_8ptDescriptors; 112 | fontKern = 1; 113 | break; 114 | } 115 | 116 | fontStart = pgm_read_byte(fontData+FONT_START); 117 | fontEnd = pgm_read_byte(fontData+FONT_END); 118 | } 119 | 120 | // Draw a circle outline 121 | void Adafruit_GFX::drawCircle(int16_t x0, int16_t y0, int16_t r, 122 | uint16_t color) { 123 | int16_t f = 1 - r; 124 | int16_t ddF_x = 1; 125 | int16_t ddF_y = -2 * r; 126 | int16_t x = 0; 127 | int16_t y = r; 128 | 129 | drawPixel(x0 , y0+r, color); 130 | drawPixel(x0 , y0-r, color); 131 | drawPixel(x0+r, y0 , color); 132 | drawPixel(x0-r, y0 , color); 133 | 134 | while (x= 0) { 136 | y--; 137 | ddF_y += 2; 138 | f += ddF_y; 139 | } 140 | x++; 141 | ddF_x += 2; 142 | f += ddF_x; 143 | 144 | drawPixel(x0 + x, y0 + y, color); 145 | drawPixel(x0 - x, y0 + y, color); 146 | drawPixel(x0 + x, y0 - y, color); 147 | drawPixel(x0 - x, y0 - y, color); 148 | drawPixel(x0 + y, y0 + x, color); 149 | drawPixel(x0 - y, y0 + x, color); 150 | drawPixel(x0 + y, y0 - x, color); 151 | drawPixel(x0 - y, y0 - x, color); 152 | } 153 | } 154 | 155 | void Adafruit_GFX::drawCircleHelper( int16_t x0, int16_t y0, 156 | int16_t r, uint8_t cornername, uint16_t color) { 157 | int16_t f = 1 - r; 158 | int16_t ddF_x = 1; 159 | int16_t ddF_y = -2 * r; 160 | int16_t x = 0; 161 | int16_t y = r; 162 | 163 | while (x= 0) { 165 | y--; 166 | ddF_y += 2; 167 | f += ddF_y; 168 | } 169 | x++; 170 | ddF_x += 2; 171 | f += ddF_x; 172 | if (cornername & 0x4) { 173 | drawPixel(x0 + x, y0 + y, color); 174 | drawPixel(x0 + y, y0 + x, color); 175 | } 176 | if (cornername & 0x2) { 177 | drawPixel(x0 + x, y0 - y, color); 178 | drawPixel(x0 + y, y0 - x, color); 179 | } 180 | if (cornername & 0x8) { 181 | drawPixel(x0 - y, y0 + x, color); 182 | drawPixel(x0 - x, y0 + y, color); 183 | } 184 | if (cornername & 0x1) { 185 | drawPixel(x0 - y, y0 - x, color); 186 | drawPixel(x0 - x, y0 - y, color); 187 | } 188 | } 189 | } 190 | 191 | void Adafruit_GFX::fillCircle(int16_t x0, int16_t y0, int16_t r, 192 | uint16_t color) { 193 | drawFastVLine(x0, y0-r, 2*r+1, color); 194 | fillCircleHelper(x0, y0, r, 3, 0, color); 195 | } 196 | 197 | // Used to do circles and roundrects 198 | void Adafruit_GFX::fillCircleHelper(int16_t x0, int16_t y0, int16_t r, 199 | uint8_t cornername, int16_t delta, uint16_t color) { 200 | 201 | int16_t f = 1 - r; 202 | int16_t ddF_x = 1; 203 | int16_t ddF_y = -2 * r; 204 | int16_t x = 0; 205 | int16_t y = r; 206 | 207 | while (x= 0) { 209 | y--; 210 | ddF_y += 2; 211 | f += ddF_y; 212 | } 213 | x++; 214 | ddF_x += 2; 215 | f += ddF_x; 216 | 217 | if (cornername & 0x1) { 218 | drawFastVLine(x0+x, y0-y, 2*y+1+delta, color); 219 | drawFastVLine(x0+y, y0-x, 2*x+1+delta, color); 220 | } 221 | if (cornername & 0x2) { 222 | drawFastVLine(x0-x, y0-y, 2*y+1+delta, color); 223 | drawFastVLine(x0-y, y0-x, 2*x+1+delta, color); 224 | } 225 | } 226 | } 227 | 228 | // Bresenham's algorithm - thx wikpedia 229 | void Adafruit_GFX::drawLine(int16_t x0, int16_t y0, 230 | int16_t x1, int16_t y1, 231 | uint16_t color) { 232 | int16_t steep = abs(y1 - y0) > abs(x1 - x0); 233 | if (steep) { 234 | swap(x0, y0); 235 | swap(x1, y1); 236 | } 237 | 238 | if (x0 > x1) { 239 | swap(x0, x1); 240 | swap(y0, y1); 241 | } 242 | 243 | int16_t dx, dy; 244 | dx = x1 - x0; 245 | dy = abs(y1 - y0); 246 | 247 | int16_t err = dx / 2; 248 | int16_t ystep; 249 | 250 | if (y0 < y1) { 251 | ystep = 1; 252 | } else { 253 | ystep = -1; 254 | } 255 | 256 | for (; x0<=x1; x0++) { 257 | if (steep) { 258 | drawPixel(y0, x0, color); 259 | } else { 260 | drawPixel(x0, y0, color); 261 | } 262 | err -= dy; 263 | if (err < 0) { 264 | y0 += ystep; 265 | err += dx; 266 | } 267 | } 268 | } 269 | 270 | // Draw a rectangle 271 | void Adafruit_GFX::drawRect(int16_t x, int16_t y, 272 | int16_t w, int16_t h, 273 | uint16_t color) { 274 | drawFastHLine(x, y, w, color); 275 | drawFastHLine(x, y+h-1, w, color); 276 | drawFastVLine(x, y, h, color); 277 | drawFastVLine(x+w-1, y, h, color); 278 | } 279 | 280 | void Adafruit_GFX::drawFastVLine(int16_t x, int16_t y, 281 | int16_t h, uint16_t color) { 282 | // Update in subclasses if desired! 283 | drawLine(x, y, x, y+h-1, color); 284 | } 285 | 286 | void Adafruit_GFX::drawFastHLine(int16_t x, int16_t y, 287 | int16_t w, uint16_t color) { 288 | // Update in subclasses if desired! 289 | drawLine(x, y, x+w-1, y, color); 290 | } 291 | 292 | void Adafruit_GFX::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, 293 | uint16_t color) { 294 | // Update in subclasses if desired! 295 | for (int16_t i=x; i= y1 >= y0) 347 | if (y0 > y1) { 348 | swap(y0, y1); swap(x0, x1); 349 | } 350 | if (y1 > y2) { 351 | swap(y2, y1); swap(x2, x1); 352 | } 353 | if (y0 > y1) { 354 | swap(y0, y1); swap(x0, x1); 355 | } 356 | 357 | if(y0 == y2) { // Handle awkward all-on-same-line case as its own thing 358 | a = b = x0; 359 | if(x1 < a) a = x1; 360 | else if(x1 > b) b = x1; 361 | if(x2 < a) a = x2; 362 | else if(x2 > b) b = x2; 363 | drawFastHLine(a, y0, b-a+1, color); 364 | return; 365 | } 366 | 367 | int16_t 368 | dx01 = x1 - x0, 369 | dy01 = y1 - y0, 370 | dx02 = x2 - x0, 371 | dy02 = y2 - y0, 372 | dx12 = x2 - x1, 373 | dy12 = y2 - y1, 374 | sa = 0, 375 | sb = 0; 376 | 377 | // For upper part of triangle, find scanline crossings for segments 378 | // 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1 379 | // is included here (and second loop will be skipped, avoiding a /0 380 | // error there), otherwise scanline y1 is skipped here and handled 381 | // in the second loop...which also avoids a /0 error here if y0=y1 382 | // (flat-topped triangle). 383 | if(y1 == y2) last = y1; // Include y1 scanline 384 | else last = y1-1; // Skip it 385 | 386 | for(y=y0; y<=last; y++) { 387 | a = x0 + sa / dy01; 388 | b = x0 + sb / dy02; 389 | sa += dx01; 390 | sb += dx02; 391 | /* longhand: 392 | a = x0 + (x1 - x0) * (y - y0) / (y1 - y0); 393 | b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); 394 | */ 395 | if(a > b) swap(a,b); 396 | drawFastHLine(a, y, b-a+1, color); 397 | } 398 | 399 | // For lower part of triangle, find scanline crossings for segments 400 | // 0-2 and 1-2. This loop is skipped if y1=y2. 401 | sa = dx12 * (y - y1); 402 | sb = dx02 * (y - y0); 403 | for(; y<=y2; y++) { 404 | a = x1 + sa / dy12; 405 | b = x0 + sb / dy02; 406 | sa += dx12; 407 | sb += dx02; 408 | /* longhand: 409 | a = x1 + (x2 - x1) * (y - y1) / (y2 - y1); 410 | b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); 411 | */ 412 | if(a > b) swap(a,b); 413 | drawFastHLine(a, y, b-a+1, color); 414 | } 415 | } 416 | 417 | void Adafruit_GFX::drawBitmap(int16_t x, int16_t y, 418 | const uint8_t *bitmap, int16_t w, int16_t h, 419 | uint16_t color) { 420 | 421 | int16_t i, j, byteWidth = (w + 7) / 8; 422 | 423 | for(j=0; j> (i & 7))) { 426 | drawPixel(x+i, y+j, color); 427 | } 428 | } 429 | } 430 | } 431 | 432 | size_t Adafruit_GFX::write(uint8_t c) { 433 | 434 | if (c == '\n') { 435 | cursor_y += textsize*fontDesc[0].height; //all chars are same height so use height of space char 436 | cursor_x = 0; 437 | } else if (c == '\r') { 438 | // skip em 439 | } else { 440 | drawFastChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize); 441 | uint16_t w = fontDesc[c-fontStart].width; 442 | uint16_t h = fontDesc[c-fontStart].height; 443 | if (fontKern > 0 && textcolor != textbgcolor) { 444 | fillRect(cursor_x+w*textsize,cursor_y,fontKern*textsize,h*textsize,textbgcolor); 445 | } 446 | cursor_x += textsize*(w+fontKern); 447 | if (wrap && (cursor_x > (_width - textsize*w))) { 448 | cursor_y += textsize*h; 449 | cursor_x = 0; 450 | } 451 | } 452 | return 1; 453 | } 454 | 455 | void Adafruit_GFX::drawFastChar(int16_t x, int16_t y, unsigned char c, 456 | uint16_t color, uint16_t bg, uint8_t size) { 457 | // Update in subclasses if desired! 458 | drawChar(x,y,c,color,bg,size); 459 | } 460 | 461 | // Draw a character 462 | void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c, 463 | uint16_t color, uint16_t bg, uint8_t size) { 464 | 465 | if (c < fontStart || c > fontEnd) { 466 | c = 0; 467 | } 468 | else { 469 | c -= fontStart; 470 | } 471 | 472 | if((x >= _width) || // Clip right 473 | (y >= _height) || // Clip bottom 474 | ((x + (fontDesc[c].width * size) - 1) < 0) || // Clip left 475 | ((y + (fontDesc[c].height * size) - 1) < 0)) // Clip top 476 | return; 477 | 478 | uint8_t bitCount=0; 479 | uint16_t fontIndex = fontDesc[c].offset + 2; //((fontDesc + c)->offset) + 2; 480 | 481 | for (int8_t i=0; i 0) ? s : 1; 514 | } 515 | 516 | void Adafruit_GFX::setTextColor(uint16_t c) { 517 | // For 'transparent' background, we'll set the bg 518 | // to the same as fg instead of using a flag 519 | textcolor = textbgcolor = c; 520 | } 521 | 522 | void Adafruit_GFX::setTextColor(uint16_t c, uint16_t b) { 523 | textcolor = c; 524 | textbgcolor = b; 525 | } 526 | 527 | void Adafruit_GFX::setTextWrap(boolean w) { 528 | wrap = w; 529 | } 530 | 531 | uint8_t Adafruit_GFX::getRotation(void) { 532 | return rotation; 533 | } 534 | 535 | void Adafruit_GFX::setRotation(uint8_t x) { 536 | rotation = (x & 3); 537 | switch(rotation) { 538 | case 0: 539 | case 2: 540 | _width = WIDTH; 541 | _height = HEIGHT; 542 | break; 543 | case 1: 544 | case 3: 545 | _width = HEIGHT; 546 | _height = WIDTH; 547 | break; 548 | } 549 | } 550 | 551 | // Return the size of the display (per current rotation) 552 | int16_t Adafruit_GFX::width(void) { 553 | return _width; 554 | } 555 | 556 | int16_t Adafruit_GFX::height(void) { 557 | return _height; 558 | } 559 | 560 | void Adafruit_GFX::invertDisplay(boolean i) { 561 | // Do nothing, must be subclassed if supported 562 | } 563 | --------------------------------------------------------------------------------