Skip to content

Commit d8abdac

Browse files
committed
fix: avoid compiling for different targets
1 parent db3007b commit d8abdac

File tree

2 files changed

+316
-5
lines changed

2 files changed

+316
-5
lines changed

rust-project.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"sysroot_src": "/Users/adrien/.rustup/toolchains/esp/lib",
3+
"crates": [
4+
{
5+
"root_module": "src/main.rs",
6+
"edition": "2021",
7+
"deps": [],
8+
"cfg": [],
9+
"env": {
10+
"RUSTFLAGS": "--target=xtensa-esp32s3-espidf"
11+
},
12+
"target": "xtensa-esp32s3-espidf"
13+
}
14+
]
15+
}

src/vs1053.rs

Lines changed: 301 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
use anyhow::Result;
2+
use core::cmp::max;
23
use embedded_hal::spi::{Operation, SpiDevice};
34
use esp_idf_hal::gpio::{InputPin, OutputPin, PinDriver};
45
use log::warn;
56
use std::{ffi::CStr, str, thread::sleep, time::Duration};
67

78
const VS1053_CHUNK_SIZE: u8 = 32;
9+
810
// SCI Register
911
const SCI_MODE: u8 = 0x0;
1012
const SCI_STATUS: u8 = 0x1;
@@ -19,6 +21,7 @@ const SCI_VOL: u8 = 0xB;
1921
const SCI_AICTRL0: u8 = 0xC;
2022
const SCI_AICTRL1: u8 = 0xD;
2123
const SCI_NUM_REGISTERS: u8 = 0xF;
24+
2225
// SCI_MODE bits
2326
const SM_SDINEW: u8 = 11; // Bitnumber in SCI_MODE always on
2427
const SM_RESET: u8 = 2; // Bitnumber in SCI_MODE soft reset
@@ -58,13 +61,17 @@ fn contains(str: *const u8, substr: &str) -> bool {
5861
false
5962
}
6063

