2021-01-29 06:31:58 -05:00
|
|
|
//
|
|
|
|
// FILE: M62429.cpp
|
|
|
|
// AUTHOR: Rob Tillaart
|
|
|
|
// PURPOSE: Arduino library for M62429 volume control IC
|
2022-11-15 04:47:38 -05:00
|
|
|
// VERSION: 0.3.6
|
2021-01-29 06:31:58 -05:00
|
|
|
// HISTORY: See M62429.cpp2
|
|
|
|
// URL: https://github.com/RobTillaart/M62429
|
|
|
|
|
2022-11-15 04:47:38 -05:00
|
|
|
// HISTORY: see changelog.md
|
|
|
|
|
2021-05-28 07:36:28 -04:00
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
|
|
|
|
#include "M62429.h"
|
|
|
|
|
2022-11-15 04:47:38 -05:00
|
|
|
#define M62429_MAX_ATTN 87 // decibel
|
2022-02-12 03:23:23 -05:00
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
|
|
|
|
void M62429::begin(uint8_t dataPin, uint8_t clockPin)
|
|
|
|
{
|
|
|
|
_data = dataPin;
|
|
|
|
_clock = clockPin;
|
|
|
|
pinMode(_data, OUTPUT);
|
|
|
|
pinMode(_clock, OUTPUT);
|
|
|
|
digitalWrite(_data, LOW);
|
|
|
|
digitalWrite(_clock, LOW);
|
|
|
|
|
|
|
|
_muted = false;
|
|
|
|
setVolume(2, 0);
|
|
|
|
}
|
|
|
|
|
2021-05-28 07:36:28 -04:00
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
int M62429::getVolume(uint8_t channel)
|
|
|
|
{
|
|
|
|
if (channel > 2) return M62429_CHANNEL_ERROR;
|
|
|
|
return _vol[channel & 1];
|
|
|
|
}
|
|
|
|
|
2021-05-28 07:36:28 -04:00
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
int M62429::setVolume(uint8_t channel, uint8_t volume)
|
|
|
|
{
|
|
|
|
if (channel > 2) return M62429_CHANNEL_ERROR;
|
|
|
|
if (_muted) return M62429_MUTED;
|
|
|
|
|
2022-02-12 03:23:23 -05:00
|
|
|
uint16_t attn = (M62429_MAX_ATTN * volume)/255;
|
|
|
|
_setAttn(channel, attn);
|
2021-01-29 06:31:58 -05:00
|
|
|
|
2022-11-15 04:47:38 -05:00
|
|
|
// update cached values
|
2022-02-12 03:51:57 -05:00
|
|
|
if (channel == 0) _vol[0] = volume;
|
|
|
|
else if (channel == 1) _vol[1] = volume;
|
|
|
|
else _vol[0] = _vol[1] = volume;
|
2022-01-05 10:44:57 -05:00
|
|
|
return M62429_OK;
|
2021-01-29 06:31:58 -05:00
|
|
|
}
|
|
|
|
|
2021-05-28 07:36:28 -04:00
|
|
|
|
2022-02-13 09:58:42 -05:00
|
|
|
int M62429::incr(uint8_t channel)
|
2021-01-29 06:31:58 -05:00
|
|
|
{
|
2022-02-13 09:58:42 -05:00
|
|
|
if (channel > 2) return M62429_CHANNEL_ERROR;
|
2022-02-12 08:33:18 -05:00
|
|
|
if (_muted) return M62429_MUTED;
|
2022-02-13 09:58:42 -05:00
|
|
|
|
|
|
|
if ( ((channel == 0) || (channel == 2)) && (_vol[0] < 255))
|
2022-02-12 03:51:57 -05:00
|
|
|
{
|
|
|
|
_vol[0]++;
|
|
|
|
setVolume(0, _vol[0]);
|
|
|
|
}
|
2022-02-13 09:58:42 -05:00
|
|
|
if ( ((channel == 1) || (channel == 2)) && (_vol[1] < 255))
|
2022-02-12 03:51:57 -05:00
|
|
|
{
|
|
|
|
_vol[1]++;
|
|
|
|
setVolume(1, _vol[1]);
|
|
|
|
}
|
2022-02-12 08:33:18 -05:00
|
|
|
return M62429_OK;
|
2021-01-29 06:31:58 -05:00
|
|
|
}
|
|
|
|
|
2021-05-28 07:36:28 -04:00
|
|
|
|
2022-02-13 09:58:42 -05:00
|
|
|
int M62429::decr(uint8_t channel)
|
2021-01-29 06:31:58 -05:00
|
|
|
{
|
2022-02-13 09:58:42 -05:00
|
|
|
if (channel > 2) return M62429_CHANNEL_ERROR;
|
2022-02-12 08:33:18 -05:00
|
|
|
if (_muted) return M62429_MUTED;
|
2022-02-13 09:58:42 -05:00
|
|
|
|
|
|
|
if ( ((channel == 0) || (channel == 2)) && (_vol[0] > 0))
|
2022-02-12 03:51:57 -05:00
|
|
|
{
|
|
|
|
_vol[0]--;
|
|
|
|
setVolume(0, _vol[0]);
|
|
|
|
}
|
2022-02-13 09:58:42 -05:00
|
|
|
if ( ((channel == 1) || (channel == 2)) && (_vol[1] > 0))
|
2022-02-12 03:51:57 -05:00
|
|
|
{
|
|
|
|
_vol[1]--;
|
|
|
|
setVolume(1, _vol[1]);
|
|
|
|
}
|
2022-02-12 08:33:18 -05:00
|
|
|
return M62429_OK;
|
2021-01-29 06:31:58 -05:00
|
|
|
}
|
|
|
|
|
2021-05-28 07:36:28 -04:00
|
|
|
|
2022-02-12 08:33:18 -05:00
|
|
|
int M62429::average()
|
2021-01-29 06:31:58 -05:00
|
|
|
{
|
2022-02-12 08:33:18 -05:00
|
|
|
if (_muted) return M62429_MUTED;
|
2021-01-29 06:31:58 -05:00
|
|
|
uint8_t v = (((int)_vol[0]) + _vol[1]) / 2;
|
2022-02-12 03:51:57 -05:00
|
|
|
setVolume(2, v);
|
2022-02-12 08:33:18 -05:00
|
|
|
return M62429_OK;
|
2021-01-29 06:31:58 -05:00
|
|
|
}
|
|
|
|
|
2021-05-28 07:36:28 -04:00
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
void M62429::muteOn()
|
|
|
|
{
|
2022-02-12 08:33:18 -05:00
|
|
|
if (_muted) return;
|
2021-01-29 06:31:58 -05:00
|
|
|
_muted = true;
|
2022-11-15 04:47:38 -05:00
|
|
|
// if ((_vol[0] > 0) || (_vol[1] > 0)) _setAttn(2, 0);
|
|
|
|
_setAttn(2, 0); // mute must work unconditional.
|
2021-01-29 06:31:58 -05:00
|
|
|
}
|
|
|
|
|
2021-05-28 07:36:28 -04:00
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
void M62429::muteOff()
|
|
|
|
{
|
2022-02-12 08:33:18 -05:00
|
|
|
if (_muted == false) return;
|
2021-01-29 06:31:58 -05:00
|
|
|
_muted = false;
|
2022-02-13 09:58:42 -05:00
|
|
|
if (_vol[0] > 0) setVolume(0, _vol[0]);
|
|
|
|
if (_vol[1] > 0) setVolume(1, _vol[1]);
|
2021-01-29 06:31:58 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
2022-11-15 04:47:38 -05:00
|
|
|
// PRIVATE
|
2021-01-29 06:31:58 -05:00
|
|
|
//
|
|
|
|
|
2022-11-15 04:47:38 -05:00
|
|
|
// attn = 0..M62429_MAX_ATTN
|
2022-02-12 03:23:23 -05:00
|
|
|
void M62429::_setAttn(uint8_t channel, uint8_t attn)
|
2021-01-29 06:31:58 -05:00
|
|
|
{
|
2022-02-12 03:23:23 -05:00
|
|
|
uint16_t databits = 0x0200; // D9 latch bit
|
2022-01-05 10:44:57 -05:00
|
|
|
databits |= ((attn & 0x03) << 7); // D8 - D7
|
2022-02-12 03:23:23 -05:00
|
|
|
databits |= (attn & 0x7C); // D6 - D2
|
2022-11-15 04:47:38 -05:00
|
|
|
// channel == 2 -> both 0x00 is default
|
2022-01-05 10:44:57 -05:00
|
|
|
if (channel == 0) databits |= 0x03; // D0 - D1
|
|
|
|
if (channel == 1) databits |= 0x02; // D0 - D1
|
2021-01-29 06:31:58 -05:00
|
|
|
|
2022-01-05 10:44:57 -05:00
|
|
|
// write D0 - D9
|
2022-02-12 03:23:23 -05:00
|
|
|
for (uint8_t i = 0; i < 10; i++)
|
2021-01-29 06:31:58 -05:00
|
|
|
{
|
2022-02-12 03:23:23 -05:00
|
|
|
digitalWrite(_data, databits & 0x01);
|
|
|
|
databits >>= 1;
|
2021-01-29 06:31:58 -05:00
|
|
|
digitalWrite(_clock, HIGH);
|
2022-11-15 04:47:38 -05:00
|
|
|
// Note if _clock pulses are long enough, _data pulses are too.
|
2022-02-15 11:59:16 -05:00
|
|
|
#if M62429_CLOCK_DELAY > 0
|
|
|
|
delayMicroseconds(M62429_CLOCK_DELAY);
|
|
|
|
#endif
|
2021-12-21 06:50:11 -05:00
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
digitalWrite(_data, LOW);
|
|
|
|
digitalWrite(_clock, LOW);
|
2022-02-15 11:59:16 -05:00
|
|
|
#if M62429_CLOCK_DELAY > 0
|
|
|
|
delayMicroseconds(M62429_CLOCK_DELAY);
|
|
|
|
#endif
|
2021-01-29 06:31:58 -05:00
|
|
|
}
|
2022-01-05 10:44:57 -05:00
|
|
|
|
2022-11-15 04:47:38 -05:00
|
|
|
// Send D10 HIGH bit (Latch signal)
|
2021-01-29 06:31:58 -05:00
|
|
|
digitalWrite(_data, HIGH);
|
|
|
|
digitalWrite(_clock, HIGH);
|
2022-02-15 11:59:16 -05:00
|
|
|
#if M62429_CLOCK_DELAY > 0
|
|
|
|
delayMicroseconds(M62429_CLOCK_DELAY);
|
|
|
|
#endif
|
2021-12-21 06:50:11 -05:00
|
|
|
|
2022-11-15 04:47:38 -05:00
|
|
|
// latch D10 signal requires _clock low before _data
|
|
|
|
// make _data dummy write to keep timing constant
|
2022-01-05 10:44:57 -05:00
|
|
|
digitalWrite(_data, HIGH);
|
2021-01-29 06:31:58 -05:00
|
|
|
digitalWrite(_clock, LOW);
|
2022-02-15 11:59:16 -05:00
|
|
|
#if M62429_CLOCK_DELAY > 0
|
|
|
|
delayMicroseconds(M62429_CLOCK_DELAY);
|
|
|
|
#endif
|
2022-01-05 10:44:57 -05:00
|
|
|
|
|
|
|
digitalWrite(_data, LOW);
|
2022-02-15 11:59:16 -05:00
|
|
|
#if M62429_CLOCK_DELAY > 0
|
|
|
|
delayMicroseconds(M62429_CLOCK_DELAY);
|
|
|
|
#endif
|
2021-01-29 06:31:58 -05:00
|
|
|
}
|
|
|
|
|
2021-12-21 06:50:11 -05:00
|
|
|
|
2022-02-21 13:21:27 -05:00
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// M62429_RAW
|
|
|
|
//
|
|
|
|
void M62429_RAW::begin(uint8_t dataPin, uint8_t clockPin)
|
|
|
|
{
|
|
|
|
_data = dataPin;
|
|
|
|
_clock = clockPin;
|
|
|
|
pinMode(_data, OUTPUT);
|
|
|
|
pinMode(_clock, OUTPUT);
|
|
|
|
digitalWrite(_data, LOW);
|
|
|
|
digitalWrite(_clock, LOW);
|
|
|
|
|
|
|
|
setAttn(2, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int M62429_RAW::getAttn(uint8_t channel)
|
|
|
|
{
|
|
|
|
return _attn[channel & 1];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void M62429_RAW::setAttn(uint8_t channel, uint8_t attn)
|
|
|
|
{
|
|
|
|
uint16_t databits = 0x0200; // D9 latch bit
|
|
|
|
databits |= ((attn & 0x03) << 7); // D8 - D7
|
|
|
|
databits |= (attn & 0x7C); // D6 - D2
|
2022-11-15 04:47:38 -05:00
|
|
|
// channel == 2 -> both 0x00 is default
|
2022-02-21 13:21:27 -05:00
|
|
|
if (channel == 0) databits |= 0x03; // D0 - D1
|
|
|
|
if (channel == 1) databits |= 0x02; // D0 - D1
|
|
|
|
|
2022-11-15 04:47:38 -05:00
|
|
|
// write D0 - D9
|
2022-02-21 13:21:27 -05:00
|
|
|
for (uint8_t i = 0; i < 10; i++)
|
|
|
|
{
|
|
|
|
digitalWrite(_data, databits & 0x01);
|
|
|
|
databits >>= 1;
|
|
|
|
digitalWrite(_clock, HIGH);
|
|
|
|
// Note if _clock pulses are long enough, _data pulses are too.
|
|
|
|
#if M62429_CLOCK_DELAY > 0
|
|
|
|
delayMicroseconds(M62429_CLOCK_DELAY);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
digitalWrite(_data, LOW);
|
|
|
|
digitalWrite(_clock, LOW);
|
|
|
|
#if M62429_CLOCK_DELAY > 0
|
|
|
|
delayMicroseconds(M62429_CLOCK_DELAY);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2022-11-15 04:47:38 -05:00
|
|
|
// Send D10 HIGH bit (Latch signal)
|
2022-02-21 13:21:27 -05:00
|
|
|
digitalWrite(_data, HIGH);
|
|
|
|
digitalWrite(_clock, HIGH);
|
|
|
|
#if M62429_CLOCK_DELAY > 0
|
|
|
|
delayMicroseconds(M62429_CLOCK_DELAY);
|
|
|
|
#endif
|
|
|
|
|
2022-11-15 04:47:38 -05:00
|
|
|
// latch D10 signal requires _clock low before _data
|
|
|
|
// make _data dummy write to keep timing constant
|
2022-02-21 13:21:27 -05:00
|
|
|
digitalWrite(_data, HIGH);
|
|
|
|
digitalWrite(_clock, LOW);
|
|
|
|
#if M62429_CLOCK_DELAY > 0
|
|
|
|
delayMicroseconds(M62429_CLOCK_DELAY);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
digitalWrite(_data, LOW);
|
|
|
|
#if M62429_CLOCK_DELAY > 0
|
|
|
|
delayMicroseconds(M62429_CLOCK_DELAY);
|
|
|
|
#endif
|
|
|
|
|
2022-11-15 04:47:38 -05:00
|
|
|
// update cached values
|
2022-02-21 13:21:27 -05:00
|
|
|
if (channel == 0) _attn[0] = attn;
|
|
|
|
else if (channel == 1) _attn[1] = attn;
|
|
|
|
else _attn[0] = _attn[1] = attn;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
// -- END OF FILE --
|
2021-12-21 06:50:11 -05:00
|
|
|
|