$9 Raspberry pi VCO with Seeed XIAO RP2040 Eurorack Modular Synthesizer
Raspberry pi RP2040 を搭載したSeeed XIAO RP2040を使用してモジュラーシンセサイザー のVCOを自作したので、その備忘録。
背景
自作モジュラーシンセの53作品目。
私のYoutubeチャンネルでアンケートを取ったところ、Raspberry pi pico VCOが一番人気だった。しかしRaspberry pi picoはADコンバータが3pinしかなく、VCOとして使うにはやや不便で悩んでいた。
そんななか、Seeed studioよりSeeed Xiao RP2040という小型のマイコンボードが発売された。ADコンバータが4pinあるため、最低限の構成のVCOが作れると思い、今回のモジュールの企画をした。
制作物のスペック
ユーロラック規格 3U 6HPサイズ
電源:45mA ( at 5V )
5V単電源で動作可能。
Wavefold、FM、AMの3つのモードを備えたデジタルVCO。
音声出力はPWMを使うことで、コストダウンをしている。
各モードには8種類の波形を内蔵している。
FREQ POT : 周波数を調整。チューニング用なので調整できる周波数レンジは狭い。
MOD POT : モジュレーションのかかり具合を調整。
MODE SW : モードを切り替えるトグルスイッチ
OCT SW : オクターブを切り替える。-1,0,+1の3つのレンジ。
PUSH SW : 音色を切り替える。各モードで8つの音色を選択可能。
MOD CV : モジュレーションのかかり具合を調整。入力レンジは0-5V。
V/oct : 周波数を制御。入力レンジは0-5V、分解能は10bit。
OUT : 音声出力、出力レンジは5Vp-p。
Wavefoldモードではベーシックな波形のVCOとしても使用できる。
FMモードでは柔らかい音や、強烈な倍音を含むインダストリアルな波形を出せる。
AMモードは金属的な音のパーカッションでの使用を想定しており、非整数倍音を含む音を内蔵している。
製作費
総額約1100円
---------------------------------
フロントパネル 100円
Seeed Xiao RP2040 600円
トグルSW 20円*2pcs
可変抵抗 30円*2pcs
オペアンプMPC6232 45円
他(汎用部品は下記リンク先参照)
Seeed XIAO RP2040はRaspberry pi picoと同じRP2040 MCUを搭載したマイコンボード。ADコンバータの数はpi picoが3個なのに対し、XIAOは4個搭載していて使い勝手が良い。
ハードウェア
ADコンバータは上限3.3Vまでしか読み取れないので、抵抗で分圧することで入力レンジを5Vに広げている。
V/oct回路の分圧抵抗の誤差は、ソフトウェアキャリブレーションをすることでV/octを実現している。
音声出力はPWMのため、出力回路には2poleのローパスフィルタがある。
オペアンプにより3.3Vp-pから5Vp-pに増幅している。
PWMを使用しているため、若干の高調波ノイズが発生する。気になる場合はローパスフィルタのチューニングをするとよい。
2022/JUL/25 追記
トグルスイッチはON-OFF-ONの3state スイッチです。
注意点
Seeed XIAO RP2040の回路図には複数のバージョンがある。
Ver1.08と書かれた回路図は古く、いくつかの回路が異なるため参考にしてはいけない。最新のVer1.22と書かれた回路図を参考にすべし。
ソフトウェア
Seeed XIAO RP2040の導入注意点
XIAO RP2040はArduino IDEで開発が可能だ。
ここにも注意点がある。
公式WIKIにあるソフトウェアセットアップ手順でボードマネージャを導入したら、私の環境では書き込みに失敗した。
adafruitで紹介されているボードマネージャを導入したところ、書き込みに成功した。
同様の不具合はほかの人も経験しているようなので、もしArduino IDEで書き込みに失敗する場合は、ボードマネージャーを疑ってみるとよいかもしれない。
音声出力
wavetableに波形を格納し、一定の周期で割り込みをて、wavetableを読み出すことで音声出力をしている。wavetableは10bit、256サンプル。
Interfaeという雑誌の2021年8月号にRaspberry pi picoを使ったシンセサイザーの記事があり、そのソースコードを参考にした。私の知識では書いてあることの9割は理解できなかったのだが、割り込み処理の考え方を学ぶことができた。
ソースコードは下記のリンク先でも公開されている。感謝だ!
https://github.com/risgk/pico_synth_ex/blob/main/pico_synth_ex.c
こちらの記事も参考になる。割り込みの考え方が丁寧に解説されている。
https://blog.boochow.com/article/pico-pwm-sound.html
ソフトウェアキャリブレーション
V/oct回路の分圧抵抗の誤差をなくすため、キャリブレーション定数がある。
calbの値を0.7~1.3くらいの範囲で調整することでキャリブレーションをする。
float calb = 1.19;//calibration for reduce resistance error
宣伝:オープンソースプロジェクトの支援をお願いします
DIYモジュラーシンセのオープンソースプロジェクトを継続するために、patreonというサービスでパトロンを募集しています。
コーヒー一杯の支援をいただけると嬉しいです。
また、パトロン限定のコンテンツも配信しています。
ソースコード
粗末だが公開する。悪い点があれば指摘を貰えると嬉しい。
#include <hardware/pwm.h>
int k = 1;
float AM_mod = 1;//AM modulation rate
float f = 0;
int slice_num = 0;
float osc_freq = 0;
bool push_sw, old_push_sw;//push sw
float mod = 0;
int wavetable[256];//1024 resolution , 256 rate
float mod_wavetable[256];//1st modulated wavetable
int mod2_wavetable[256];//2nd modulated wavetable
float calb = 1.15;//calibration for reduce resistance error
int adc, freq_pot, oct_sw, mode;
int waveform = 0;
int f0 = 35;//base osc frequency
long timer = 0;//use for making AM sinewave
const static float voctpow[1230] = {//Covers 6(=1230) octaves. If it is 1230 or more, the operation becomes unstable.
0, 0.004882, 0.009765, 0.014648, 0.019531, 0.024414, 0.029296, 0.034179, 0.039062, 0.043945, 0.048828, 0.05371, 0.058593, 0.063476, 0.068359, 0.073242, 0.078125, 0.083007, 0.08789, 0.092773, 0.097656, 0.102539, 0.107421, 0.112304, 0.117187, 0.12207, 0.126953, 0.131835, 0.136718, 0.141601, 0.146484, 0.151367, 0.15625, 0.161132, 0.166015, 0.170898, 0.175781, 0.180664, 0.185546, 0.190429, 0.195312, 0.200195, 0.205078, 0.20996, 0.214843, 0.219726, 0.224609, 0.229492, 0.234375, 0.239257, 0.24414, 0.249023, 0.253906, 0.258789, 0.263671, 0.268554, 0.273437, 0.27832, 0.283203, 0.288085, 0.292968, 0.297851, 0.302734, 0.307617, 0.3125, 0.317382, 0.322265, 0.327148, 0.332031, 0.336914, 0.341796, 0.346679, 0.351562, 0.356445, 0.361328, 0.36621, 0.371093, 0.375976, 0.380859, 0.385742, 0.390625, 0.395507, 0.40039, 0.405273, 0.410156, 0.415039, 0.419921, 0.424804, 0.429687, 0.43457, 0.439453, 0.444335, 0.449218, 0.454101, 0.458984, 0.463867, 0.46875, 0.473632, 0.478515, 0.483398, 0.488281, 0.493164, 0.498046, 0.502929, 0.507812, 0.512695, 0.517578, 0.52246, 0.527343, 0.532226, 0.537109, 0.541992, 0.546875, 0.551757, 0.55664, 0.561523, 0.566406, 0.571289, 0.576171, 0.581054, 0.585937, 0.59082, 0.595703, 0.600585, 0.605468, 0.610351, 0.615234, 0.620117, 0.625, 0.629882, 0.634765, 0.639648, 0.644531, 0.649414, 0.654296, 0.659179, 0.664062, 0.668945, 0.673828, 0.67871, 0.683593, 0.688476, 0.693359, 0.698242, 0.703125, 0.708007, 0.71289, 0.717773, 0.722656, 0.727539, 0.732421, 0.737304, 0.742187, 0.74707, 0.751953, 0.756835, 0.761718, 0.766601, 0.771484, 0.776367, 0.78125, 0.786132, 0.791015, 0.795898, 0.800781, 0.805664, 0.810546, 0.815429, 0.820312, 0.825195, 0.830078, 0.83496, 0.839843, 0.844726, 0.849609, 0.854492, 0.859375, 0.864257, 0.86914, 0.874023, 0.878906, 0.883789, 0.888671, 0.893554, 0.898437, 0.90332, 0.908203, 0.913085, 0.917968, 0.922851, 0.927734, 0.932617, 0.9375, 0.942382, 0.947265, 0.952148, 0.957031, 0.961914, 0.966796, 0.971679, 0.976562, 0.981445, 0.986328, 0.99121, 0.996093, 1.000976, 1.005859, 1.010742, 1.015625, 1.020507, 1.02539, 1.030273, 1.035156, 1.040039, 1.044921, 1.049804, 1.054687, 1.05957, 1.064453, 1.069335, 1.074218, 1.079101, 1.083984, 1.088867, 1.09375, 1.098632, 1.103515, 1.108398, 1.113281, 1.118164, 1.123046, 1.127929, 1.132812, 1.137695, 1.142578, 1.14746, 1.152343, 1.157226, 1.162109, 1.166992, 1.171875, 1.176757, 1.18164, 1.186523, 1.191406, 1.196289, 1.201171, 1.206054, 1.210937, 1.21582, 1.220703, 1.225585, 1.230468, 1.235351, 1.240234, 1.245117, 1.25, 1.254882, 1.259765, 1.264648, 1.269531, 1.274414, 1.279296, 1.284179, 1.289062, 1.293945, 1.298828, 1.30371, 1.308593, 1.313476, 1.318359, 1.323242, 1.328125, 1.333007, 1.33789, 1.342773, 1.347656, 1.352539, 1.357421, 1.362304, 1.367187, 1.37207, 1.376953, 1.381835, 1.386718, 1.391601, 1.396484, 1.401367, 1.40625, 1.411132, 1.416015, 1.420898, 1.425781, 1.430664, 1.435546, 1.440429, 1.445312, 1.450195, 1.455078, 1.45996, 1.464843, 1.469726, 1.474609, 1.479492, 1.484375, 1.489257, 1.49414, 1.499023, 1.503906, 1.508789, 1.513671, 1.518554, 1.523437, 1.52832, 1.533203, 1.538085, 1.542968, 1.547851, 1.552734, 1.557617, 1.5625, 1.567382, 1.572265, 1.577148, 1.582031, 1.586914, 1.591796, 1.596679, 1.601562, 1.606445, 1.611328, 1.61621, 1.621093, 1.625976, 1.630859, 1.635742, 1.640625, 1.645507, 1.65039, 1.655273, 1.660156, 1.665039, 1.669921, 1.674804, 1.679687, 1.68457, 1.689453, 1.694335, 1.699218, 1.704101, 1.708984, 1.713867, 1.71875, 1.723632, 1.728515, 1.733398, 1.738281, 1.743164, 1.748046, 1.752929, 1.757812, 1.762695, 1.767578, 1.77246, 1.777343, 1.782226, 1.787109, 1.791992, 1.796875, 1.801757, 1.80664, 1.811523, 1.816406, 1.821289, 1.826171, 1.831054, 1.835937, 1.84082, 1.845703, 1.850585, 1.855468, 1.860351, 1.865234, 1.870117, 1.875, 1.879882, 1.884765, 1.889648, 1.894531, 1.899414, 1.904296, 1.909179, 1.914062, 1.918945, 1.923828, 1.92871, 1.933593, 1.938476, 1.943359, 1.948242, 1.953125, 1.958007, 1.96289, 1.967773, 1.972656, 1.977539, 1.982421, 1.987304, 1.992187, 1.99707, 2.001953, 2.006835, 2.011718, 2.016601, 2.021484, 2.026367, 2.03125, 2.036132, 2.041015, 2.045898, 2.050781, 2.055664, 2.060546, 2.065429, 2.070312, 2.075195, 2.080078, 2.08496, 2.089843, 2.094726, 2.099609, 2.104492, 2.109375, 2.114257, 2.11914, 2.124023, 2.128906, 2.133789, 2.138671, 2.143554, 2.148437, 2.15332, 2.158203, 2.163085, 2.167968, 2.172851, 2.177734, 2.182617, 2.1875, 2.192382, 2.197265, 2.202148, 2.207031, 2.211914, 2.216796, 2.221679, 2.226562, 2.231445, 2.236328, 2.24121, 2.246093, 2.250976, 2.255859, 2.260742, 2.265625, 2.270507, 2.27539, 2.280273, 2.285156, 2.290039, 2.294921, 2.299804, 2.304687, 2.30957, 2.314453, 2.319335, 2.324218, 2.329101, 2.333984, 2.338867, 2.34375, 2.348632, 2.353515, 2.358398, 2.363281, 2.368164, 2.373046, 2.377929, 2.382812, 2.387695, 2.392578, 2.39746, 2.402343, 2.407226, 2.412109, 2.416992, 2.421875, 2.426757, 2.43164, 2.436523, 2.441406, 2.446289, 2.451171, 2.456054, 2.460937, 2.46582, 2.470703, 2.475585, 2.480468, 2.485351, 2.490234, 2.495117, 2.5, 2.504882, 2.509765, 2.514648, 2.519531, 2.524414, 2.529296, 2.534179, 2.539062, 2.543945, 2.548828, 2.55371, 2.558593, 2.563476, 2.568359, 2.573242, 2.578125, 2.583007, 2.58789, 2.592773, 2.597656, 2.602539, 2.607421, 2.612304, 2.617187, 2.62207, 2.626953, 2.631835, 2.636718, 2.641601, 2.646484, 2.651367, 2.65625, 2.661132, 2.666015, 2.670898, 2.675781, 2.680664, 2.685546, 2.690429, 2.695312, 2.700195, 2.705078, 2.70996, 2.714843, 2.719726, 2.724609, 2.729492, 2.734375, 2.739257, 2.74414, 2.749023, 2.753906, 2.758789, 2.763671, 2.768554, 2.773437, 2.77832, 2.783203, 2.788085, 2.792968, 2.797851, 2.802734, 2.807617, 2.8125, 2.817382, 2.822265, 2.827148, 2.832031, 2.836914, 2.841796, 2.846679, 2.851562, 2.856445, 2.861328, 2.86621, 2.871093, 2.875976, 2.880859, 2.885742, 2.890625, 2.895507, 2.90039, 2.905273, 2.910156, 2.915039, 2.919921, 2.924804, 2.929687, 2.93457, 2.939453, 2.944335, 2.949218, 2.954101, 2.958984, 2.963867, 2.96875, 2.973632, 2.978515, 2.983398, 2.988281, 2.993164, 2.998046, 3.002929, 3.007812, 3.012695, 3.017578, 3.02246, 3.027343, 3.032226, 3.037109, 3.041992, 3.046875, 3.051757, 3.05664, 3.061523, 3.066406, 3.071289, 3.076171, 3.081054, 3.085937, 3.09082, 3.095703, 3.100585, 3.105468, 3.110351, 3.115234, 3.120117, 3.125, 3.129882, 3.134765, 3.139648, 3.144531, 3.149414, 3.154296, 3.159179, 3.164062, 3.168945, 3.173828, 3.17871, 3.183593, 3.188476, 3.193359, 3.198242, 3.203125, 3.208007, 3.21289, 3.217773, 3.222656, 3.227539, 3.232421, 3.237304, 3.242187, 3.24707, 3.251953, 3.256835, 3.261718, 3.266601, 3.271484, 3.276367, 3.28125, 3.286132, 3.291015, 3.295898, 3.300781, 3.305664, 3.310546, 3.315429, 3.320312, 3.325195, 3.330078, 3.33496, 3.339843, 3.344726, 3.349609, 3.354492, 3.359375, 3.364257, 3.36914, 3.374023, 3.378906, 3.383789, 3.388671, 3.393554, 3.398437, 3.40332, 3.408203, 3.413085, 3.417968, 3.422851, 3.427734, 3.432617, 3.4375, 3.442382, 3.447265, 3.452148, 3.457031, 3.461914, 3.466796, 3.471679, 3.476562, 3.481445, 3.486328, 3.49121, 3.496093, 3.500976, 3.505859, 3.510742, 3.515625, 3.520507, 3.52539, 3.530273, 3.535156, 3.540039, 3.544921, 3.549804, 3.554687, 3.55957, 3.564453, 3.569335, 3.574218, 3.579101, 3.583984, 3.588867, 3.59375, 3.598632, 3.603515, 3.608398, 3.613281, 3.618164, 3.623046, 3.627929, 3.632812, 3.637695, 3.642578, 3.64746, 3.652343, 3.657226, 3.662109, 3.666992, 3.671875, 3.676757, 3.68164, 3.686523, 3.691406, 3.696289, 3.701171, 3.706054, 3.710937, 3.71582, 3.720703, 3.725585, 3.730468, 3.735351, 3.740234, 3.745117, 3.75, 3.754882, 3.759765, 3.764648, 3.769531, 3.774414, 3.779296, 3.784179, 3.789062, 3.793945, 3.798828, 3.80371, 3.808593, 3.813476, 3.818359, 3.823242, 3.828125, 3.833007, 3.83789, 3.842773, 3.847656, 3.852539, 3.857421, 3.862304, 3.867187, 3.87207, 3.876953, 3.881835, 3.886718, 3.891601, 3.896484, 3.901367, 3.90625, 3.911132, 3.916015, 3.920898, 3.925781, 3.930664, 3.935546, 3.940429, 3.945312, 3.950195, 3.955078, 3.95996, 3.964843, 3.969726, 3.974609, 3.979492, 3.984375, 3.989257, 3.99414, 3.999023, 4.003906, 4.008789, 4.013671, 4.018554, 4.023437, 4.02832, 4.033203, 4.038085, 4.042968, 4.047851, 4.052734, 4.057617, 4.0625, 4.067382, 4.072265, 4.077148, 4.082031, 4.086914, 4.091796, 4.096679, 4.101562, 4.106445, 4.111328, 4.11621, 4.121093, 4.125976, 4.130859, 4.135742, 4.140625, 4.145507, 4.15039, 4.155273, 4.160156, 4.165039, 4.169921, 4.174804, 4.179687, 4.18457, 4.189453, 4.194335, 4.199218, 4.204101, 4.208984, 4.213867, 4.21875, 4.223632, 4.228515, 4.233398, 4.238281, 4.243164, 4.248046, 4.252929, 4.257812, 4.262695, 4.267578, 4.27246, 4.277343, 4.282226, 4.287109, 4.291992, 4.296875, 4.301757, 4.30664, 4.311523, 4.316406, 4.321289, 4.326171, 4.331054, 4.335937, 4.34082, 4.345703, 4.350585, 4.355468, 4.360351, 4.365234, 4.370117, 4.375, 4.379882, 4.384765, 4.389648, 4.394531, 4.399414, 4.404296, 4.409179, 4.414062, 4.418945, 4.423828, 4.42871, 4.433593, 4.438476, 4.443359, 4.448242, 4.453125, 4.458007, 4.46289, 4.467773, 4.472656, 4.477539, 4.482421, 4.487304, 4.492187, 4.49707, 4.501953, 4.506835, 4.511718, 4.516601, 4.521484, 4.526367, 4.53125, 4.536132, 4.541015, 4.545898, 4.550781, 4.555664, 4.560546, 4.565429, 4.570312, 4.575195, 4.580078, 4.58496, 4.589843, 4.594726, 4.599609, 4.604492, 4.609375, 4.614257, 4.61914, 4.624023, 4.628906, 4.633789, 4.638671, 4.643554, 4.648437, 4.65332, 4.658203, 4.663085, 4.667968, 4.672851, 4.677734, 4.682617, 4.6875, 4.692382, 4.697265, 4.702148, 4.707031, 4.711914, 4.716796, 4.721679, 4.726562, 4.731445, 4.736328, 4.74121, 4.746093, 4.750976, 4.755859, 4.760742, 4.765625, 4.770507, 4.77539, 4.780273, 4.785156, 4.790039, 4.794921, 4.799804, 4.804687, 4.80957, 4.814453, 4.819335, 4.824218, 4.829101, 4.833984, 4.838867, 4.84375, 4.848632, 4.853515, 4.858398, 4.863281, 4.868164, 4.873046, 4.877929, 4.882812, 4.887695, 4.892578, 4.89746, 4.902343, 4.907226, 4.912109, 4.916992, 4.921875, 4.926757, 4.93164, 4.936523, 4.941406, 4.946289, 4.951171, 4.956054, 4.960937, 4.96582, 4.970703, 4.975585, 4.980468, 4.985351, 4.990234, 4.995117, 5, 5.004882, 5.009765, 5.014648, 5.019531, 5.024414, 5.029296, 5.034179, 5.039062, 5.043945, 5.048828, 5.05371, 5.058593, 5.063476, 5.068359, 5.073242, 5.078125, 5.083007, 5.08789, 5.092773, 5.097656, 5.102539, 5.107421, 5.112304, 5.117187, 5.12207, 5.126953, 5.131835, 5.136718, 5.141601, 5.146484, 5.151367, 5.15625, 5.161132, 5.166015, 5.170898, 5.175781, 5.180664, 5.185546, 5.190429, 5.195312, 5.200195, 5.205078, 5.20996, 5.214843, 5.219726, 5.224609, 5.229492, 5.234375, 5.239257, 5.24414, 5.249023, 5.253906, 5.258789, 5.263671, 5.268554, 5.273437, 5.27832, 5.283203, 5.288085, 5.292968, 5.297851, 5.302734, 5.307617, 5.3125, 5.317382, 5.322265, 5.327148, 5.332031, 5.336914, 5.341796, 5.346679, 5.351562, 5.356445, 5.361328, 5.36621, 5.371093, 5.375976, 5.380859, 5.385742, 5.390625, 5.395507, 5.40039, 5.405273, 5.410156, 5.415039, 5.419921, 5.424804, 5.429687, 5.43457, 5.439453, 5.444335, 5.449218, 5.454101, 5.458984, 5.463867, 5.46875, 5.473632, 5.478515, 5.483398, 5.488281, 5.493164, 5.498046, 5.502929, 5.507812, 5.512695, 5.517578, 5.52246, 5.527343, 5.532226, 5.537109, 5.541992, 5.546875, 5.551757, 5.55664, 5.561523, 5.566406, 5.571289, 5.576171, 5.581054, 5.585937, 5.59082, 5.595703, 5.600585, 5.605468, 5.610351, 5.615234, 5.620117, 5.625, 5.629882, 5.634765, 5.639648, 5.644531, 5.649414, 5.654296, 5.659179, 5.664062, 5.668945, 5.673828, 5.67871, 5.683593, 5.688476, 5.693359, 5.698242, 5.703125, 5.708007, 5.71289, 5.717773, 5.722656, 5.727539, 5.732421, 5.737304, 5.742187, 5.74707, 5.751953, 5.756835, 5.761718, 5.766601, 5.771484, 5.776367, 5.78125, 5.786132, 5.791015, 5.795898, 5.800781, 5.805664, 5.810546, 5.815429, 5.820312, 5.825195, 5.830078, 5.83496, 5.839843, 5.844726, 5.849609, 5.854492, 5.859375, 5.864257, 5.86914, 5.874023, 5.878906, 5.883789, 5.888671, 5.893554, 5.898437, 5.90332, 5.908203, 5.913085, 5.917968, 5.922851, 5.927734, 5.932617, 5.9375, 5.942382, 5.947265, 5.952148, 5.957031, 5.961914, 5.966796, 5.971679, 5.976562, 5.981445, 5.986328, 5.99121, 5.996093, 6.000976,
};
float freq_table[2048];
void setup1() {
}
void setup()
{
pinMode(0, INPUT_PULLUP);//oct select
pinMode(1, INPUT_PULLUP);//oct select
pinMode(6, INPUT_PULLUP);//push sw
pinMode(3, INPUT_PULLUP);//mode select
pinMode(4, INPUT_PULLUP);//mode select
timer = micros();
table_set();//set wavetable
//-------------------octave select-------------------------------
for (int i = 0; i < 1230; i++) {//Covers 6(=1230) octaves. If it is 1230 or more, the operation becomes unstable.
freq_table[i] = f0 * pow(2, (voctpow[i]));
}
for (int i = 0; i < 2048 - 1230; i++) {
freq_table[i + 1230] = 6;
}
//-------------------PWM setting-------------------------------
gpio_set_function(2, GPIO_FUNC_PWM);// set GP2 function PWM
slice_num = pwm_gpio_to_slice_num(2);// GP2 PWM slice
pwm_clear_irq(slice_num);
pwm_set_irq_enabled(slice_num, true);
irq_set_exclusive_handler(PWM_IRQ_WRAP, on_pwm_wrap);
irq_set_enabled(PWM_IRQ_WRAP, true);
//set PWM frequency
pwm_set_clkdiv(slice_num, 1);//=sysclock/((resolution+1)*frequency)
pwm_set_wrap(slice_num, 1023);//resolutio
pwm_set_enabled(slice_num, true);//PWM output enable
}
void on_pwm_wrap() {
pwm_clear_irq(slice_num);
f = f + osc_freq;
if (f > 255) {
f = 0;
}
int k = (int)f;
pwm_set_chan_level(slice_num, PWM_CHAN_A, mod2_wavetable[k] + 511);
}
void loop()
{
old_push_sw = push_sw;
//-------------------octave select-------------------------------
if (digitalRead(0) == 1 && digitalRead(1) == 1) {
oct_sw = 1;
}
else if (digitalRead(0) == 0 && digitalRead(1) == 1) {
oct_sw = 3;
}
else if (digitalRead(0) == 1 && digitalRead(1) == 0) {
oct_sw = 0;
}
// -------------------mode select-------------------------------
if (digitalRead(4) == 1 && digitalRead(3) == 1) {
mode = 1;//fm
}
else if (digitalRead(4) == 0 && digitalRead(3) == 1) {
mode = 0;//AM
}
else if (digitalRead(4) == 1 && digitalRead(3) == 0) {
mode = 2;//wavefolder
}
// -------------------frequeny calculation-------------------------------
adc = analogRead(26) * calb;//Correct resistance errors
adc = constrain(adc , 0, 1225) ;//Covers 6(=1220) octaves. If it is 1230 or more, the operation becomes unstable.
freq_pot = map(analogRead(27), 0, 1023, 0, 127);
osc_freq = freq_table[adc + freq_pot]; // V/oct apply
osc_freq = 256 * osc_freq / 122070 * (1 + oct_sw);
// -------------------mod parameter set-------------------------------
if (mode == 0) {//fold
mod = constrain(analogRead(29) + analogRead(28), 0, 1023) * 0.0036 + 0.90; //28 is CV , 29 is pot
}
else if (mode == 1) {//FM
mod = constrain(analogRead(29) + analogRead(28), 0, 1023) / 8;
}
else if (mode == 2) {//AM
mod = 1023 - constrain(analogRead(29) + analogRead(28), 0, 1023) ;
}
// -------------------push sw-------------------------------
push_sw = digitalRead(6);
if (push_sw == 0 && old_push_sw == 1) {//when push sw ON
waveform++;//change waveform
if (waveform > 7) {
waveform = 0;
}
if (mode == 0 || mode == 2) {
table_set();
}
}
//}
//void loop1() {//modulation
if (mode == 0 ) {//wavefold
for (int i = 0; i < 256; i++) {
mod_wavetable[i] = wavetable[i] * mod;
}
for (int i = 0; i < 256; i++) { //fold
if (mod_wavetable[i] > 511 && mod_wavetable[i] < 1023 + 512) {
mod2_wavetable[i] = 1024 - mod_wavetable[i];
}
else if (mod_wavetable[i] < -512 && mod_wavetable[i] > -1024 - 512) {
mod2_wavetable[i] = -1023 - mod_wavetable[i];
}
else if (mod_wavetable[i] < -1024 - 511) {
mod2_wavetable[i] = 2048 + mod_wavetable[i];
}
else if (mod_wavetable[i] > 1023 + 511) {
mod2_wavetable[i] = -2047 + mod_wavetable[i];
}
else {
mod2_wavetable[i] = mod_wavetable[i] ;
}
}
}
else if (mode == 1) {//FM
switch (waveform) {
case 0:
for (int i = 0; i < 256; i++) { //FM1
mod2_wavetable[i] = (sin(2 * M_PI * i / 256 + mod / 128 * sin(2 * M_PI * 3 * i / 256)) ) * 511;
}
break;
case 1:
for (int i = 0; i < 256; i++) { //FM2
mod2_wavetable[i] = (sin(2 * M_PI * i / 256 + mod / 128 * sin(2 * M_PI * 3 * i / 256 + mod / 128 * sin(2 * M_PI * 3 * i / 256))) ) * 511;
}
break;
case 2:
for (int i = 0; i < 256; i++) { //FM3
mod2_wavetable[i] = (sin(2 * M_PI * i / 256 + mod / 128 * sin(2 * M_PI * 5 * i / 256 + mod / 128 * sin(2 * M_PI * 7 * i / 256))) ) * 511;
}
break;
case 3:
for (int i = 0; i < 256; i++) { //FM4
mod2_wavetable[i] = (sin(2 * M_PI * i / 256 + mod / 128 * sin(2 * M_PI * 9 * i / 256 + mod / 128 * sin(2 * M_PI * 5 * i / 256))) ) * 511;
}
break;
case 4:
for (int i = 0; i < 256; i++) { //FM5
mod2_wavetable[i] = ((sin(2 * M_PI * i / 256 + mod / 128 * sin(2 * M_PI * 19 * i / 256)) ) + (sin(2 * M_PI * 3 * i / 256 + mod / 128 * sin(2 * M_PI * 7 * i / 256)) )) / 2 * 511;
}
break;
case 5:
for (int i = 0; i < 256; i++) { //FM6
mod2_wavetable[i] = ((sin(2 * M_PI * i / 256 + mod / 128 * sin(2 * M_PI * 7 * i / 124)) ) + (sin(2 * M_PI * 9 * i / 368 + mod / 128 * sin(2 * M_PI * 11 * i / 256)) )) * 511;
}
break;
case 6:
for (int i = 0; i < 256; i++) { //FM7
mod2_wavetable[i] = ((sin(2 * M_PI * i / 256 + mod / 128 * sin(2 * M_PI * 13 * i / 256)) ) + (sin(2 * M_PI * 17 * i / 111 + mod / 128 * sin(2 * M_PI * 19 * i / 89)) )) * 511;
}
break;
case 7:
for (int i = 0; i < 256; i++) { //FM8
mod2_wavetable[i] = (sin(2 * M_PI * i / 256 + mod / 128 * sin(2 * M_PI * 11 * i / 124 + mod / 128 * sin(2 * M_PI * 7 * i / 333 + mod / 128 * sin(2 * M_PI * 9 * i / 56)))) ) * 511;
}
break;
}
}
else if (mode == 2) {//AM
if (timer + mod <= micros()) {
k++;
if (k > 63) {
k = 0;
}
AM_mod = sin( 2 * M_PI * k / 63);//make modulation sine wave
for (int i = 0; i < 255 ; i++) {
mod2_wavetable[i] = wavetable[i] * AM_mod;//multiply AM sine wave
}
timer = micros();
}
}
}
void table_set() {//make wavetable
if (mode == 0) { //wavefold
switch (waveform) {
case 0:
for (int i = 0; i < 256; i++) { //saw
wavetable[i] = i * 4 - 512;
}
break;
case 1:
for (int i = 0; i < 256; i++) { //sin
wavetable[i] = (sin(2 * M_PI * i / 256)) * 511;
}
break;
case 2:
for (int i = 0; i < 128; i++) { //squ
wavetable[i] = 511;
wavetable[i + 128] = -511;
}
break;
case 3:
for (int i = 0; i < 128; i++) { //tri
wavetable[i] = i * 8 - 511;
wavetable[i + 128] = 511 - i * 8;
}
break;
case 4:
for (int i = 0; i < 128; i++) { //oct saw
wavetable[i] = i * 4 - 512 + i * 2;
wavetable[i + 128] = i * 2 - 256 + i * 4;
}
break;
case 5:
for (int i = 0; i < 256; i++) { //FM1
wavetable[i] = (sin(2 * M_PI * i / 256 + sin(2 * M_PI * 3 * i / 256)) ) * 511;
}
break;
case 6:
for (int i = 0; i < 256; i++) { //FM2
wavetable[i] = (sin(2 * M_PI * i / 256 + sin(2 * M_PI * 7 * i / 256))) * 511;
}
break;
case 7:
for (int i = 0; i < 256; i++) { //FM3
wavetable[i] = (sin(2 * M_PI * i / 256 + sin(2 * M_PI * 4 * i / 256 + sin(2 * M_PI * 11 * i / 256)))) * 511;
}
break;
}
}
else if (mode == 2) { //AM
switch (waveform) {
case 0:
for (int i = 0; i < 256; i++) { //saw
wavetable[i] = (sin(2 * M_PI * i / 256)) * 511;
}
break;
case 1:
for (int i = 0; i < 256; i++) { //fm1
wavetable[i] = (sin(2 * M_PI * i / 256 + sin(2 * M_PI * 3 * i / 256)) ) * 511;
}
break;
case 2:
for (int i = 0; i < 256; i++) { //fm2
wavetable[i] = (sin(2 * M_PI * i / 256 + sin(2 * M_PI * 5 * i / 256)) ) * 511;
}
break;
case 3:
for (int i = 0; i < 256; i++) { //fm3
wavetable[i] = (sin(2 * M_PI * i / 256 + sin(2 * M_PI * 4 * i / 256 + sin(2 * M_PI * 11 * i / 256)))) * 511;
}
break;
case 4:
for (int i = 0; i < 256; i++) { //non-integer multiplets fm1
wavetable[i] = (sin(2 * M_PI * i / 256 + sin(2 * M_PI * 1.28 * i / 256)) ) * 511;
}
break;
case 5:
for (int i = 0; i < 256; i++) { //non-integer multiplets fm2
wavetable[i] = (sin(2 * M_PI * i / 256 + sin(2 * M_PI * 3.19 * i / 256)) ) * 511;
}
break;
case 6:
for (int i = 0; i < 256; i++) { //non-integer multiplets fm3
wavetable[i] = (sin(2 * M_PI * i / 256 + sin(2 * M_PI * 2.3 * i / 256 + sin(2 * M_PI * 7.3 * i / 256)))) * 511;
}
break;
case 7:
for (int i = 0; i < 256; i++) { //non-integer multiplets fm3
wavetable[i] = (sin(2 * M_PI * i / 256 + sin(2 * M_PI * 6.3 * i / 256 + sin(2 * M_PI * 11.3 * i / 256)))) * 511;
}
break;
}
}
}
この記事が気に入ったらサポートをしてみませんか?