現在のソース
[global.h]
#define INTERRUPT_TIME_US 22
#include "Channel.h"
extern DigitalOut myled1;
extern DigitalOut myled2;
extern DigitalOut myled3;
extern DigitalOut myled4;
[main.cpp]
#include "mbed.h"
#define MAIN
#include "global.h"
#define ADD 0x2000000static Channel* gChannel[2];
DigitalOut myled1(LED1);
DigitalOut myled2(LED2);
DigitalOut myled3(LED3);
DigitalOut myled4(LED4);
int main() {
gChannel[0]=new Channel(INTERRUPT_TIME_US);
gChannel[0]->setOmega(ADD);
gChannel[1]=new Channel(INTERRUPT_TIME_US);
gChannel[1]->setOmega(ADD+0x100000);
while(1) {
wait(1);
}
}
[Channel.h]
#ifndef _CHANNEL_H_INCL
#define _CHANNEL_H_INCL
#define CHANNEL_PART_NUM 16
class Channel
{
public:
/**
* Constructor(only)
* to construct after mbed has started.
* this constructor handles interval timer automatically.
* @value interrupt_us interrupt span (micro second). it work at first time only.
*/
Channel(long interrupt_us);
/**
* Destructor
* this destructor anatach the interval timer automatically.
*/
~Channel();
/**
* Set angle speed(0x100000000 per 1 round)
* frequency was depend on interrupt_us
*/
void setOmega(long speed);
/**
* advance the Angle and caliculate value this span.
* it was called by automatically from interval timer.
* @return value on this tick(max 0xffff0000)
*/
virtual unsigned long tick();
long m_Angle;
long m_Omega;
};
#endif
[Channel.cpp]
#include "mbed.h"
#include "global.h"
#include "Channel.h"
static long interrupt_us;
static int part_num=0;
static Channel* part[CHANNEL_PART_NUM];
static Ticker sTicker;
static long total_value_in_this_span;
static AnalogOut sAnalogOut(p18);
/* interrupt handler */
/*static void tick(uint32_t id);*/
static void tick();
Channel::Channel(long interrupt_us)
{
myled1=1;
::interrupt_us=interrupt_us;
if(part_num==0)
{
sTicker.attach_us(::tick,interrupt_us);
}
part_num++;
for(int i=0;i<CHANNEL_PART_NUM;i++)
{
if(part[i]==NULL)
{
part[i]=this;
break;
}
}
}
Channel::~Channel()
{
part_num--;
for(int i=0;i<CHANNEL_PART_NUM;i++)
{
if(part[i]==this)
{
part[i]=NULL;
break;
}
}
if(part_num<=0)
{
sTicker.detach();
}
}
void Channel::setOmega(long speed)
{
m_Omega=speed;
myled2=1;
}
unsigned long Channel::tick()
{
m_Angle+=m_Omega;
if (m_Angle & 0x80000000)
{
myled3 = 1;
return 0xffff0000;
}
else
{
myled3 = 0;
return 0;
}
}
void ::tick()
{
long long value=0;
for (int i=0;i<CHANNEL_PART_NUM;i++)
{
if (part[i]!=NULL)
{
value+=total_value_in_this_span + part[i]->tick();
}
}
value = value>=0x100000000 ? 0xffff0000 : value;
sAnalogOut=value;
myled4=value > 0x80000000;
}
mbedって ソースを公開するってどうすればいいんだろう?githabにでも入れるのがいいのかなぁ? でも、ソースの在り処ってクラウドでしょ? この「パブリッシュ」ってメニューを使うのかなぁ?(使ったことがない)
超未完成な状態でPublishするとなんかマズそうなのでひとまずカット&ペースト。Apache Licence2です。超未完成なコードだけど参考にしたい人のために。
これに、
- MIDIのノートナンバーを入れると12音平均律の角速度(周波数じゃなくて)を計算するヘルパ
- ADSRエンベロープを出すジェネレータ
- ディレイ付きLFOと一つのトラックでデチューンするジェネレータ
- Channelクラスを派生して角度を元に4bit(16段階)の音色を作るWaveTableクラス(これを使ってノイズも作る)
- MMLを解釈するクラス
辺りをつけるとシンセサイザーっぽくなるな。うわー、作るものたくさんだ。ネタは尽きないなぁ。チップチューンきちんとやろうとするとできることたくさんあるもんね。