Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: Amp AverageAnalogIn Envelope FilterController Sequence BaseMachineComon mbed-rtos mbed
Fork of SpiSequenceSender_Test by
main.cpp
- Committer:
- ryood
- Date:
- 2016-08-23
- Revision:
- 22:82f1e7877f9f
- Parent:
- 21:c4d09aaa52b9
- Child:
- 23:5fe70293e34c
File content as of revision 22:82f1e7877f9f:
/*
* main.cpp
* SpiSequencerSender_test
*
* 2016.08.20 mbed Rev 121 / mbed-rtos Rev 117で動作確認
*
*/
#include "mbed.h"
#include "rtos.h"
#include "st7565LCD.h"
#include "PinDetect.h"
#include "RotaryEncoder.h"
#include "AverageAnalogIn.h"
#define UART_TRACE (0)
#include "SpiSequenceSender.h"
#include "EnvelopeGenerator.h"
#include "SpiAmpController.h"
#include "SpiFilterController.h"
#include "ST7565_SequencerDisplay.h"
#define TITLE_STR1 ("BaseMachine Sequencer")
#define TITLE_STR2 ("20160823")
#define SEQUENCE_N (16)
#define SPI_RATE (8000000)
const int samplingPeriod = 1; // ms
const int bpm = 120;
const int envelopeLength = (60 * 1000 / (bpm * 4)) / samplingPeriod;
const int waveShape = SpiSequenceSender::WAVESHAPE_SQUARE;
const int baseNoteNumber = 36;
const int pitchMax = 12;
const int bpmMax = 240;
const int bpmMin = 60;
// Initial Sequence
const int noteOn[SEQUENCE_N] = { 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0 };
const int octave[SEQUENCE_N] = {-1,-1,-1, 0, 0,-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 };
const int pitch[SEQUENCE_N] = { 9, 7, 3, 0, 0, 3, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0 };
const int tie[SEQUENCE_N] = { 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0 };
// Devices
//
//SPI (PinName mosi, PinName miso, PinName sclk, PinName ssel=NC)
SPI spiMaster(PA_7, PA_6, PA_5);
//ST7565(PinName mosi, PinName sclk, PinName cs, PinName rst, PinName a0);
ST7565 gLCD(PB_15, PB_13, PB_12, PB_2, PB_1);
AverageAnalogIn AinPulseWidth(PC_2);
AverageAnalogIn AinCutOff(PB_0);
AverageAnalogIn AinResonance(PC_1);
AverageAnalogIn AinEnvMod(PC_3);
AverageAnalogIn AinLevel(PC_0);
AverageAnalogIn AinDuration(PA_4);
AverageAnalogIn AinDecay(PA_1);
AverageAnalogIn AinSustain(PA_0);
RotaryEncoder RotEncStep(D2, D3, 0, SEQUENCE_N - 1, 0);
RotaryEncoder RotEncPitch(D4, D5, 0, pitchMax, 0);
RotaryEncoder RotEncBpm(D14, D15, bpmMin, bpmMax, 120);
PinDetect PinWaveShape(PD_2, PullUp);
PinDetect PinModNumber(PC_11, PullUp);
PinDetect PinOctaveUp(PC_10, PullUp);
PinDetect PinOctaveDown(PC_12, PullUp);
PinDetect PinNoteOnOff(PA_13, PullUp);
PinDetect PinTie(PA_14, PullUp);
PinDetect PinAccent(PA_15, PullUp);
PinDetect PinRunStop(PB_7, PullUp);
// Grobal Variables
//
Sequence sequences[SEQUENCE_N];
SpiSequenceSender sequenceSender(&spiMaster, D9, sequences, SEQUENCE_N, samplingPeriod, bpm);
Envelope envelope(4095, envelopeLength, envelopeLength*3/4, envelopeLength/2, 2047);
EnvelopeGenerator envelopeGenerator;
SpiAmpController ampController(&spiMaster, D8, D7);
SpiFilterController filterController(&spiMaster, D10);
ST7565_SequencerDisplay sequencerDisplay(&gLCD, sequences, SEQUENCE_N);
volatile int currentStep = 0;
volatile bool isRunning = false;
volatile bool isDirty = false;
volatile uint8_t pinFlag = 0x00;
enum PinBit {
bWaveShape = 0x01,
bModNumber = 0x02,
bOctaveUp = 0x04,
bOctaveDown = 0x08,
bNoteOnOff = 0x10,
bTie = 0x20,
bAccent = 0x40,
bRunStop = 0x80
};
// とりあえずの変数(後でClassのメンバ変数に格納)
#define MOD_NUMBER_MAX 1
volatile int modNumber = 0;
volatile uint8_t envMod = 127;
//------------------------------------------------------------------------
// Callback functions
//------------------------------------------------------------------------
void updateFunction(int ticks)
{
if (ticks == 0) {
envelopeGenerator.init(envelope);
}
if (sequenceSender.getSequences()[sequenceSender.getStep()].isNoteOn()) {
uint16_t level = envelopeGenerator.getModLevel();
ampController.outDca(level);
} else {
ampController.outDca(0);
}
envelopeGenerator.update();
filterController.outDcf();
// ToDo: 再生中のLCD表示を検討→SPI1とSPI2の信号のタイミングを調査
//sequencerDisplay.update(SequencerDisplay::stop, sequenceSender.getStep());
}
//------------------------------------------------------------------------
// PinDetect ISR
//------------------------------------------------------------------------
void swWaveShapePressed()
{
pinFlag |= bWaveShape;
}
void swModNumberPressed()
{
pinFlag |= bModNumber;
}
void swOctaveUpPressed()
{
pinFlag |= bOctaveUp;
}
void swOctaveDownPressed()
{
pinFlag |= bOctaveDown;
}
void swNoteOnOffPressed()
{
pinFlag |= bNoteOnOff;
}
void swTiePressed()
{
pinFlag |= bTie;
}
void swAccentPressed()
{
pinFlag |= bAccent;
}
void swRunStopPressed()
{
pinFlag |= bRunStop;
}
//------------------------------------------------------------------------
// Functions
//------------------------------------------------------------------------
void pollingPots()
{
//pulseWidth = AinPulseWidth.read_u16() >> 8;
filterController.setCutoff(AinCutOff.read_u16() >> 8);
filterController.setResonance(AinResonance.read_u16() >> 8);
//envMod = AinEnvMod.read_u16() >> 8;
//envelope.setLevel(AinLevel.read_u16() >> 4);
envelope.setLevel(4095);
envelope.setDuration(AinDuration.read() * envelopeLength);
envelope.setDecay(AinDecay.read() * envelopeLength);
envelope.setSustain(AinSustain.read() * 4095);
}
void pollingRotEncs()
{
int _bpm = RotEncBpm.getVal();
if (_bpm != sequenceSender.getBpm()) {
sequenceSender.setBpm(_bpm);
isDirty = true;
}
int _step = RotEncStep.getVal();
if (_step != currentStep) {
currentStep = _step;
// syncronize sequence value & Rotary Encoder's value
RotEncPitch.setVal(sequences[currentStep].getPitch());
isDirty = true;
}
int _pitch = RotEncPitch.getVal();
if (_pitch != sequences[currentStep].getPitch()) {
sequences[currentStep].setPitch(_pitch);
isDirty = true;
}
}
void pollingPins()
{
if (pinFlag & bWaveShape) {
#if (UART_TRACE)
printf("PinWaveShape Pushed\r\n");
#endif
uint8_t waveShape = sequenceSender.getWaveShape();
waveShape++;
if (waveShape < SpiSequenceSender::WAVESHAPE_N) {
sequenceSender.setWaveShape(waveShape);
} else {
sequenceSender.setWaveShape(0);
}
pinFlag &= ~bWaveShape;
}
if (pinFlag & bModNumber) {
#if (UART_TRACE)
printf("PinModNumber Pushed\r\n");
#endif
modNumber++;
if (modNumber > MOD_NUMBER_MAX) {
modNumber = 0;
}
pinFlag &= ~bModNumber;
}
if (pinFlag & bOctaveUp) {
#if (UART_TRACE)
printf("PinOctaveUp Pushed\r\n");
#endif
sequences[currentStep].setOctave(sequences[currentStep].getOctave() + 1);
pinFlag &= ~bOctaveUp;
}
if (pinFlag & bOctaveDown) {
#if (UART_TRACE)
printf("PinOctaveDown Pushed\r\n");
#endif
sequences[currentStep].setOctave(sequences[currentStep].getOctave() - 1);
pinFlag &= ~bOctaveDown;
}
if (pinFlag & bNoteOnOff) {
#if (UART_TRACE)
printf("PinNoteOnOff Pushed\r\n");
#endif
sequences[currentStep].setNoteOn(!sequences[currentStep].isNoteOn());
pinFlag &= ~bNoteOnOff;
}
if (pinFlag & bTie) {
#if (UART_TRACE)
printf("PinTie Pushed\r\n");
#endif
sequences[currentStep].setTie(!sequences[currentStep].isTie());
pinFlag &= ~bTie;
}
if (pinFlag & bAccent) {
#if (UART_TRACE)
printf("PinAccent Pushed\r\n");
#endif
sequences[currentStep].setAccent(!sequences[currentStep].isAccent());
pinFlag &= ~bAccent;
}
if (pinFlag & bRunStop) {
#if (UART_TRACE)
printf("PinRunStop Pushed\r\n");
#endif
if (isRunning) {
ampController.outDca(0);
sequenceSender.stop();
isRunning = false;
} else {
sequenceSender.run(currentStep);
isRunning = true;
}
pinFlag &= ~bRunStop;
}
}
void dumpToLCD()
{
char buff[64];
int col = 0;
gLCD.clear();
sprintf(buff, "Run: %d", isRunning);
gLCD.drawstring(0, col++, buff);
sprintf(buff, "BPM: %d", sequenceSender.getBpm());
gLCD.drawstring(0, col++, buff);
sprintf(buff, "Step: %d", currentStep);
gLCD.drawstring(0, col++, buff);
sprintf(buff, "NoteOn: %d", sequences[currentStep].isNoteOn());
gLCD.drawstring(0, col++, buff);
sprintf(buff, "Pitch: %d", sequences[currentStep].getPitch());
gLCD.drawstring(0, col++, buff);
sprintf(buff, "Octave: %d", sequences[currentStep].getOctave());
gLCD.drawstring(0, col++, buff);
sprintf(buff, "Tie: %d", sequences[currentStep].isTie());
gLCD.drawstring(0, col++, buff);
sprintf(buff, "Accent: %d", sequences[currentStep].isAccent());
gLCD.drawstring(0, col++, buff);
col = 0;
sprintf(buff, "WavS: %d", sequenceSender.getWaveShape());
gLCD.drawstring(64, col++, buff);
sprintf(buff, "ModN: %d", modNumber);
gLCD.drawstring(64, col++, buff);
col = 2;
sprintf(buff, "PW%3d CO%3d", sequenceSender.getPulseWidth(), filterController.getCutoff());
gLCD.drawstring(60, col++, buff);
sprintf(buff, "RS%3d EV%3d", filterController.getResonance(), envMod);
gLCD.drawstring(60, col++, buff);
sprintf(buff, "LV%3d DR%3d", envelope.getLevel(), envelope.getDuration());
gLCD.drawstring(60, col++, buff);
sprintf(buff, "DC%3d ST%3d", envelope.getDecay(), envelope.getSustain());
gLCD.drawstring(60, col++, buff);
gLCD.display();
}
//------------------------------------------------------------------------
// Main routine
//------------------------------------------------------------------------
int main()
{
#if (UART_TRACE)
printf("*** BaseMachine Sequencer ***\r\n");
#endif
// Setup Devices
//
spiMaster.format(8, 0);
spiMaster.frequency(SPI_RATE);
gLCD.begin(0x12);
gLCD.clear();
gLCD.drawstring(0, 0, TITLE_STR1);
gLCD.drawstring(0, 1, TITLE_STR2);
gLCD.display();
Thread::wait(1000);
dumpToLCD();
Thread::wait(1000);
RotEncStep.setInterval(100);
RotEncPitch.setInterval(100);
RotEncBpm.setInterval(100);
PinWaveShape.attach_asserted(&swWaveShapePressed);
PinWaveShape.setAssertValue(0);
PinWaveShape.setSampleFrequency();
PinModNumber.attach_asserted(&swModNumberPressed);
PinModNumber.setAssertValue(0);
PinModNumber.setSampleFrequency();
PinOctaveUp.attach_asserted(&swOctaveUpPressed);
PinOctaveUp.setAssertValue(0);
PinOctaveUp.setSampleFrequency();
PinOctaveDown.attach_asserted(&swOctaveDownPressed);
PinOctaveDown.setAssertValue(0);
PinOctaveDown.setSampleFrequency();
PinNoteOnOff.attach_asserted(&swNoteOnOffPressed);
PinNoteOnOff.setAssertValue(0);
PinNoteOnOff.setSampleFrequency();
PinTie.attach_asserted(&swTiePressed);
PinTie.setAssertValue(0);
PinTie.setSampleFrequency();
PinAccent.attach_asserted(&swAccentPressed);
PinAccent.setAssertValue(0);
PinAccent.setSampleFrequency();
PinRunStop.attach_asserted(&swRunStopPressed);
PinRunStop.setAssertValue(0);
PinRunStop.setSampleFrequency();
// Initialize objects
//
Sequence::setBaseNoteNumber(baseNoteNumber);
// Initialize sequences
for (int i = 0; i < SEQUENCE_N; i++) {
Sequence& seq = sequenceSender.getSequences()[i];
seq.setPitch(pitch[i]);
seq.setOctave(octave[i]);
seq.setNoteOn(noteOn[i]);
seq.setTie(tie[i]);
}
envelopeGenerator.init(envelope);
sequenceSender.attachUpdate(&updateFunction);
sequenceSender.setWaveShape(waveShape);
//sequenceSender.run(0);
for (;;) {
pollingPots();
pollingRotEncs();
pollingPins();
}
}
