Open FFBoard
Open source force feedback firmware
MidiMain.cpp
Go to the documentation of this file.
1/*
2 * MidiMain.cpp
3 *
4 * Created on: 23.01.2020
5 * Author: Yannick
6 */
7
8#include "target_constants.h"
9#ifdef MIDI
10#include <MidiMain.h>
11
12#include "math.h"
13#include "ledEffects.h"
14#include "USBdevice.h"
15#include "cmsis_os2.h"
16
18 .name = "MIDI (TMC)" ,
19 .id=CLSID_MAIN_MIDI, // 64 prev
20 .visibility = ClassVisibility::debug
21 };
22
24 return info;
25}
26
27
29 // Generate notes
30 for(uint8_t i = 0;i<128;i++){
31 float f = std::pow(2, (i - 69) / 12.0) * 440.0;
32 this->noteToFreq[i] = f;
33 }
34
35 // Setup timer
36 extern TIM_HandleTypeDef TIM_USER;
37 this->timer_update = &TIM_USER; // Timer setup with prescaler of sysclock
38 this->timer_update->Instance->ARR = period;
39 this->timer_update->Instance->PSC = (SystemCoreClock / 1000000)-1;
40 this->timer_update->Instance->CR1 = 1;
41
42
43 // Setup one TMC for first channel
44 this->drv = std::make_unique<TMC_1>();
45 TMC4671Limits limits;
46 drv->setLimits(limits);
47 drv->setEncoderType(EncoderType_TMC::NONE);
48
49 //drv->setMotorType(MotorType::STEPPER, 50);
50 if(drv->conf.motconf.motor_type == MotorType::NONE){
52 }
53 //drv->Start(); // We do not start the driver thread
54
55 drv->setPhiEtype(PhiE::ext);
56 drv->setUdUq(0, 0);
57 drv->allowSlowSPI = false; // Force higher speed
58 if(!drv->initialize()){
60 }
61
62 drv->setPhiEtype(PhiE::ext);
63 drv->setMotionMode(MotionMode::uqudext,true);
64
65
66 //CommandHandler::registerCommands();
67 registerCommand("power", MidiMain_commands::power, "Intensity",CMDFLAG_GET|CMDFLAG_SET);
68 registerCommand("range", MidiMain_commands::range, "Range of phase change",CMDFLAG_GET|CMDFLAG_SET);
69
70 HAL_TIM_Base_Start_IT(this->timer_update);
71}
72
74
75}
76
77
79 osDelay(500); // Slow down main thread
80 if(drv->hasPower() &&!drv->isSetUp()){
81 drv->initializeWithPower();
82 }
83}
84
85void MidiMain::timerElapsed(TIM_HandleTypeDef* htim){
86 if(htim == this->timer_update){
87 play();
88 }
89}
90
92 // Take only first channel for now and last note...
93 uint8_t chan = 0;
94 if(notes[chan].empty()){
95 if(active[chan]){
96 active[chan] = false;
97 // stop driver
98 drv->setUdUq(0, 0);
99 }
100 }else{
101 if(!active[chan]){
102 drv->setUdUq(this->power,0);
103 active[chan] = true;
104 }
105
106 MidiNote* note = &notes[chan].back();
107 float freq = noteToFreq[note->note];
108 // Speed up period counter instead of changing frequency to prevent phase jumps
109 float time = periodf;//(abs((uint16_t)this->timer_update->Instance->CNT - lastSystick)%period) / 1000000.0;
110 //lastSystick = this->timer_update->Instance->CNT;
111 note->counter += time * note->pitchbend;
112
113 float volume = note->volume / 127.0f;
114 float p = (note->counter*freq);
115 float sine = sinf(M_PI*p) * volume;
116 int16_t val = (sine * movementrange); // 180° phase range
117
118 drv->setPhiE_ext(val); // Wobble motor
119 }
120}
121
122void MidiMain::noteOn(uint8_t chan, uint8_t note,uint8_t velocity){
123 // If note already present remove
124 noteOff(chan,note,velocity);
125
126 MidiNote midinote;
127 midinote.note = note;
128 midinote.counter = 0;
129 midinote.volume = velocity;
130 notes[chan].push_back(midinote);
131}
132
133void MidiMain::noteOff(uint8_t chan, uint8_t note,uint8_t velocity){
134 for(auto it = notes[chan].begin(); it!=notes[chan].end(); ++it){
135 if(it->note == note){
136 notes[chan].erase(it);
137 break;
138 }
139 }
140
141}
142
143void MidiMain::controlChange(uint8_t chan, uint8_t c, uint8_t val){
144 if(c == 120 || c == 121 || c == 123){
145 notes[chan].clear();
146 }
147}
148void MidiMain::pitchBend(uint8_t chan, int16_t val){
149 float pb = std::pow(2.0f, (((float)val/8192.0f)));
150 //printf("PB: %d, %f\n",val,pb);
151 for(auto it = notes[chan].begin(); it!=notes[chan].end(); ++it){
152 it->pitchbend = pb;
153 }
154}
155
156CommandStatus MidiMain::command(const ParsedCommand& cmd,std::vector<CommandReply>& replies){
158 switch(static_cast<MidiMain_commands>(cmd.cmdId)){
159
161 handleGetSet(cmd, replies, this->power);
162 break;
164 handleGetSet(cmd, replies, this->movementrange);
165 break;
166
167 default:
169 break;
170 }
171 return result;
172}
173
174
177 usbdev->registerUsb();
178}
179
180#endif
CommandStatus
void registerCommand(const char *cmd, const ID cmdid, const char *help=nullptr, uint32_t flags=0)
static CommandStatus handleGetSet(const ParsedCommand &cmd, std::vector< CommandReply > &replies, TVal &value)
std::unique_ptr< USBdevice > usbdev
Definition: FFBoardMain.h:66
void controlChange(uint8_t chan, uint8_t c, uint8_t val)
Definition: MidiMain.cpp:143
float noteToFreq[128]
Definition: MidiMain.h:68
bool active[16]
Definition: MidiMain.h:70
void usbInit()
Definition: MidiMain.cpp:175
MidiMain_commands
Definition: MidiMain.h:31
void play()
Definition: MidiMain.cpp:91
uint32_t power
Definition: MidiMain.h:71
std::unique_ptr< TMC4671 > drv
Definition: MidiMain.h:61
static ClassIdentifier info
Definition: MidiMain.h:41
const ClassIdentifier getInfo()
Definition: MidiMain.cpp:23
const uint16_t period
Definition: MidiMain.h:73
MidiMain()
Definition: MidiMain.cpp:28
void update()
Definition: MidiMain.cpp:78
TIM_HandleTypeDef * timer_update
Definition: MidiMain.h:39
void noteOff(uint8_t chan, uint8_t note, uint8_t velocity)
Definition: MidiMain.cpp:133
void pitchBend(uint8_t chan, int16_t val)
Definition: MidiMain.cpp:148
float periodf
Definition: MidiMain.h:74
uint32_t movementrange
Definition: MidiMain.h:63
virtual ~MidiMain()
Definition: MidiMain.cpp:73
std::vector< MidiNote > notes[16]
Definition: MidiMain.h:69
void timerElapsed(TIM_HandleTypeDef *htim)
Definition: MidiMain.cpp:85
void noteOn(uint8_t chan, uint8_t note, uint8_t velocity)
Definition: MidiMain.cpp:122
CommandStatus command(const ParsedCommand &cmd, std::vector< CommandReply > &replies)
Definition: MidiMain.cpp:156
u32 SystemCoreClock
void pulseErrLed()
Definition: ledEffects.cpp:44
const char * name
float pitchbend
Definition: MidiMain.h:26
float counter
Definition: MidiMain.h:25
uint8_t note
Definition: MidiMain.h:23
uint8_t volume
Definition: MidiMain.h:24
uint32_t cmdId
const uint8_t usb_cdc_midi_conf[]
const tusb_desc_device_t usb_devdesc_ffboard_composite
const usb_string_desc_t usb_ffboard_strings_default