Compare commits
12 Commits
Author | SHA1 | Date | |
---|---|---|---|
367d6f1187 | |||
df7e947616 | |||
4c8ca0246d | |||
b07cb67536 | |||
237cb1d18f | |||
f8ff866d32 | |||
b82c15f025 | |||
6c191892cc | |||
aba0476bbe | |||
6bf50707c4 | |||
7498016107 | |||
a60a0fa459 |
13
BOM.csv
Normal file
13
BOM.csv
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
Quantity,Manufacture Part Number,Manufacturer,Description,LCSC Part Number,Package
|
||||||
|
1,STM32F103C8,STM,Microcontroller ,,
|
||||||
|
1,SMD-5032_4P8M20pf20ppm,Zhejang Abel Elec,8Mhz Crystal,C133333,SMD-5032
|
||||||
|
1,DC-470-2.1GP,GANGYUAN,GANGYUAN DC-470-2.1GP ,C194407,
|
||||||
|
6,XKB5858-W-TP,XKB Enterprise,XKB Enterprise XKB5858-W-TP ,C381091,
|
||||||
|
4,WF06Q1002BTL,Walsn Tech Corp,10k 0603 Resistor,C305259,SMD0603
|
||||||
|
2,EWH1HM4R7D11OT,Aihua Group,4u7 leaded cap ,C105327,radial_D5P2
|
||||||
|
2,ECSS05072R2M101P00,Guangdong TOPAZ Elec Tech,2u2 leaded cap,C156723,radial_D5P2
|
||||||
|
12,PE105J2A0501,KYET,1u Polyester film cap,C390180,rectangular_7x5P5
|
||||||
|
2,0603CG200J201NT,Guangdong Fenghua Advanced Tech,20pF crystal cap,C63680,SMD0603
|
||||||
|
2,0603X106K160NT,Guangdong Fenghua Advanced Tech,10u cap,C70225,SMD0603
|
||||||
|
7,D-G080508G1-KS2,Wuxi ARK Tech Elec,LED bright green,C107402,SMD0805
|
||||||
|
1,TSA061G50-250,BRIGHT,switch ,C294501,THT
|
|
35
README.md
35
README.md
@ -1,27 +1,32 @@
|
|||||||
## Wat
|
![render image](doc/images/render.png)
|
||||||
|
|
||||||
This pcb is an audio multiplexer, meaning it can switch three analog inputs into one analog output.
|
<iframe src="https://myhub.autodesk360.com/ue28af833/shares/public/SH56a43QTfd62c1cd96847154d5ed1f7a373?mode=embed" width="640" height="480" allowfullscreen="true" webkitallowfullscreen="true" mozallowfullscreen="true" frameborder="0"></iframe>
|
||||||
|
|
||||||
## Why
|
This project contains all design files for a **6:1 audio multiplexer** , meaning it can switch six analog inputs into one analog output.
|
||||||
|
|
||||||
Sometimes you just need more inputs. And this is how you do it.
|
It is based on the [BD3491](https://www.digikey.de/product-detail/de/rohm-semiconductor/BD3491FS-E2/BD3491FS-E2TR-ND/5720882) which does everthing related to the Audio signals.
|
||||||
|
|
||||||
## How
|
On top of switching the inputs, it is also able to condition the signal. It can
|
||||||
|
|
||||||
The BD3491 does all the audio switching. It combines one 6 input switch and an equalizer into a simple package.
|
- Apply Bass-Boosting and Treble-Boosting (essentially a crappy 3-Point Equalizer)
|
||||||
The STM32 configures the BD3491 to switch to the specified inputs based on pressed buttons or software control.
|
- Amplify the input signal by up to 20dB
|
||||||
|
- Add attenuation to the individual channels (aka. balance the left and right channel)
|
||||||
|
|
||||||
# serial control Syntax
|
All of these feature of the chip can be activated with the on-board STM32, which can in turn be controlled
|
||||||
Upon connecting the stm32 to a PC using USB it will register itself as a new Serial Port. The following text commands can be issued via said Serial connection (the baudrate is irrelevant):
|
with either on-board buttons or via it's integrated USB port. One can either use the serial protocol directly
|
||||||
|
or a [GUI written in python](gui/README.md)
|
||||||
|
|
||||||
- `C[number]\n` will change the input to the specified channel. The stm32 echo the command as it was understood. e.g: When Sending `C0\n` it will respond `C0\r\n` to acknowledge the channel switched to **Input 1**. When issuing a `C10` there will be no response, since 10 is out of range. *NOTE:* when using the buttons on the PCB to switch the input, the stm will also issue a `C[number]\r\n` over the serial port if it is connected to notify the PCB of the external input change.
|
The Board can be supplied over said USB port as well (if the primary use-case implies it beeing connected
|
||||||
|
to the PC constantly) or by applying power using a 2.1mm Barrel Jack.
|
||||||
|
|
||||||
- `G[number]\n` will activate an input gain of [number] in dB. It will also respond with the closest gain it can do. e.g: `G10` will result in the stm responding `G12\r\n` which means it will add a 12db input boost, which was the closest matching _valid_ input gain value. You can check the datasheet of the BD3491 to find the possible gain values if this peaks your interest :)
|
For more details on the pcb, check the [PCB readme](kicad/README.md)
|
||||||
|
|
||||||
- `L[number]\n` or `R[number]\n` will activate an attenuator in either the left or the right channel. [number] is once again in dB. It works much like the `G`-command. Setting [number] to 0 will deactivate the Attenuation.
|
For details on the Serial command syntax and firmware flashing instructions, check the [firmware readme](firmware/README.md)
|
||||||
|
|
||||||
- `B[number]\n` or `T[number]\n` adds **B**ass or **T**reble gain to the output
|
|
||||||
|
|
||||||
- `M[0/1]\n` will either mute or unmute the output
|
# Why
|
||||||
|
|
||||||
|
Because ?
|
||||||
|
|
||||||
|
Sometimes you just need more inputs. This is how you do it.
|
||||||
|
|
||||||
- `S[0/1]\n` will connect all inputs to the output
|
|
||||||
|
BIN
case/case.f3z
Normal file
BIN
case/case.f3z
Normal file
Binary file not shown.
72170
case/case.iges
Normal file
72170
case/case.iges
Normal file
File diff suppressed because it is too large
Load Diff
75262
case/case.step
Normal file
75262
case/case.step
Normal file
File diff suppressed because it is too large
Load Diff
4397
doc/audioMux-brd.svg
Normal file
4397
doc/audioMux-brd.svg
Normal file
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 186 KiB |
BIN
doc/images/render.png
Normal file
BIN
doc/images/render.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 152 KiB |
@ -20,9 +20,9 @@ int bd_set_gain(I2C_HandleTypeDef * handle, uint8_t gain_in_db);
|
|||||||
uint8_t bd_set_attenuation(I2C_HandleTypeDef * handle, uint8_t right_channel, uint8_t attenuation_in_db);
|
uint8_t bd_set_attenuation(I2C_HandleTypeDef * handle, uint8_t right_channel, uint8_t attenuation_in_db);
|
||||||
|
|
||||||
// when gain == 0, cut bass boost
|
// when gain == 0, cut bass boost
|
||||||
void bd_set_bass_boost(I2C_HandleTypeDef * handle, uint8_t gain);
|
uint8_t bd_set_bass_boost(I2C_HandleTypeDef * handle, uint8_t gain);
|
||||||
// when gain == 0, cut treble boost
|
// when gain == 0, cut treble boost
|
||||||
void bd_set_treble_boost(I2C_HandleTypeDef * handle, uint8_t gain);
|
uint8_t bd_set_treble_boost(I2C_HandleTypeDef * handle, uint8_t gain);
|
||||||
|
|
||||||
enum BD_SOURROUND_GAIN {
|
enum BD_SOURROUND_GAIN {
|
||||||
BD_SOURROUND_OFF = 0,
|
BD_SOURROUND_OFF = 0,
|
||||||
|
@ -37,7 +37,20 @@ extern "C" {
|
|||||||
|
|
||||||
/* Exported types ------------------------------------------------------------*/
|
/* Exported types ------------------------------------------------------------*/
|
||||||
/* USER CODE BEGIN ET */
|
/* USER CODE BEGIN ET */
|
||||||
|
struct ui_state {
|
||||||
|
uint8_t oldchannel;
|
||||||
|
enum {
|
||||||
|
UI_STATE_NORMAL = 0,
|
||||||
|
UI_STATE_MUTE,
|
||||||
|
UI_STATE_SHORT,
|
||||||
|
} state;
|
||||||
|
|
||||||
|
uint8_t gain;
|
||||||
|
uint8_t bboost, tboost;
|
||||||
|
uint8_t latt, ratt;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct ui_state ui_state; // global ui state
|
||||||
/* USER CODE END ET */
|
/* USER CODE END ET */
|
||||||
|
|
||||||
/* Exported constants --------------------------------------------------------*/
|
/* Exported constants --------------------------------------------------------*/
|
||||||
@ -54,8 +67,12 @@ extern "C" {
|
|||||||
void Error_Handler(void);
|
void Error_Handler(void);
|
||||||
|
|
||||||
void set_input(uint8_t channel);
|
void set_input(uint8_t channel);
|
||||||
|
int get_input();
|
||||||
void set_attenuation(uint8_t left, uint8_t right);
|
void set_attenuation(uint8_t left, uint8_t right);
|
||||||
void set_mute(uint8_t mute);
|
void set_mute(uint8_t mute); //< tries to switch to muted ui state
|
||||||
|
int is_muted(); //< returns whether the ui is muted
|
||||||
|
void set_short(uint8_t shorted); //< tries to switch to shorted ui state
|
||||||
|
int is_shorted();
|
||||||
|
|
||||||
/* USER CODE BEGIN EFP */
|
/* USER CODE BEGIN EFP */
|
||||||
|
|
||||||
|
35
firmware/README.md
Normal file
35
firmware/README.md
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
|
||||||
|
# Building the Firmware
|
||||||
|
|
||||||
|
In order to build the firmware, [platformio](https://platformio.org/install/cli) must be installed.
|
||||||
|
|
||||||
|
To build the firmware, navigate to this folder using the terminal of your choice and type
|
||||||
|
|
||||||
|
```bash
|
||||||
|
platformio run
|
||||||
|
```
|
||||||
|
|
||||||
|
## Flashing the firmware
|
||||||
|
|
||||||
|
If you happen to have an stlink compatible interface (e.g the [programmer attached the nucleo-boards](https://jeelabs.org/book/1547a/])),
|
||||||
|
then (after connecting said interface to the PC and the PCB),
|
||||||
|
the firmware can be flashed with
|
||||||
|
|
||||||
|
```bash
|
||||||
|
platformio run -t upload
|
||||||
|
```
|
||||||
|
|
||||||
|
# serial control Syntax
|
||||||
|
Upon connecting the stm32 to a PC using USB it will register itself as a new Serial Port. The following text commands can be issued via said Serial connection (the baudrate is irrelevant):
|
||||||
|
|
||||||
|
- `C[number]\n` will change the input to the specified channel. The stm32 echo the command as it was understood. e.g: When Sending `C0\n` it will respond `C0\r\n` to acknowledge the channel switched to **Input 1**. When issuing a `C10` there will be no response, since 10 is out of range. *NOTE:* when using the buttons on the PCB to switch the input, the stm will also issue a `C[number]\r\n` over the serial port if it is connected to notify the PCB of the external input change.
|
||||||
|
|
||||||
|
- `G[number]\n` will activate an input gain of [number] in dB. It will also respond with the closest gain it can do. e.g: `G10` will result in the stm responding `G12\r\n` which means it will add a 12db input boost, which was the closest matching _valid_ input gain value. You can check the datasheet of the BD3491 to find the possible gain values if this peaks your interest :)
|
||||||
|
|
||||||
|
- `L[number]\n` or `R[number]\n` will activate an attenuator in either the left or the right channel. [number] is once again in dB. It works much like the `G`-command. Setting [number] to 0 will deactivate the Attenuation.
|
||||||
|
|
||||||
|
- `B[number]\n` or `T[number]\n` adds **B**ass or **T**reble gain to the output
|
||||||
|
|
||||||
|
- `M[0/1]\n` will either mute or unmute the output
|
||||||
|
|
||||||
|
- `S[0/1]\n` will connect all inputs to the output
|
@ -64,19 +64,30 @@ int bd_set_gain(I2C_HandleTypeDef * handle, uint8_t gain_in_db) {
|
|||||||
uint8_t bd_set_attenuation(I2C_HandleTypeDef * handle, uint8_t right_channel, uint8_t attenuation_in_db) {
|
uint8_t bd_set_attenuation(I2C_HandleTypeDef * handle, uint8_t right_channel, uint8_t attenuation_in_db) {
|
||||||
if ((attenuation_in_db&0x7F) > 87)
|
if ((attenuation_in_db&0x7F) > 87)
|
||||||
attenuation_in_db = BD_INF_ATTENUATION;
|
attenuation_in_db = BD_INF_ATTENUATION;
|
||||||
|
|
||||||
bd_write_reg(handle, 0x21 + right_channel, attenuation_in_db | 0x80);
|
if (right_channel)
|
||||||
|
right_channel = 1;
|
||||||
|
|
||||||
|
bd_write_reg(handle, 0x22 - right_channel, attenuation_in_db | 0x80);
|
||||||
return attenuation_in_db;
|
return attenuation_in_db;
|
||||||
}
|
}
|
||||||
|
|
||||||
// when gain == 0, cut bass boost
|
// when gain == 0, cut bass boost
|
||||||
void bd_set_bass_boost(I2C_HandleTypeDef * handle, uint8_t gain) {
|
uint8_t bd_set_bass_boost(I2C_HandleTypeDef * handle, uint8_t gain) {
|
||||||
|
if (gain > 0x07) gain = 0x07;
|
||||||
|
|
||||||
bd_write_reg(handle, 0x51, (gain == 0)?(0x80):(0x00) | (gain&0x07) << 1);
|
bd_write_reg(handle, 0x51, (gain == 0)?(0x80):(0x00) | (gain&0x07) << 1);
|
||||||
|
|
||||||
|
return gain;
|
||||||
}
|
}
|
||||||
|
|
||||||
// when gain == 0, cut treble boost
|
// when gain == 0, cut treble boost
|
||||||
void bd_set_treble_boost(I2C_HandleTypeDef * handle, uint8_t gain) {
|
uint8_t bd_set_treble_boost(I2C_HandleTypeDef * handle, uint8_t gain) {
|
||||||
|
if (gain > 0x07) gain = 0x07;
|
||||||
|
|
||||||
bd_write_reg(handle, 0x57, (gain == 0)?(0x80):(0x00) | (gain&0x07) << 1);
|
bd_write_reg(handle, 0x57, (gain == 0)?(0x80):(0x00) | (gain&0x07) << 1);
|
||||||
|
|
||||||
|
return gain;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bd_set_sourround(I2C_HandleTypeDef * handle, enum BD_SOURROUND_GAIN gain) {
|
void bd_set_sourround(I2C_HandleTypeDef * handle, enum BD_SOURROUND_GAIN gain) {
|
||||||
|
@ -102,58 +102,92 @@ int test_button_pressed() {
|
|||||||
#undef TEST_BUTTON
|
#undef TEST_BUTTON
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ui_state {
|
struct ui_state ui_state = {
|
||||||
uint8_t oldchannel;
|
|
||||||
uint8_t mute;
|
|
||||||
} ui_state = {
|
|
||||||
.oldchannel = -1,
|
.oldchannel = -1,
|
||||||
.mute = 0,
|
.state = UI_STATE_NORMAL,
|
||||||
};
|
};
|
||||||
|
|
||||||
void set_input(uint8_t channel) {
|
void set_input(uint8_t channel) {
|
||||||
if (ui_state.oldchannel == channel || channel >= 6)
|
if (ui_state.state != UI_STATE_NORMAL || ui_state.oldchannel == channel || channel >= 6)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
set_input_led(ui_state.oldchannel, 0);
|
set_input_led(ui_state.oldchannel, 0);
|
||||||
|
|
||||||
|
set_input_led(channel, 1);
|
||||||
|
|
||||||
// do not disturb the mute mode
|
// invert bd inputs to match the numbers on the case
|
||||||
if (!ui_state.mute)
|
bd_set_input(&hi2c1, 5-channel);
|
||||||
{
|
|
||||||
set_input_led(channel, 1);
|
|
||||||
|
|
||||||
// invert bd inputs to match the numbers on the case
|
|
||||||
bd_set_input(&hi2c1, 5-channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
ui_state.oldchannel = channel;
|
ui_state.oldchannel = channel;
|
||||||
|
|
||||||
printf("C%d\n", channel);
|
printf("C%d\n", channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int get_input() {
|
||||||
|
return ui_state.oldchannel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// only mute if the ui allows to
|
||||||
void set_mute(uint8_t mute) {
|
void set_mute(uint8_t mute) {
|
||||||
if(ui_state.mute == mute)
|
if(UI_STATE_MUTE == ui_state.state && mute)
|
||||||
|
// no state change required
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (0 == (ui_state.mute = mute)) {
|
// figure out the state transition
|
||||||
|
if (UI_STATE_NORMAL == ui_state.state && mute) {
|
||||||
|
ui_state.state = UI_STATE_MUTE;
|
||||||
|
HAL_GPIO_WritePin(USER_LED_GPIO_Port, USER_LED_Pin, 1);
|
||||||
|
set_input_led(ui_state.oldchannel, 0);
|
||||||
|
bd_set_input(&hi2c1, BD_INPUT_MUTE);
|
||||||
|
}
|
||||||
|
else if (UI_STATE_MUTE == ui_state.state && !mute)
|
||||||
|
{
|
||||||
|
ui_state.state = UI_STATE_NORMAL;
|
||||||
// hack to make reactivation of the last channel easier
|
// hack to make reactivation of the last channel easier
|
||||||
uint8_t old_input = ui_state.oldchannel;
|
uint8_t old_input = ui_state.oldchannel;
|
||||||
ui_state.oldchannel = -1;
|
ui_state.oldchannel = -1;
|
||||||
|
|
||||||
set_input(old_input);
|
set_input(old_input);
|
||||||
HAL_GPIO_WritePin(USER_LED_GPIO_Port, USER_LED_Pin, 0);
|
HAL_GPIO_WritePin(USER_LED_GPIO_Port, USER_LED_Pin, 0);
|
||||||
}
|
|
||||||
else {
|
|
||||||
HAL_GPIO_WritePin(USER_LED_GPIO_Port, USER_LED_Pin, 1);
|
|
||||||
set_input_led(ui_state.oldchannel, 0);
|
|
||||||
bd_set_input(&hi2c1, BD_INPUT_MUTE);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
printf("M%d\n", ui_state.mute?1:0);
|
int is_muted() {
|
||||||
|
return ui_state.state == UI_STATE_MUTE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_short(uint8_t do_short) {
|
||||||
|
// test for possible state changes
|
||||||
|
if (UI_STATE_NORMAL == ui_state.state && do_short)
|
||||||
|
{
|
||||||
|
ui_state.state = UI_STATE_SHORT;
|
||||||
|
bd_set_input(&hi2c1, BD_INPUT_ALL);
|
||||||
|
|
||||||
|
// visualize that all inputs are shorted
|
||||||
|
for (int i = 0; i < 6; ++i)
|
||||||
|
set_input_led(i, 1);
|
||||||
|
}
|
||||||
|
else if (UI_STATE_SHORT == ui_state.state && !do_short)
|
||||||
|
{
|
||||||
|
ui_state.state = UI_STATE_NORMAL;
|
||||||
|
|
||||||
|
for (int i = 0; i < 6; ++i)
|
||||||
|
set_input_led(i, 0);
|
||||||
|
|
||||||
|
// reactivate currently selected input
|
||||||
|
uint8_t old_input = ui_state.oldchannel;
|
||||||
|
ui_state.oldchannel = -1;
|
||||||
|
set_input(old_input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int is_shorted() {
|
||||||
|
return ui_state.state == UI_STATE_SHORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_attenuation(uint8_t left, uint8_t right) {
|
void set_attenuation(uint8_t left, uint8_t right) {
|
||||||
bd_set_attenuation(&hi2c1, 0, left);
|
ui_state.latt = bd_set_attenuation(&hi2c1, 0, left);
|
||||||
bd_set_attenuation(&hi2c1, 1, right);
|
ui_state.ratt = bd_set_attenuation(&hi2c1, 1, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -202,6 +236,7 @@ int main(void)
|
|||||||
set_attenuation(0,0);
|
set_attenuation(0,0);
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int button_timeout = 0;
|
int button_timeout = 0;
|
||||||
|
|
||||||
/* USER CODE END 2 */
|
/* USER CODE END 2 */
|
||||||
|
|
||||||
/* Infinite loop */
|
/* Infinite loop */
|
||||||
@ -226,7 +261,8 @@ int main(void)
|
|||||||
|
|
||||||
if (1000 < button_timeout) {
|
if (1000 < button_timeout) {
|
||||||
// long press, toggle mute
|
// long press, toggle mute
|
||||||
set_mute(!ui_state.mute);
|
set_mute(!is_muted());
|
||||||
|
printf("M%d\n", is_muted());
|
||||||
button_timeout = 0;
|
button_timeout = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,16 +138,24 @@ int parse_buffer() {
|
|||||||
uint16_t gain;
|
uint16_t gain;
|
||||||
if (next_arg_unsigned(&gain)) break;
|
if (next_arg_unsigned(&gain)) break;
|
||||||
|
|
||||||
printf("G%d\n", bd_set_gain(&hi2c1, gain));
|
printf("G%d\n", (ui_state.gain = bd_set_gain(&hi2c1, gain)));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'L':
|
case 'L':
|
||||||
case 'R':
|
case 'R':
|
||||||
{
|
{
|
||||||
uint16_t att;
|
uint16_t att;
|
||||||
if (next_arg_unsigned(&att)) break;
|
uint8_t dir = 0;
|
||||||
|
uint8_t * save = &ui_state.latt;
|
||||||
|
|
||||||
printf("%c%d\n", temp, bd_set_attenuation(&hi2c1, temp == 'R', att&0xFF));
|
if (next_arg_unsigned(&att)) break;
|
||||||
|
|
||||||
|
if (temp == 'R') {
|
||||||
|
dir = 1;
|
||||||
|
save = &ui_state.ratt;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%c%d\n", temp, (*save = bd_set_attenuation(&hi2c1, dir, att&0xFF)));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'M':
|
case 'M':
|
||||||
@ -156,11 +164,46 @@ int parse_buffer() {
|
|||||||
if (next_arg_unsigned(&mute)) break;
|
if (next_arg_unsigned(&mute)) break;
|
||||||
|
|
||||||
set_mute(mute);
|
set_mute(mute);
|
||||||
|
printf("M%d\n", is_muted());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
{
|
||||||
|
uint16_t shorted;
|
||||||
|
if (next_arg_unsigned(&shorted)) break;
|
||||||
|
|
||||||
|
set_short(shorted);
|
||||||
|
printf("S%d\n", is_shorted());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'B':
|
case 'B':
|
||||||
case 'T':
|
{
|
||||||
|
uint16_t boost;
|
||||||
|
if (next_arg_unsigned(&boost)) break;
|
||||||
|
|
||||||
|
printf("B%d\n", (ui_state.bboost = bd_set_bass_boost(&hi2c1, boost)));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'T':
|
||||||
|
{
|
||||||
|
uint16_t boost;
|
||||||
|
if (next_arg_unsigned(&boost)) break;
|
||||||
|
|
||||||
|
printf("T%d\n", (ui_state.tboost = bd_set_treble_boost(&hi2c1, boost)));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
{
|
||||||
|
// return the system state
|
||||||
|
printf("M%d\n", is_muted());
|
||||||
|
printf("S%d\n", is_shorted());
|
||||||
|
printf("C%d\n", get_input());
|
||||||
|
printf("B%d\n", ui_state.bboost);
|
||||||
|
printf("T%d\n", ui_state.tboost);
|
||||||
|
printf("L%d\n", ui_state.latt);
|
||||||
|
printf("R%d\n", ui_state.ratt);
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
printf("E\n");
|
printf("E\n");
|
||||||
}
|
}
|
||||||
|
3
gui/.vscode/settings.json
vendored
Normal file
3
gui/.vscode/settings.json
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"python.pythonPath": "/usr/bin/python"
|
||||||
|
}
|
33
gui/app.spec
Normal file
33
gui/app.spec
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# -*- mode: python ; coding: utf-8 -*-
|
||||||
|
|
||||||
|
block_cipher = None
|
||||||
|
|
||||||
|
|
||||||
|
a = Analysis(['app.py'],
|
||||||
|
pathex=['/home/julian/git/audioMux/gui'],
|
||||||
|
binaries=[],
|
||||||
|
datas=[],
|
||||||
|
hiddenimports=[],
|
||||||
|
hookspath=[],
|
||||||
|
runtime_hooks=[],
|
||||||
|
excludes=[],
|
||||||
|
win_no_prefer_redirects=False,
|
||||||
|
win_private_assemblies=False,
|
||||||
|
cipher=block_cipher,
|
||||||
|
noarchive=False)
|
||||||
|
pyz = PYZ(a.pure, a.zipped_data,
|
||||||
|
cipher=block_cipher)
|
||||||
|
exe = EXE(pyz,
|
||||||
|
a.scripts,
|
||||||
|
a.binaries,
|
||||||
|
a.zipfiles,
|
||||||
|
a.datas,
|
||||||
|
[],
|
||||||
|
name='app',
|
||||||
|
debug=False,
|
||||||
|
bootloader_ignore_signals=False,
|
||||||
|
strip=False,
|
||||||
|
upx=True,
|
||||||
|
upx_exclude=[],
|
||||||
|
runtime_tmpdir=None,
|
||||||
|
console=False )
|
BIN
gui/dist/gui_linux
vendored
Executable file
BIN
gui/dist/gui_linux
vendored
Executable file
Binary file not shown.
77
gui/icon.svg
Normal file
77
gui/icon.svg
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="10mm"
|
||||||
|
height="10mm"
|
||||||
|
viewBox="0 0 10 10"
|
||||||
|
version="1.1"
|
||||||
|
id="svg8"
|
||||||
|
inkscape:version="0.92.4 5da689c313, 2019-01-14"
|
||||||
|
sodipodi:docname="icon.svg"
|
||||||
|
inkscape:export-filename="/home/julian/git/audioMux/gui/icon/1.png"
|
||||||
|
inkscape:export-xdpi="325.12"
|
||||||
|
inkscape:export-ydpi="325.12">
|
||||||
|
<defs
|
||||||
|
id="defs2" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="5.6"
|
||||||
|
inkscape:cx="4.446261"
|
||||||
|
inkscape:cy="56.922155"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:window-width="1918"
|
||||||
|
inkscape:window-height="1058"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="20"
|
||||||
|
inkscape:window-maximized="1" />
|
||||||
|
<metadata
|
||||||
|
id="metadata5">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Ebene 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(0,-287)">
|
||||||
|
<circle
|
||||||
|
style="color:#000000;overflow:visible;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#298f29;stroke-width:0.9441849;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path815"
|
||||||
|
cx="5"
|
||||||
|
cy="292"
|
||||||
|
r="4.5279074" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-size:4.23333311px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:#beb3b3;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;"
|
||||||
|
x="2.6935086"
|
||||||
|
y="294.57178"
|
||||||
|
id="text819"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan817"
|
||||||
|
x="2.6935086"
|
||||||
|
y="294.57178"
|
||||||
|
style="font-size:7.05555534px;fill:#000000;fill-opacity:1;stroke:#beb3b3;stroke-width:0.26458332px;stroke-opacity:1;">1</tspan></text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.6 KiB |
BIN
gui/icon/1.png
Normal file
BIN
gui/icon/1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.2 KiB |
55
gui/tray.py
Normal file
55
gui/tray.py
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import wx
|
||||||
|
from wx import adv
|
||||||
|
|
||||||
|
def create_menu_item(menu, label, func):
|
||||||
|
item = wx.MenuItem(menu, -1, label)
|
||||||
|
menu.Bind(wx.EVT_MENU, func, id=item.GetId())
|
||||||
|
menu.AppendItem(item)
|
||||||
|
return item
|
||||||
|
|
||||||
|
|
||||||
|
class Tray(wx.adv.TaskBarIcon):
|
||||||
|
def __init__(self, parent):
|
||||||
|
super().__init__()
|
||||||
|
self.Bind(wx.adv.EVT_TASKBAR_LEFT_DOWN, self.OnLeftDown)
|
||||||
|
self.SetIcon(wx.Icon("icon/1.png"))
|
||||||
|
self.parent = parent
|
||||||
|
|
||||||
|
def CreatePopupMenu(self):
|
||||||
|
menu = wx.Menu()
|
||||||
|
hidem = wx.MenuItem(menu, wx.ID_ANY, 'Show Window')
|
||||||
|
menu.Bind(wx.EVT_MENU, self.ShowParent, id=hidem.GetId())
|
||||||
|
menu.Append(hidem)
|
||||||
|
menu.AppendSeparator()
|
||||||
|
|
||||||
|
quitm = wx.MenuItem(menu, wx.ID_ANY, 'Quit')
|
||||||
|
menu.Bind(wx.EVT_MENU, self.OnExit, id=quitm.GetId())
|
||||||
|
menu.Append(quitm)
|
||||||
|
return menu
|
||||||
|
|
||||||
|
def CreateSelectionMenu(self):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def OnLeftDown(self, event):
|
||||||
|
menu = self.CreateSelectionMenu()
|
||||||
|
if menu:
|
||||||
|
self.PopupMenu(menu)
|
||||||
|
|
||||||
|
|
||||||
|
def OnExit(self, event):
|
||||||
|
# close self and parent
|
||||||
|
wx.CallAfter(self.Destroy)
|
||||||
|
wx.CallAfter(self.parent.Destroy)
|
||||||
|
|
||||||
|
def ShowParent(self, evt):
|
||||||
|
self.parent.Show()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app = wx.App()
|
||||||
|
|
||||||
|
|
||||||
|
# create an empty frame to keep the main loop running
|
||||||
|
Tray(wx.Frame(None))
|
||||||
|
|
||||||
|
app.MainLoop()
|
||||||
|
|
29
kicad/README.md
Normal file
29
kicad/README.md
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
![THE PCB](../doc/audioMux-brd.svg)
|
||||||
|
|
||||||
|
There are a total of six solderjumpers on the board:
|
||||||
|
|
||||||
|
# switching to the barrel jack as voltage supply
|
||||||
|
|
||||||
|
*JP3* and *JP4* set the source for the supply voltage.
|
||||||
|
*JP4* connects the voltage input to the barrel jack, *JP4* connects it to the USB +5V rail.
|
||||||
|
|
||||||
|
Per Default JP4 is closed and JP3 is open, making the default way of supplying voltage the USB jack.
|
||||||
|
|
||||||
|
If the Barrel Jack should be used, then **JP4 has to be opened first** by cutting the trace which shorts it by default, otherwise **the USB voltage will be shorted with the barrel jack, causing potential damage to the USB port**.
|
||||||
|
Afterwards, *JP3* can be closed with a small blob of solder.
|
||||||
|
|
||||||
|
# activating the equalizer
|
||||||
|
|
||||||
|
*JP1* and *JP2* connect the output of the Audio switching part of the Rohm chip.
|
||||||
|
When left in the default setting, they will connect them to the output jack directly, bypassing the Equalisation part of the chip completely.
|
||||||
|
|
||||||
|
By selecting the other possible path, the equalisation circuit becomes usable. For this to work,
|
||||||
|
*JP7* and *JP8* have to be closed with small solder blobs as well, since those connect the equalizers
|
||||||
|
output to the output audio jack.
|
||||||
|
|
||||||
|
# Assembling the rest
|
||||||
|
|
||||||
|
For assembly of the board, check the [documentation folder](../doc). It contains the [interactive bill of materials](../doc/interactive_placement.html),
|
||||||
|
which indicates what components go where.
|
||||||
|
|
||||||
|
Also take a look at the [BOM](../doc/BOM.xlsx) for what components can be sourced where.
|
Loading…
Reference in New Issue
Block a user