64+
fn map(x: i64, in_min: i64, in_max: i64, out_min: i64, out_max: i64) -> i64 {
65+
(x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
66+
}
67+
6168
pub struct VS1053<SPI, XCS, XDCS, DREQ> {
6269
spi: SPI,
6370
low_spi: SPI,
6471
xcs_pin: XCS,
6572
xdcs_pin: XDCS,
6673
dreq_pin: DREQ,
67-
current_volume: i8,
74+
current_volume: u8,
6875
current_balance: i8,
6976
}
7077

@@ -274,13 +281,13 @@ where
274281
// // Will give warnings on serial output if DEBUG is active.
275282
// // A maximum of 20 errors will be reported.
276283

277-
let (mut r1, mut r2, mut cnt): (u16, u16, u16) = (0, 0, 0);
284+
let (mut r1, mut r2);
285+
let mut cnt = 0;
278286
let mut delta: usize = 300; // 3 for fast SPI
279-
287+
280288
if contains(header, "Fast") {
281289
delta = 3; // Fast SPI, more loops
282290
}
283-
284291
log::info!("header:{:?}", header);
285292

286293
for i in (0..0xFFFF).step_by(delta) {
@@ -296,10 +303,299 @@ where
296303
cnt += 1;
297304
sleep(Duration::from_millis(10));
298305
}
299-
// yield(); // Allow ESP firmware to do some bookkeeping
306+
// yield(); // Allow ESP firmware to do some bookkeeping
300307
}
301308
return cnt == 0; // Return the result
302309
}
310+
311+
fn set_volume(&mut self, vol: u8) -> Result<(), DSPError> {
312+
// Set volume. Both left and right.
313+
// Input value is 0..100. 100 is the loudest.
314+
let (mut value_l, mut value_r); // Values to send to SCI_VOL
315+
316+
self.current_volume = vol; // Save for later use
317+
value_l = vol;
318+
value_r = vol;
319+
320+
if self.current_balance < 0 {
321+
value_r = max(0, vol.saturating_add(self.current_balance as u8));
322+
} else if self.current_balance > 0 {
323+
value_l = max(0, vol.saturating_sub(self.current_balance as u8));
324+
}
325+
326+
value_l = map(value_l.into(), 0, 100, 0xFE, 0x00) as u8; // 0..100% to left channel
327+
value_r = map(value_r.into(), 0, 100, 0xFE, 0x00) as u8; // 0..100% to right channel
328+
329+
self.write_register(true, SCI_VOL, ((value_l as u16) << 8) | value_r as u16) // Volume left and right
330+
}
331+
332+
fn set_balance(&mut self, balance: i8) {
333+
if balance > 100 {
334+
self.current_balance = 100;
335+
} else if balance < -100 {
336+
self.current_balance = -100;
337+
} else {
338+
self.current_balance = balance;
339+
}
340+
}
341+
342+
// fn setTone(uint8_t *rtone) { // Set bass/treble (4 nibbles)
343+
// // Set tone characteristics. See documentation for the 4 nibbles.
344+
// uint16_t value = 0; // Value to send to SCI_BASS
345+
// int i; // Loop control
346+
347+
// for (i = 0; i < 4; i++) {
348+
// value = (value << 4) | rtone[i]; // Shift next nibble in
349+
// }
350+
// writeRegister(SCI_BASS, value); // Volume left and right
351+
// }
352+
353+
fn get_volume(&mut self) -> u8 { // Get the current volume setting.
354+
return self.current_volume;
355+
}
356+
357+
fn get_balance(&mut self) -> i8 { // Get the current balance setting.
358+
return self.current_balance;
359+
}
360+
361+
// fn startSong() {
362+
// sdi_send_fillers(10);
363+
// }
364+
365+
// fn playChunk(uint8_t *data, size_t len) {
366+
// sdi_send_buffer(data, len);
367+
// }
368+
369+
// fn stopSong() {
370+
// uint16_t modereg; // Read from mode register
371+
// int i; // Loop control
372+
373+
// sdi_send_fillers(2052);
374+
// delay(10);
375+
// writeRegister(SCI_MODE, _BV(SM_SDINEW) | _BV(SM_CANCEL));
376+
// for (i = 0; i < 200; i++) {
377+
// sdi_send_fillers(32);
378+
// modereg = read_register(SCI_MODE); // Read status
379+
// if ((modereg & _BV(SM_CANCEL)) == 0) {
380+
// sdi_send_fillers(2052);
381+
// LOG("Song stopped correctly after %d msec\n", i * 10);
382+
// return;
383+
// }
384+
// delay(10);
385+
// }
386+
// printDetails("Song stopped incorrectly!");
387+
// }
388+
389+
// fn softReset() {
390+
// LOG("Performing soft-reset\n");
391+
// writeRegister(SCI_MODE, _BV(SM_SDINEW) | _BV(SM_RESET));
392+
// delay(10);
393+
// await_data_request();
394+
// }
395+
396+
// /**
397+
// * VLSI datasheet: "SM_STREAM activates VS1053b’s stream mode. In this mode, data should be sent with as
398+
// * even intervals as possible and preferable in blocks of less than 512 bytes, and VS1053b makes
399+
// * every attempt to keep its input buffer half full by changing its playback speed up to 5%. For best
400+
// * quality sound, the average speed error should be within 0.5%, the bitrate should not exceed
401+
// * 160 kbit/s and VBR should not be used. For details, see Application Notes for VS10XX. This
402+
// * mode only works with MP3 and WAV files."
403+
// */
404+
405+
// fn streamModeOn() {
406+
// LOG("Performing streamModeOn\n");
407+
// writeRegister(SCI_MODE, _BV(SM_SDINEW) | _BV(SM_STREAM));
408+
// delay(10);
409+
// await_data_request();
410+
// }
411+
412+
// fn streamModeOff() {
413+
// LOG("Performing streamModeOff\n");
414+
// writeRegister(SCI_MODE, _BV(SM_SDINEW));
415+
// delay(10);
416+
// await_data_request();
417+
// }
418+
419+
// fn printDetails(const char *header) {
420+
// uint16_t regbuf[16];
421+
// uint8_t i;
422+
// (void)regbuf;
423+
424+
// LOG("%s", header);
425+
// LOG("REG Contents\n");
426+
// LOG("--- -----\n");
427+
// for (i = 0; i <= SCI_num_registers; i++) {
428+
// regbuf[i] = read_register(i);
429+
// }
430+
// for (i = 0; i <= SCI_num_registers; i++) {
431+
// delay(5);
432+
// LOG("%3X - %5X\n", i, regbuf[i]);
433+
// }
434+
// }
435+
436+
// /**
437+
// * An optional switch.
438+
// * Most VS1053 modules will start up in MIDI mode. The result is that there is no audio when playing MP3.
439+
// * You can modify the board, but there is a more elegant way without soldering.
440+
// * No side effects for boards which do not need this switch. It means you can call it just in case.
441+
// *
442+
// * Read more here: http://www.bajdi.com/lcsoft-vs1053-mp3-module/#comment-33773
443+
// */
444+
// fn switchToMp3Mode() {
445+
// wram_write(ADDR_REG_GPIO_DDR_RW, 3); // GPIO DDR = 3
446+
// wram_write(ADDR_REG_GPIO_ODATA_RW, 0); // GPIO ODATA = 0
447+
// delay(100);
448+
// LOG("Switched to mp3 mode\n");
449+
// softReset();
450+
// }
451+
452+
// fn disableI2sOut() {
453+
// wram_write(ADDR_REG_I2S_CONFIG_RW, 0x0000);
454+
455+
// // configure GPIO0 4-7 (I2S) as input (default)
456+
// // leave other GPIOs unchanged
457+
// uint16_t cur_ddr = wram_read(ADDR_REG_GPIO_DDR_RW);
458+
// wram_write(ADDR_REG_GPIO_DDR_RW, cur_ddr & ~0x00f0);
459+
// }
460+
461+
// fn enableI2sOut(VS1053_I2S_RATE i2sRate) {
462+
// // configure GPIO0 4-7 (I2S) as output
463+
// // leave other GPIOs unchanged
464+
// uint16_t cur_ddr = wram_read(ADDR_REG_GPIO_DDR_RW);
465+
// wram_write(ADDR_REG_GPIO_DDR_RW, cur_ddr | 0x00f0);
466+
467+
// uint16_t i2s_config = 0x000c; // Enable MCLK(3); I2S(2)
468+
// switch (i2sRate) {
469+
// case VS1053_I2S_RATE_192_KHZ:
470+
// i2s_config |= 0x0002;
471+
// break;
472+
// case VS1053_I2S_RATE_96_KHZ:
473+
// i2s_config |= 0x0001;
474+
// break;
475+
// default:
476+
// case VS1053_I2S_RATE_48_KHZ:
477+
// // 0x0000
478+
// break;
479+
// }
480+
481+
// wram_write(ADDR_REG_I2S_CONFIG_RW, i2s_config );
482+
// }
483+
484+
// /**
485+
// * A lightweight method to check if VS1053 is correctly wired up (power supply and connection to SPI interface).
486+
// *
487+
// * @return true if the chip is wired up correctly
488+
// */
489+
// bool VS1053::isChipConnected() {
490+
// uint16_t status = read_register(SCI_STATUS);
491+
492+
// return !(status == 0 || status == 0xFFFF);
493+
// }
494+
495+
// /**
496+
// * get the Version Number for the VLSI chip
497+
// * VLSI datasheet: 0 for VS1001, 1 for VS1011, 2 for VS1002, 3 for VS1003, 4 for VS1053 and VS8053,
498+
// * 5 for VS1033, 7 for VS1103, and 6 for VS1063.
499+
// */
500+
// uint16_t VS1053::getChipVersion() {
501+
// uint16_t status = read_register(SCI_STATUS);
502+
503+
// return ( (status & 0x00F0) >> 4);
504+
// }
505+
506+
// /**
507+
// * Provides current decoded time in full seconds (from SCI_DECODE_TIME register value)
508+
// *
509+
// * When decoding correct data, current decoded time is shown in SCI_DECODE_TIME
510+
// * register in full seconds. The user may change the value of this register.
511+
// * In that case the new value should be written twice to make absolutely certain
512+
// * that the change is not overwritten by the firmware. A write to SCI_DECODE_TIME
513+
// * also resets the byteRate calculation.
514+
// *
515+
// * SCI_DECODE_TIME is reset at every hardware and software reset. It is no longer
516+
// * cleared when decoding of a file ends to allow the decode time to proceed
517+
// * automatically with looped files and with seamless playback of multiple files.
518+
// * With fast playback (see the playSpeed extra parameter) the decode time also
519+
// * counts faster. Some codecs (WMA and Ogg Vorbis) can also indicate the absolute
520+
// * play position, see the positionMsec extra parameter in section 10.11.
521+
// *
522+
// * @see VS1053b Datasheet (1.31) / 9.6.5 SCI_DECODE_TIME (RW)
523+
// *
524+
// * @return current decoded time in full seconds
525+
// */
526+
// uint16_t VS1053::getDecodedTime() {
527+
// return read_register(SCI_DECODE_TIME);
528+
// }
529+
530+
// /**
531+
// * Clears decoded time (sets SCI_DECODE_TIME register to 0x00)
532+
// *
533+
// * The user may change the value of this register. In that case the new value
534+
// * should be written twice to make absolutely certain that the change is not
535+
// * overwritten by the firmware. A write to SCI_DECODE_TIME also resets the
536+
// * byteRate calculation.
537+
// */
538+
// fn clearDecodedTime() {
539+
// writeRegister(SCI_DECODE_TIME, 0x00);
540+
// writeRegister(SCI_DECODE_TIME, 0x00);
541+
// }
542+
543+
// /**
544+
// * Fine tune the data rate
545+
// */
546+
// fn adjustRate(long ppm2) {
547+
// writeRegister(SCI_WRAMADDR, 0x1e07);
548+
// writeRegister(SCI_WRAM, ppm2);
549+
// writeRegister(SCI_WRAM, ppm2 >> 16);
550+
// // oldClock4KHz = 0 forces adjustment calculation when rate checked.
551+
// writeRegister(SCI_WRAMADDR, 0x5b1c);
552+
// writeRegister(SCI_WRAM, 0);
553+
// // Write to AUDATA or CLOCKF checks rate and recalculates adjustment.
554+
// writeRegister(SCI_AUDATA, read_register(SCI_AUDATA));
555+
// }
556+
557+
// /**
558+
// * Load a patch or plugin
559+
// *
560+
// * Patches can be found on the VLSI Website http://www.vlsi.fi/en/support/software/vs10xxpatches.html
561+
// *
562+
// * Please note that loadUserCode only works for compressed plugins (file ending .plg).
563+
// * To include them, rename them to file ending .h
564+
// * Please also note that, in order to avoid multiple definitions, if you are using more than one patch,
565+
// * it is necessary to rename the name of the array plugin[] and the name of PLUGIN_SIZE to names of your choice.
566+
// * example: after renaming plugin[] to plugin_myname[] and PLUGIN_SIZE to PLUGIN_MYNAME_SIZE
567+
// * the method is called by player.loadUserCode(plugin_myname, PLUGIN_MYNAME_SIZE)
568+
// * It is also possible to just rename the array plugin[] to a name of your choice
569+
// * example: after renaming plugin[] to plugin_myname[]
570+
// * the method is called by player.loadUserCode(plugin_myname, sizeof(plugin_myname)/sizeof(plugin_myname[0]))
571+
// */
572+
// fn loadUserCode(const unsigned short* plugin, unsigned short plugin_size) {
573+
// int i = 0;
574+
// while (i<plugin_size) {
575+
// unsigned short addr, n, val;
576+
// addr = plugin[i++];
577+
// n = plugin[i++];
578+
// if (n & 0x8000U) { /* RLE run, replicate n samples */
579+
// n &= 0x7FFF;
580+
// val = plugin[i++];
581+
// while (n--) {
582+
// writeRegister(addr, val);
583+
// }
584+
// } else { /* Copy run, copy n samples */
585+
// while (n--) {
586+
// val = plugin[i++];
587+
// writeRegister(addr, val);
588+
// }
589+
// }
590+
// }
591+
// }
592+
593+
// /**
594+
// * Load the latest generic firmware patch
595+
// */
596+
// fn loadDefaultVs1053Patches() {
597+
// loadUserCode(PATCHES,PATCHES_SIZE);
598+
// };
303599
}
304600

305601
#[derive(Copy, Clone, Debug)]

0 commit comments

Comments
 (0)