47 selected_mono_dac =
dac;
52 min_write_bytes =
bytes;
60 activeDACs = stereoOutput ? 3 : selected_mono_dac;
70 size_t write(
const uint8_t *data,
size_t len) {
76 int frames = len / frameSize;
82 while (!writeFrame(
stereo)) {
90 int availableForWrite() {
91 int result = totalSampleWords-lastFilledWord;
92 return result < min_write_bytes ? 0 : result;
97 const ulp_insn_t stopulp[] = {
102 size_t load_addr = 0;
103 size_t size =
sizeof(stopulp) /
sizeof(ulp_insn_t);
104 ulp_process_macros_and_load(load_addr, stopulp, &size);
109 if (activeDACs & 1) {
110 dac_output_voltage(DAC_CHANNEL_1, 128);
112 if (activeDACs & 2) {
113 dac_output_voltage(DAC_CHANNEL_2, 128);
119 int lastFilledWord = 0;
121 int min_write_bytes = 128;
122 UlpDac selected_mono_dac = ULP_DAC1;
123 uint8_t bufferedOddSample = 128;
124 bool waitingOddSample =
true;
126 bool stereoOutput =
true;
127 const int opcodeCount = 20;
128 const uint32_t dacTableStart1 = 2048 - 512;
129 const uint32_t dacTableStart2 = dacTableStart1 - 512;
130 uint32_t totalSampleWords =
131 2048 - 512 - 512 - (opcodeCount + 1);
132 const int totalSamples = totalSampleWords * 2;
133 const uint32_t indexAddress = opcodeCount;
134 const uint32_t bufferStart = indexAddress + 1;
139 waitingOddSample =
false;
145 unsigned long rtc_8md256_period = rtc_clk_cal(RTC_CAL_8MD256, 1000);
146 unsigned long rtc_fast_freq_hz =
147 1000000ULL * (1 << RTC_CLK_CAL_FRACT) * 256 / rtc_8md256_period;
150 if (activeDACs & 1) {
151 dac_output_enable(DAC_CHANNEL_1);
152 dac_output_voltage(DAC_CHANNEL_1, 128);
154 if (activeDACs & 2) {
155 dac_output_enable(DAC_CHANNEL_2);
156 dac_output_voltage(DAC_CHANNEL_2, 128);
160 int retAddress2 = 14;
162 int loopCycles = 134;
163 int loopHalfCycles1 = 90;
164 int loopHalfCycles2 = 44;
166 LOGI(
"Real RTC clock: %d", rtc_fast_freq_hz);
168 uint32_t dt = (rtc_fast_freq_hz / hertz) - loopCycles;
171 dt = (rtc_fast_freq_hz / hertz) - loopHalfCycles1;
172 dt2 = (rtc_fast_freq_hz / hertz) - loopHalfCycles2;
176 LOGI(
"dt2: %d", dt2);
178 const ulp_insn_t stereo[] = {
186 I_ST(R0, R3, indexAddress),
188 I_LD(R1, R0, bufferStart),
190 I_ANDI(R2, R1, 0x00ff),
194 I_ADDI(R2, R2, dacTableStart1),
201 I_ANDI(R2, R1, 0xff00),
203 I_RSHI(R2, R2, 8 - 1),
205 I_ADDI(R2, R2, dacTableStart2),
212 I_ST(R1, R0, indexAddress),
216 I_BGE(-16, totalSampleWords),
219 I_DELAY((
unsigned int)dt + 2),
225 size_t load_addr = 0;
226 size_t size =
sizeof(stereo) /
sizeof(ulp_insn_t);
227 ulp_process_macros_and_load(load_addr, stereo, &size);
233 switch (activeDACs) {
235 for (
int i = 0; i < 256; i++) {
236 RTC_SLOW_MEM[dacTableStart1 + i * 2] = create_I_WR_REG(
237 RTC_IO_PAD_DAC1_REG, 19, 26, i);
238 RTC_SLOW_MEM[dacTableStart1 + 1 + i * 2] =
239 create_I_BXI(retAddress1);
240 RTC_SLOW_MEM[dacTableStart2 + i * 2] = create_I_WR_REG(
241 RTC_IO_PAD_DAC1_REG, 19, 26, i);
242 RTC_SLOW_MEM[dacTableStart2 + 1 + i * 2] =
243 create_I_BXI(retAddress2);
247 for (
int i = 0; i < 256; i++) {
248 RTC_SLOW_MEM[dacTableStart1 + i * 2] = create_I_WR_REG(
249 RTC_IO_PAD_DAC2_REG, 19, 26, i);
250 RTC_SLOW_MEM[dacTableStart1 + 1 + i * 2] =
251 create_I_BXI(retAddress1);
252 RTC_SLOW_MEM[dacTableStart2 + i * 2] = create_I_WR_REG(
253 RTC_IO_PAD_DAC2_REG, 19, 26, i);
254 RTC_SLOW_MEM[dacTableStart2 + 1 + i * 2] =
255 create_I_BXI(retAddress2);
259 for (
int i = 0; i < 256; i++) {
260 RTC_SLOW_MEM[dacTableStart1 + i * 2] = create_I_WR_REG(
261 RTC_IO_PAD_DAC1_REG, 19, 26, i);
262 RTC_SLOW_MEM[dacTableStart1 + 1 + i * 2] =
263 create_I_BXI(retAddress1);
264 RTC_SLOW_MEM[dacTableStart2 + i * 2] = create_I_WR_REG(
265 RTC_IO_PAD_DAC1_REG, 19, 26, i);
266 RTC_SLOW_MEM[dacTableStart2 + 1 + i * 2] =
267 create_I_BXI(retAddress2);
273 for (
int i = 0; i < totalSampleWords; i++)
274 RTC_SLOW_MEM[bufferStart + i] = 0x8080;
277 RTC_SLOW_MEM[indexAddress] = 0;
282 while (RTC_SLOW_MEM[indexAddress] == 0)
288 bool writeFrame(int16_t sample[2]) {
296 int currentSample = RTC_SLOW_MEM[indexAddress] & 0xffff;
297 int currentWord = currentSample >> 1;
299 for (
int i = 0; i < 2; i++) {
300 ms[i] = ((ms[i] >> 8) + 128) & 0xff;
304 (uint16_t)(((uint32_t)((int32_t)(ms[0]) + (int32_t)(ms[1])) >> 1) &
307 if (waitingOddSample) {
309 if (lastFilledWord !=
318 w = bufferedOddSample;
320 bufferedOddSample = 128;
321 waitingOddSample =
false;
323 RTC_SLOW_MEM[bufferStart + lastFilledWord] = w;
325 if (lastFilledWord == totalSampleWords)
332 bufferedOddSample = ms[0];
333 waitingOddSample =
true;
338 uint32_t create_I_WR_REG(uint32_t reg, uint32_t low_bit, uint32_t high_bit,
344 const ulp_insn_t singleinstruction[] = {
345 I_WR_REG(reg, low_bit, high_bit, val)};
346 ulp_union recover_ins;
347 recover_ins.ulp_ins = singleinstruction[0];
348 return (uint32_t)(recover_ins.ulp_bin);
351 uint32_t create_I_BXI(uint32_t imm_pc) {
356 const ulp_insn_t singleinstruction[] = {I_BXI(imm_pc)};
357 ulp_union recover_ins;
358 recover_ins.ulp_ins = singleinstruction[0];
359 return (uint32_t)(recover_ins.ulp_bin);