summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/keymaps/keymap-fiiom3k.c42
-rw-r--r--firmware/export/ak4376.h4
-rw-r--r--firmware/export/config/fiiom3k.h8
-rw-r--r--firmware/target/mips/ingenic_x1000/fiiom3k/audiohw-fiiom3k.c127
-rw-r--r--manual/platform/keymap-fiiom3k.tex12
5 files changed, 183 insertions, 10 deletions
diff --git a/apps/keymaps/keymap-fiiom3k.c b/apps/keymaps/keymap-fiiom3k.c
index a97be0870d..337a2184cd 100644
--- a/apps/keymaps/keymap-fiiom3k.c
+++ b/apps/keymaps/keymap-fiiom3k.c
@@ -138,6 +138,16 @@ static const struct button_mapping button_context_settings[] = {
138 LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) 138 LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
139}; /* button_context_settings */ 139}; /* button_context_settings */
140 140
141static const struct button_mapping button_context_settings_rectrigger[] = {
142 {ACTION_SETTINGS_INC, BUTTON_RIGHT, BUTTON_NONE},
143 {ACTION_SETTINGS_INCREPEAT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE},
144 {ACTION_SETTINGS_INCBIGSTEP, BUTTON_VOL_UP, BUTTON_NONE},
145 {ACTION_SETTINGS_DEC, BUTTON_LEFT, BUTTON_NONE},
146 {ACTION_SETTINGS_DECREPEAT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE},
147 {ACTION_SETTINGS_DECBIGSTEP, BUTTON_VOL_DOWN, BUTTON_NONE},
148 LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
149}; /* button_context_settings_rectrigger */
150
141static const struct button_mapping button_context_settings_eq[] = { 151static const struct button_mapping button_context_settings_eq[] = {
142 {ACTION_SETTINGS_INC, BUTTON_RIGHT, BUTTON_NONE}, 152 {ACTION_SETTINGS_INC, BUTTON_RIGHT, BUTTON_NONE},
143 {ACTION_SETTINGS_INCREPEAT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE}, 153 {ACTION_SETTINGS_INCREPEAT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE},
@@ -203,6 +213,33 @@ static const struct button_mapping button_context_yesnoscreen[] = {
203 LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) 213 LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
204}; /* button_context_yesnoscreen */ 214}; /* button_context_yesnoscreen */
205 215
216static const struct button_mapping button_context_recscreen[] = {
217 {ACTION_REC_PAUSE, BUTTON_SELECT, BUTTON_NONE},
218 {ACTION_REC_PAUSE, BUTTON_PLAY, BUTTON_NONE},
219 {ACTION_REC_NEWFILE, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_SELECT},
220 {ACTION_REC_NEWFILE, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_PLAY},
221 {ACTION_STD_MENU, BUTTON_MENU, BUTTON_NONE},
222 {ACTION_STD_CANCEL, BUTTON_BACK, BUTTON_NONE},
223 {ACTION_STD_CANCEL, BUTTON_POWER, BUTTON_NONE},
224 {ACTION_STD_PREV, BUTTON_UP, BUTTON_NONE},
225 {ACTION_STD_PREVREPEAT, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE},
226 {ACTION_STD_NEXT, BUTTON_DOWN, BUTTON_NONE},
227 {ACTION_STD_NEXTREPEAT, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE},
228 {ACTION_STD_PREV, BUTTON_SCROLL_BACK, BUTTON_NONE},
229 {ACTION_STD_PREVREPEAT, BUTTON_SCROLL_BACK|BUTTON_REPEAT, BUTTON_NONE},
230 {ACTION_STD_NEXT, BUTTON_SCROLL_FWD, BUTTON_NONE},
231 {ACTION_STD_NEXTREPEAT, BUTTON_SCROLL_FWD|BUTTON_REPEAT, BUTTON_NONE},
232 {ACTION_SETTINGS_INC, BUTTON_VOL_UP, BUTTON_NONE},
233 {ACTION_SETTINGS_INCREPEAT, BUTTON_VOL_UP|BUTTON_REPEAT, BUTTON_NONE},
234 {ACTION_SETTINGS_DEC, BUTTON_VOL_DOWN, BUTTON_NONE},
235 {ACTION_SETTINGS_DECREPEAT, BUTTON_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE},
236 {ACTION_SETTINGS_INC, BUTTON_RIGHT, BUTTON_NONE},
237 {ACTION_SETTINGS_INCREPEAT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE},
238 {ACTION_SETTINGS_DEC, BUTTON_LEFT, BUTTON_NONE},
239 {ACTION_SETTINGS_DECREPEAT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE},
240 LAST_ITEM_IN_LIST
241}; /* button_context_recscreen */
242
206static const struct button_mapping button_context_keyboard[] = { 243static const struct button_mapping button_context_keyboard[] = {
207 {ACTION_KBD_UP, BUTTON_UP, BUTTON_NONE}, 244 {ACTION_KBD_UP, BUTTON_UP, BUTTON_NONE},
208 {ACTION_KBD_DOWN, BUTTON_DOWN, BUTTON_NONE}, 245 {ACTION_KBD_DOWN, BUTTON_DOWN, BUTTON_NONE},
@@ -315,8 +352,9 @@ const struct button_mapping* get_context_mapping(int context)
315 return button_context_list; 352 return button_context_list;
316 case CONTEXT_SETTINGS: 353 case CONTEXT_SETTINGS:
317 case CONTEXT_SETTINGS_TIME: 354 case CONTEXT_SETTINGS_TIME:
318 case CONTEXT_SETTINGS_RECTRIGGER:
319 return button_context_settings; 355 return button_context_settings;
356 case CONTEXT_SETTINGS_RECTRIGGER:
357 return button_context_settings_rectrigger;
320 case CONTEXT_SETTINGS_EQ: 358 case CONTEXT_SETTINGS_EQ:
321 case CONTEXT_SETTINGS_COLOURCHOOSER: 359 case CONTEXT_SETTINGS_COLOURCHOOSER:
322 return button_context_settings_eq; 360 return button_context_settings_eq;
@@ -326,6 +364,8 @@ const struct button_mapping* get_context_mapping(int context)
326 return button_context_pitchscreen; 364 return button_context_pitchscreen;
327 case CONTEXT_YESNOSCREEN: 365 case CONTEXT_YESNOSCREEN:
328 return button_context_yesnoscreen; 366 return button_context_yesnoscreen;
367 case CONTEXT_RECSCREEN:
368 return button_context_recscreen;
329 case CONTEXT_KEYBOARD: 369 case CONTEXT_KEYBOARD:
330 return button_context_keyboard; 370 return button_context_keyboard;
331 case CONTEXT_USB_HID: 371 case CONTEXT_USB_HID:
diff --git a/firmware/export/ak4376.h b/firmware/export/ak4376.h
index 0ae156bc37..ad842b2b80 100644
--- a/firmware/export/ak4376.h
+++ b/firmware/export/ak4376.h
@@ -22,7 +22,9 @@
22#ifndef __AK4376_H__ 22#ifndef __AK4376_H__
23#define __AK4376_H__ 23#define __AK4376_H__
24 24
25#define AUDIOHW_CAPS (FILTER_ROLL_OFF_CAP|POWER_MODE_CAP) 25/* The target config must define this; defining it here would prevent
26 the target from supporting audio recording via an alternate codec. */
27/* #define AUDIOHW_CAPS (FILTER_ROLL_OFF_CAP|POWER_MODE_CAP) */
26#define AUDIOHW_HAVE_SHORT2_ROLL_OFF 28#define AUDIOHW_HAVE_SHORT2_ROLL_OFF
27 29
28#define AK4376_MIN_VOLUME (-890) 30#define AK4376_MIN_VOLUME (-890)
diff --git a/firmware/export/config/fiiom3k.h b/firmware/export/config/fiiom3k.h
index 45c2150208..ea97d52d76 100644
--- a/firmware/export/config/fiiom3k.h
+++ b/firmware/export/config/fiiom3k.h
@@ -55,11 +55,15 @@
55 55
56/* Codec / audio hardware defines */ 56/* Codec / audio hardware defines */
57#define HW_SAMPR_CAPS SAMPR_CAP_ALL_192 57#define HW_SAMPR_CAPS SAMPR_CAP_ALL_192
58#define REC_SAMPR_CAPS (SAMPR_CAP_ALL_96 & ~SAMPR_CAP_64)
59#define INPUT_SRC_CAPS SRC_CAP_MIC
60#define AUDIOHW_CAPS (FILTER_ROLL_OFF_CAP|POWER_MODE_CAP|MIC_GAIN_CAP)
61#define HAVE_RECORDING
58#define HAVE_AK4376 62#define HAVE_AK4376
63#define HAVE_X1000_ICODEC_REC
59#define HAVE_SW_TONE_CONTROLS 64#define HAVE_SW_TONE_CONTROLS
60#define HAVE_SW_VOLUME_CONTROL 65#define HAVE_SW_VOLUME_CONTROL
61 66#define DEFAULT_REC_MIC_GAIN 12
62/* TODO: Need to implement recording */
63 67
64/* Button defines */ 68/* Button defines */
65#define CONFIG_KEYPAD FIIO_M3K_PAD 69#define CONFIG_KEYPAD FIIO_M3K_PAD
diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/audiohw-fiiom3k.c b/firmware/target/mips/ingenic_x1000/fiiom3k/audiohw-fiiom3k.c
index f7dced8f54..9374d23a81 100644
--- a/firmware/target/mips/ingenic_x1000/fiiom3k/audiohw-fiiom3k.c
+++ b/firmware/target/mips/ingenic_x1000/fiiom3k/audiohw-fiiom3k.c
@@ -7,7 +7,7 @@
7 * \/ \/ \/ \/ \/ 7 * \/ \/ \/ \/ \/
8 * $Id$ 8 * $Id$
9 * 9 *
10 * Copyright (C) 2021 Aidan MacDonald 10 * Copyright (C) 2021-2022 Aidan MacDonald
11 * 11 *
12 * This program is free software; you can redistribute it and/or 12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License 13 * modify it under the terms of the GNU General Public License
@@ -20,6 +20,7 @@
20 ****************************************************************************/ 20 ****************************************************************************/
21 21
22#include "audiohw.h" 22#include "audiohw.h"
23#include "audio.h"
23#include "system.h" 24#include "system.h"
24#include "pcm_sampr.h" 25#include "pcm_sampr.h"
25#include "aic-x1000.h" 26#include "aic-x1000.h"
@@ -27,6 +28,11 @@
27#include "gpio-x1000.h" 28#include "gpio-x1000.h"
28#include "logf.h" 29#include "logf.h"
29 30
31static int cur_audio_source = AUDIO_SRC_PLAYBACK;
32static int cur_vol_r = AK4376_MIN_VOLUME;
33static int cur_vol_l = AK4376_MIN_VOLUME;
34static int cur_recvol = 0;
35static int cur_filter_roll_off = 0;
30static int cur_fsel = HW_FREQ_48; 36static int cur_fsel = HW_FREQ_48;
31static int cur_power_mode = SOUND_HIGH_POWER; 37static int cur_power_mode = SOUND_HIGH_POWER;
32 38
@@ -60,29 +66,138 @@ void audiohw_postinit(void)
60 66
61void audiohw_close(void) 67void audiohw_close(void)
62{ 68{
63 ak4376_close(); 69 if(cur_audio_source == AUDIO_SRC_PLAYBACK)
70 ak4376_close();
71 else if(cur_audio_source == AUDIO_SRC_MIC)
72 x1000_icodec_close();
73}
74
75void audio_set_output_source(int source)
76{
77 /* this is a no-op */
78 (void)source;
79}
80
81void audio_input_mux(int source, unsigned flags)
82{
83 (void)flags;
84
85 if(source == cur_audio_source)
86 return;
87
88 /* close whatever codec is currently in use */
89 audiohw_close();
90 aic_enable_i2s_bit_clock(false);
91
92 /* switch to new source */
93 cur_audio_source = source;
94
95 if(source == AUDIO_SRC_PLAYBACK) {
96 /* power on DAC */
97 aic_set_external_codec(true);
98 aic_set_i2s_mode(AIC_I2S_MASTER_MODE);
99 ak4376_open();
100
101 /* apply the old settings */
102 audiohw_set_volume(cur_vol_l, cur_vol_r);
103 audiohw_set_filter_roll_off(cur_filter_roll_off);
104 set_ak_freqmode();
105 } else if(source == AUDIO_SRC_MIC) {
106 aic_set_external_codec(false);
107 aic_set_i2s_mode(AIC_I2S_SLAVE_MODE);
108 /* Note: Sampling frequency is irrelevant here */
109 aic_set_i2s_clock(X1000_CLK_EXCLK, 48000, 0);
110 aic_enable_i2s_bit_clock(true);
111
112 x1000_icodec_open();
113
114 /* configure the mic */
115 x1000_icodec_mic1_enable(true);
116 x1000_icodec_mic1_bias_enable(true);
117 x1000_icodec_mic1_configure(JZCODEC_MIC1_DIFFERENTIAL |
118 JZCODEC_MIC1_BIAS_2_08V);
119
120 /* configure the ADC */
121 x1000_icodec_adc_mic_sel(JZCODEC_MIC_SEL_ANALOG);
122 x1000_icodec_adc_highpass_filter(true);
123 x1000_icodec_adc_frequency(cur_fsel);
124 x1000_icodec_adc_enable(true);
125
126 /* configure the mixer to put mic input in both channels */
127 x1000_icodec_mixer_enable(true);
128 x1000_icodec_write(JZCODEC_MIX2, 0x10);
129
130 /* set gain and unmute */
131 audiohw_set_recvol(cur_recvol, 0, AUDIO_GAIN_MIC);
132 x1000_icodec_adc_mute(false);
133 } else {
134 logf("bad audio input source: %d (flags: %x)", source, flags);
135 }
64} 136}
65 137
66void audiohw_set_volume(int vol_l, int vol_r) 138void audiohw_set_volume(int vol_l, int vol_r)
67{ 139{
68 ak4376_set_volume(vol_l, vol_r); 140 cur_vol_l = vol_l;
141 cur_vol_r = vol_r;
142
143 if(cur_audio_source == AUDIO_SRC_PLAYBACK)
144 ak4376_set_volume(vol_l, vol_r);
69} 145}
70 146
71void audiohw_set_filter_roll_off(int val) 147void audiohw_set_filter_roll_off(int val)
72{ 148{
73 ak4376_set_filter_roll_off(val); 149 cur_filter_roll_off = val;
150
151 if(cur_audio_source == AUDIO_SRC_PLAYBACK)
152 ak4376_set_filter_roll_off(val);
74} 153}
75 154
76void audiohw_set_frequency(int fsel) 155void audiohw_set_frequency(int fsel)
77{ 156{
78 cur_fsel = fsel; 157 cur_fsel = fsel;
79 set_ak_freqmode(); 158
159 if(cur_audio_source == AUDIO_SRC_PLAYBACK)
160 set_ak_freqmode();
161 else
162 x1000_icodec_adc_frequency(fsel);
80} 163}
81 164
82void audiohw_set_power_mode(int mode) 165void audiohw_set_power_mode(int mode)
83{ 166{
84 cur_power_mode = mode; 167 cur_power_mode = mode;
85 set_ak_freqmode(); 168
169 if(cur_audio_source == AUDIO_SRC_PLAYBACK)
170 set_ak_freqmode();
171}
172
173static int round_step_up(int x, int step)
174{
175 int rem = x % step;
176 if(rem > 0)
177 rem -= step;
178 return x - rem;
179}
180
181void audiohw_set_recvol(int left, int right, int type)
182{
183 (void)right;
184
185 if(type == AUDIO_GAIN_MIC) {
186 cur_recvol = left;
187
188 if(cur_audio_source == AUDIO_SRC_MIC) {
189 int mic_gain = round_step_up(left, X1000_ICODEC_MIC_GAIN_STEP);
190 mic_gain = MIN(mic_gain, X1000_ICODEC_MIC_GAIN_MAX);
191 mic_gain = MAX(mic_gain, X1000_ICODEC_MIC_GAIN_MIN);
192
193 int adc_gain = left - mic_gain;
194 adc_gain = MIN(adc_gain, X1000_ICODEC_ADC_GAIN_MAX);
195 adc_gain = MAX(adc_gain, X1000_ICODEC_ADC_GAIN_MIN);
196
197 x1000_icodec_adc_gain(adc_gain);
198 x1000_icodec_mic1_gain(mic_gain);
199 }
200 }
86} 201}
87 202
88void ak4376_set_pdn_pin(int level) 203void ak4376_set_pdn_pin(int level)
diff --git a/manual/platform/keymap-fiiom3k.tex b/manual/platform/keymap-fiiom3k.tex
index ecf07bebd4..95c56f13ed 100644
--- a/manual/platform/keymap-fiiom3k.tex
+++ b/manual/platform/keymap-fiiom3k.tex
@@ -45,6 +45,18 @@
45\newcommand{\ActionWpsAbSetBNextDir}{Long \ButtonDown} 45\newcommand{\ActionWpsAbSetBNextDir}{Long \ButtonDown}
46\newcommand{\ActionWpsAbReset}{Long \ButtonSelect} 46\newcommand{\ActionWpsAbReset}{Long \ButtonSelect}
47 47
48%Button actions, recording context
49\newcommand{\ActionRecPause}{\ButtonSelect{} or \ButtonPlay}
50\newcommand{\ActionRecExit}{\ButtonBack{} or \ButtonPower}
51\newcommand{\ActionRecNewfile}{Long \ButtonSelect{} or Long \ButtonPlay}
52\newcommand{\ActionRecMenu}{\ButtonMenu}
53\newcommand{\ActionRecPrev}{\ActionStdPrev}
54\newcommand{\ActionRecPrevRepeat}{\ActionStdPrevRepeat}
55\newcommand{\ActionRecNext}{\ActionStdNext}
56\newcommand{\ActionRecNextRepeat}{\ActionStdNextRepeat}
57\newcommand{\ActionRecSettingsInc}{\ButtonVolUp{} or \ButtonRight}
58\newcommand{\ActionRecSettingsDec}{\ButtonVolDown{} or \ButtonLeft}
59
48%Button actions, tree context 60%Button actions, tree context
49\newcommand{\ActionTreeWps}{Long \ButtonBack} 61\newcommand{\ActionTreeWps}{Long \ButtonBack}
50\newcommand{\ActionTreeStop}{Long \ButtonPlay} 62\newcommand{\ActionTreeStop}{Long \ButtonPlay}