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);
    }
}
▲ この日のエントリ