Implement ui stuff

This commit is contained in:
Jan-Henrik 2019-10-28 18:56:37 +01:00
parent 77d8c2d97e
commit e9368dd5a5
7 changed files with 223 additions and 8 deletions

6
midi2cv/.lvimrc Normal file
View file

@ -0,0 +1,6 @@
:packadd termdebug
let termdebugger = "/usr/bin/arm-none-eabi-gdb"
:map <c-d> :Termdebug /home/jhbruhn/eurorack/eurorack-dev-environment/eurorack-modules/build/midi2cv/midi2cv.elf --eval-command='target remote localhost:3333'

View file

@ -22,8 +22,6 @@ u8g2_t* Display::u8g2()
return &u8g2_;
}
void InitSPI(void);
void Display::Init()
{
// init SS/CS/RST GPIO

View file

@ -0,0 +1,56 @@
// Copyright 2013 Emilie Gillet.
//
// Author: Emilie Gillet (emilie.o.gillet@gmail.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// See http://creativecommons.org/licenses/MIT/ for more information.
//
// -----------------------------------------------------------------------------
//
// Driver for rotary encoder.
#include "midi2cv/drivers/encoder.h"
void Encoder::Init() {
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
GPIO_InitTypeDef gpio_init;
gpio_init.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
gpio_init.GPIO_Speed = GPIO_Speed_10MHz;
gpio_init.GPIO_Mode = GPIO_Mode_IN;
gpio_init.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOC, &gpio_init);
switch_state_ = 0xff;
quadrature_decoding_state_[0] = quadrature_decoding_state_[1] = 0xff;
}
void Encoder::Debounce() {
switch_state_ = (switch_state_ << 1) | \
GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_15);
quadrature_decoding_state_[0] = (quadrature_decoding_state_[0] << 1) | \
GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_13);
quadrature_decoding_state_[1] = (quadrature_decoding_state_[1] << 1) | \
GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_14);
}

82
midi2cv/drivers/encoder.h Normal file
View file

@ -0,0 +1,82 @@
// Copyright 2013 Emilie Gillet.
//
// Author: Emilie Gillet (emilie.o.gillet@gmail.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// See http://creativecommons.org/licenses/MIT/ for more information.
//
// -----------------------------------------------------------------------------
//
// Driver for rotary encoder.
#ifndef YARNS_DRIVERS_ENCODER_H_
#define YARNS_DRIVERS_ENCODER_H_
#include <stm32f37x_conf.h>
#include "stmlib/stmlib.h"
class Encoder {
public:
Encoder() { }
~Encoder() { }
void Init();
void Debounce();
inline bool released() const {
return switch_state_ == 0x7f;
}
inline bool just_pressed() const {
return switch_state_ == 0x80;
}
inline bool pressed() const {
return switch_state_ == 0x00;
}
inline bool pressed_immediate() const {
return !GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_15);
}
inline int32_t increment() const {
int32_t increment = 0;
uint8_t a = quadrature_decoding_state_[0];
uint8_t b = quadrature_decoding_state_[1];
if ((a & 0x03) == 0x02 && (b & 0x03) == 0x00) {
increment = -1;
} else {
if ((b & 0x03) == 0x02 && (a & 0x03) == 0x00) {
increment = 1;
}
}
return increment;
}
private:
uint8_t switch_state_;
uint8_t quadrature_decoding_state_[2];
DISALLOW_COPY_AND_ASSIGN(Encoder);
};
extern Encoder encoder;
#endif // YARNS_DRIVERS_ENCODER_H_

View file

@ -1,6 +1,7 @@
#include <stm32f37x_conf.h>
#include "drivers/display.h"
#include "drivers/encoder.h"
#include "drivers/gpio.h"
#include "part.h"
#include "stmlib/system/system_clock.h"
@ -10,8 +11,9 @@ using namespace stmlib;
GPIO gpio;
Display display;
Encoder encoder;
UI ui;
//SystemClock system_clock;
Part part[PART_COUNT];
// Default interrupt handlers.
@ -46,6 +48,7 @@ void SysTick_Handler()
{
IWDG_ReloadCounter();
system_clock.Tick();
ui.Poll();
}
void TIM2_IRQHandler(void)
@ -116,6 +119,8 @@ void Init(void)
gpio.Init();
// asm("bkpt #0");
display.Init();
encoder.Init();
ui.Init();
InitTimers();
}
@ -125,6 +130,8 @@ int main(void)
while (1) {
// In this loop we do things that dont depend on any timing, but that have to be done.
// you should not write on spi here because that should happen in the TIM2 interrupt
ui.Update();
// do we want to call the watchdog here? it's the only part thats getting interrupted after all
// (next to the interrupts themselves potentially interrupting each other)
ui.DoEvents();
}
}

View file

@ -1,5 +1,6 @@
#include "ui.h"
#include "drivers/display.h"
#include "midi2cv/drivers/encoder.h"
#include "part.h"
#include "stmlib/utils/random.h"
#include <u8g2.h>
@ -10,9 +11,23 @@ using namespace stmlib;
const char part_names[4][2] = { "A", "B", "C", "D" };
void UI::Update()
void UI::Init()
{
input_queue.Init();
}
void UI::Poll()
{
encoder.Debounce();
int32_t increment = encoder.increment();
if (increment != 0) {
input_queue.AddEvent(CONTROL_ENCODER, 0, increment);
}
}
void UI::Draw() {
u8g2_ClearBuffer(display.u8g2());
switch (current_menu) {
case MENU_PART_1:
case MENU_PART_2:
@ -25,6 +40,7 @@ void UI::Update()
break;
}
display.Swap();
}
@ -53,3 +69,43 @@ void UI::Flush()
{
display.Flush();
}
bool UI::DoEvents()
{
bool refresh_display = false;
while (input_queue.available()) {
Event e = input_queue.PullEvent();
if (e.control_type == CONTROL_ENCODER_CLICK) {
OnClick();
} else if (e.control_type == CONTROL_ENCODER_LONG_CLICK) {
OnLongClick();
} else if (e.control_type == CONTROL_ENCODER) {
OnIncrement(e);
}
refresh_display = true;
}
if (input_queue.idle_time() > 1000) {
refresh_display = true;
}
if(refresh_display) {
input_queue.Touch();
Draw();
}
return refresh_display;
}
void UI::OnClick()
{
}
void UI::OnLongClick()
{
}
void UI::OnIncrement(Event& e)
{
current_menu = (Menu_t) (((uint32_t)current_menu + e.data) % MENU_COUNT);
}

View file

@ -2,9 +2,10 @@
#define MIDI2CV_UI_H
#include "stmlib/stmlib.h"
#include "stmlib/ui/event_queue.h"
typedef enum {
MENU_PART_1,
MENU_PART_1 = 0,
MENU_PART_2,
MENU_PART_3,
MENU_PART_4,
@ -16,15 +17,24 @@ class UI {
UI() {}
~UI() {}
void Update();
void Init();
void Poll();
void Flush();
bool DoEvents();
private:
Menu_t current_menu;
Menu_t current_menu;
stmlib::EventQueue<16> input_queue;
void Draw();
void DrawHeader();
void DrawPartMenu(Menu_t menu);
void OnClick();
void OnLongClick();
void OnIncrement(stmlib::Event &e);
DISALLOW_COPY_AND_ASSIGN(UI);
};