LM1972 デジタルボリューム | tech - 氾濫原 の続きで、Arduino ではなくmbed環境での実装。
LPC11U35 で試した。AD1 にBカーブボリュームをつけてこれによって 78dBから0dbまでアッテネーションレベルをかえる。
#include "mbed.h"
// mosi miso sck
//SPI spi(P0_9, P0_8, P0_10);
//DigitalOut cs(P0_11);
class LM1972 {
SPI spi;
DigitalOut cs;
const uint8_t daisy_chain;
public:
static const uint8_t MUTE = 0xff;
// uint16_t to 1dB step attenuation value
static inline uint8_t volumeToAttenuation(const uint16_t v) {
// volume 0% -> 78dB (126)
// volume 100% -> 0dB (0)
const uint8_t dB = ((uint32_t)(1023 - v) * 78 / 1023);
uint8_t att = 0;
if (dB < 48) {
att = 2 * dB;
} else {
att = 96 + dB - 48;
}
return att;
}
static inline uint8_t volumeToAttenuation(const float v) {
// volume 0% -> 78dB (126)
// volume 100% -> 0dB (0)
const uint8_t dB = 78 * v;
uint8_t att = 0;
if (dB < 48) {
att = 2 * dB;
} else {
att = 96 + dB - 48;
}
return att;
}
LM1972(
PinName _mosi,
PinName _miso,
PinName _sck,
PinName _cs,
uint8_t _daisy_chain = 1
) :
spi(_mosi, _miso, _sck),
cs(_cs),
daisy_chain(_daisy_chain)
{
spi.format(8, 0);
spi.frequency(1e6);
cs = 1;
}
inline void setAttenuation(const uint8_t channel, const uint8_t v) {
cs = 0;
// >150ns
wait_us(2);
spi.write(channel);
spi.write(v);
// >150ns
wait_us(2);
cs = 1;
}
uint8_t setVolume(const float v) {
const uint8_t att = volumeToAttenuation(v);
for (int i = 0; i < daisy_chain; i++) {
setAttenuation(0, att);
setAttenuation(1, att);
}
return att;
}
uint8_t setMute() {
for (int i = 0; i < daisy_chain; i++) {
setAttenuation(0, MUTE);
setAttenuation(1, MUTE);
}
return MUTE;
}
};
DigitalOut led(LED1);
Serial serial(UART_TX, UART_RX);
AnalogIn pot(P0_12); // AD1
LM1972 volume(P0_9, P0_8, P0_10, P0_11);
int main() {
serial.baud(9600);
serial.printf("init\r\n");
volume.setMute();
for (;;) {
led = 1;
wait(0.5);
led = 0;
wait(0.5);
float val = pot.read();
serial.printf("pot val = %d\r\n", (int)(val * 100));
uint8_t att = volume.setVolume(val);
serial.printf("set att = %x\r\n", att);
}
}