diff options
-rw-r--r-- | apps/keymaps/keymap-fiiom3k.c | 42 | ||||
-rw-r--r-- | firmware/export/ak4376.h | 4 | ||||
-rw-r--r-- | firmware/export/config/fiiom3k.h | 8 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_x1000/fiiom3k/audiohw-fiiom3k.c | 127 | ||||
-rw-r--r-- | manual/platform/keymap-fiiom3k.tex | 12 |
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 | ||
141 | static 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 | |||
141 | static const struct button_mapping button_context_settings_eq[] = { | 151 | static 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 | ||
216 | static 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 | |||
206 | static const struct button_mapping button_context_keyboard[] = { | 243 | static 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 | ||
31 | static int cur_audio_source = AUDIO_SRC_PLAYBACK; | ||
32 | static int cur_vol_r = AK4376_MIN_VOLUME; | ||
33 | static int cur_vol_l = AK4376_MIN_VOLUME; | ||
34 | static int cur_recvol = 0; | ||
35 | static int cur_filter_roll_off = 0; | ||
30 | static int cur_fsel = HW_FREQ_48; | 36 | static int cur_fsel = HW_FREQ_48; |
31 | static int cur_power_mode = SOUND_HIGH_POWER; | 37 | static int cur_power_mode = SOUND_HIGH_POWER; |
32 | 38 | ||
@@ -60,29 +66,138 @@ void audiohw_postinit(void) | |||
60 | 66 | ||
61 | void audiohw_close(void) | 67 | void 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 | |||
75 | void audio_set_output_source(int source) | ||
76 | { | ||
77 | /* this is a no-op */ | ||
78 | (void)source; | ||
79 | } | ||
80 | |||
81 | void 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 | ||
66 | void audiohw_set_volume(int vol_l, int vol_r) | 138 | void 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 | ||
71 | void audiohw_set_filter_roll_off(int val) | 147 | void 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 | ||
76 | void audiohw_set_frequency(int fsel) | 155 | void 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 | ||
82 | void audiohw_set_power_mode(int mode) | 165 | void 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 | |||
173 | static 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 | |||
181 | void 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 | ||
88 | void ak4376_set_pdn_pin(int level) | 203 | void 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} |