vs1003 как миди синтезатор

Dmti
Dmti аватар
Offline
Зарегистрирован: 13.10.2013

Достался модуль нахаляву (больше года работал оповещателем на заводе) на микросхеме vs1003. Файлы mp3 поигрался, послушал, но теперь хочу, чтоб он, как миди синтезатор заиграл (благо миди-клава валяется давно). Для пробы написал такой скеч

#include <SPI.h>
#include <arduino.h>
#include <MusicPlayer.h>

/*
 * GND  - GND
 * XDCS - D6
 * DREQ - D7
 * XRES - D8
 * XCS  - D9
 * SCLK - D13
 * SI   - D11
 * SO   - D12
 * GND  - GND
 * 5V   - 5V
 */


void setup () {
  
// initiate SPI
    SPI.begin();
    
// initiate a serial port at 9600
   	Serial.begin(9600);
    
// initiate VS1003 for MIDI
    player.beginInMidiFmt();  //Инициализировать аппаратное обеспечение и установить режим MIDI по умолчанию.
    player.midiWriteData(0xB0, 0x07, 120); //установить громкость 
    player.midiDemoPlayer ();
}

void loop() {
 // играть ноты от F#-(30) до F#-(90):
  for (int note = 30; note < 90; note ++) {
    player.midiNoteOn(1,note,127);
    delay(50);
    player.midiNoteOff(1,note,127);
    delay(50);
  }
}

 Но эта сволочь молчит, как партизан, ни звука. Может кто сталкивался и смог победить?
andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Насчет vs1003 не знаю, могу сказать только насчет vs1053. Насколько они совместимы - не интересовался.

1. Проигрывание MIDI-файлов и реалтаймовое MIDI - это не одно и то же. На просторах И-нета можно найти программку - в уже откомпилированном виде занимает байт 20-30, как раз она переводит чип в режим реалтаймового MIDI. Для чего ее сперва нужно загружить в DSP.

2. Процессор 1053 - 16-разрядный. Соответственно, на вход ему надо подавать не однобайтные, а двухбайтные коды. (насколько это критично - не знаю, вероятно player.midiNote* так и делает, но хорошо бы проверить.)

3. В названии библиотеки не фигурирует "VS1003", есть ли уверенность, что библиотека именно для этого чипа?

Dmti
Dmti аватар
Offline
Зарегистрирован: 13.10.2013

Насколько я понял из даташитов этих процессоров 53, отличается от 03 расширенной и улучшенной библиотекой инструментов. На сайе http://www.vlsi.fi/en/products/vs1003.html для обоих кристаллов ссылаются на одни и те же примеры. А при инициализации командой player.beginInMidiFmt(); библиотека vs10xx.h подгружает в проц вот это: 

//software patch for MIDI Play
const unsigned short gVS1053_MIDI_Patch[28]={
/*if you don't let GPIO1 = H,please send this patch by spi*/
0x0007, 0x0001, 0x8050, 0x0006, 0x0014, 0x0030, 0x0715, 0xb080, /* 0 */
0x3400, 0x0007, 0x9255, 0x3d00, 0x0024, 0x0030, 0x0295, 0x6890, /* 8 */
0x3400, 0x0030, 0x0495, 0x3d00, 0x0024, 0x2908, 0x4d40, 0x0030, /* 10 */
0x0200, 0x000a, 0x0001, 0x0050,
};

чисто для vs1003 такую я не нашел, потому и обратился сюда.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Да, я использую этот же код, только добавил в него "разгон" процессора примерно до 60 МГц. 

Правда, беглое знакомство с приведенной Вами ссылкой на этот код меня нее вывело.

Подробно разбираться с vs1003 у меня сейчас ни времени, ни желания нет. Единственное, чем могу поспособствовать, либо проверить тот код, что Вы загружаете в vs1003 в свой 1053, либо, наоборот, привести код, который работает у меня на 1053. Но это в лучшем случае сегодня вечером.

И, кстати, в каком виде у Вас само устройство? Насколько я помню, ему нужно два разных напряжения питания.

У меня сейчас в доступности примерно такой: 

И с него нельзя снимать сигнал относительно общего провода - там специально есть контакт, предназначенный для использования в качестве общего с наушниками, но не соединенный с GND.

Dmti
Dmti аватар
Offline
Зарегистрирован: 13.10.2013

Если можно, то и мой проверить, и свой привести. Чтобы определится: ошибка в коде или модулее.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Ваш код проверить не могу ввиду отсутствия у меня библиотеки "MusicPlayer", публикую тот, что у меня работает (сразу прошу прощения, в коде много лишнего - чистить не стал)

MP3_Shield_VS1053b.ino

/*
 * The code is based on Nathan Seidle's Sparkfun Electronics example code for the Sparkfun 
 * MP3 Player and Music Instrument shields and and VS1053 breakout board. 
 *
 * http://www.sparkfun.com/Code/MIDI_Example.pde
 * http://dlnmh9ip6v2uc.cloudfront.net/datasheets/Dev/Arduino/Shields/VS_Sh...
 *
 *
 * THEORY OF OPERATIONS
 *
 * The VS1053b has two ways of playing MIDI: One method is that you simply send a Standard MIDI level 0 file through
 * SPI, and the chip will play it. This works exactly the same way as MP3 mode and will not be discussed further here.
 * The other method is that the VS1053b has a "Real Time MIDI mode", in which it will instantly execute MIDI commands 
 * sent to it through either the UART or SPI. 
 *
 * Real Time MIDI mode can be enabled with two different methods, controlled by USE_GPIO_INIT 
 *  (1) Setting GPIO1 to HIGH (which is hardwired in the Sparkfun Music Instrument shield, and can be done through 
 *      pin 4 in the MP3 Player Shield)
 *  (0) Sending a small software patch through SPI.
 *
 * MIDI data can be sent with two different methods as well, controlled by USE_SPI_MIDI
 *  (0) Through a (software) serial connection on pin 3, at 31250 baud
 *  (1) Through SPI, at an arbitrary data rate. For SPI, each byte of MIDI data needs to be prefixed by a 0 byte 
 *      (The V1053b data sheet erroneously states that the padding should be a 0xFF byte).
 *
 * Both initialization methods and both transmission methods can be selected through the #defines below. Out of the box, 
 * it probably makes most sense to enable real time MIDI through pin 4, and send serial data through pin 3, but if you 
 * want to cut the traces for pin 3 and 4 and use those pins for another purpose, the alternative methods may come in 
 * handy. 
 * 
 * MIDI Shield connections:
 * Arduino UNO:  2 - VS1053B:  8 - DREQ - data request ready
 * Arduino UNO:  6 - VS1053B: 23 - xCS  - select code register
 * Arduino UNO:  7 - VS1053B: 13 - xDSC - select data register
 * Arduino UNO:  8 - VS1053B:  3 - Reset
 * Arduino UNO:  9 - VS1053B:    - perhabs SD CS - SPI SD card
 * Arduino UNO: 11 - VS1053B: 29 - MOSI - SPI
 * Arduino UNO: 12 - VS1053B: 30 - MISO - SPI
 * Arduino UNO: 13 - VS1053B: 28 - SCK  - SPI
 * 
 * in other VS1053B Shield GPIO1 is connected to pin 4 Arduino and Serial In is connected to pin 3
 * becouse in this Shield pins 3 and 4 are not connected, we choise variant with plugin and SPI
 */ 

#include <SPI.h>
#include "VS1053B_MIDI.h"

void setup() {
  Serial.begin(115200); //Use serial for debugging 
  Serial.println(F("\n******\n"));
  Serial.println(F("MP3 Shield Example"));

  VS1053B_setup();
   // играть ноты от F#-(30) до F#-(90):
  for (byte note = 30; note < 90; note ++) {
    noteOn(1,note,127);
    delay(50);
    noteOff(1,note,127);
    delay(50);
  }
}

void loop() {
}

VS1053B_MIDI.h

#ifndef VS1053B_MIDI_H
#define VS1053B_MIDI_H 

#include "Arduino.h" 

#define VS_START_SPEED 1000000 // предел по дэйташиту CLKI/7 (=1.76 при 12.288 МГц)
#define VS_SPEED       4000000 // предел по дэйташиту CLKI/7 (=7.9 при 55.3 МГц)

#define VS_XCS     6 //53  //  3 //  6 // Control Chip Select Pin (for accessing SPI Control/Status registers)
#define VS_XDCS    7 //48  //  7 //  7 // Data Chip Select / BSYNC Pin
#define VS_DREQ    2 //49  //  2 //  2 // Data Request Pin: Player asks for more data
#define VS_RESET   8 //47  //  8 //  8 // Reset is active low
//#define VS_SPI_CS   53 // 10 // default SPI - this pin must be set as an output for the SPI communication to work

   //Write to VS10xx register
   //SCI: Data transfers are always 16bit. When a new SCI operation comes in DREQ goes low. We then have to wait for DREQ to go high again.
   //XCS should be low for the full duration of operation.
void VSWriteRegister(unsigned char addressbyte, unsigned char highbyte, unsigned char lowbyte);

   // Plugin to put VS10XX into realtime MIDI mode
   // Originally from http://www.vlsi.fi/fileadmin/software/VS10XX/vs1053b-rtmidistart.zip
   // Permission to reproduce here granted by VLSI solution.
void VSLoadUserCode(void);

   //Sends a MIDI command/data. Doesn't check to see that cmd is greater than 127, or that data values are less than 127
void talkMIDI(byte cmd, byte data1, byte data2);

void VS1053B_setup();

   //Send a MIDI note-on message.  Like pressing a piano key
   //channel ranges from 0-15
void noteOn(byte channel, byte note, byte attack_velocity);

   //Send a MIDI note-off message.  Like releasing a piano key
void noteOff(byte channel, byte note, byte release_velocity);

void sendMIDI(byte data);

int adc_single_channel_read(byte readAddress);

#endif // VS1053B_MIDI_H

VS1053B_MIDI.cpp

#include "VS1053B_MIDI.h"
#include <SPI.h>
//#include "arh_2560.h"

SPISettings VS1053B_START(VS_START_SPEED, MSBFIRST, SPI_MODE0);
//SPISettings VS1053B_HiFreq(VS_START_SPEED, MSBFIRST, SPI_MODE0);
SPISettings VS1053B_HiFreq(VS_SPEED, MSBFIRST, SPI_MODE0);

byte pinRead(byte pin) {return digitalRead(pin);}
void pinOutHigh(byte pin) {digitalWrite(pin, HIGH);}
void pinOutLow(byte pin) {digitalWrite(pin, LOW);}
void pinModeOut(byte pin) {pinMode(pin, OUTPUT);}
void pinModeIn(byte pin) {pinMode(pin, INPUT);}

   //Write to VS10xx register
   //SCI: Data transfers are always 16bit. When a new SCI operation comes in DREQ goes low. We then have to wait for DREQ to go high again.
   //XCS should be low for the full duration of operation.
void VSWriteRegister(unsigned char addressbyte, unsigned char highbyte, unsigned char lowbyte){
  while(!pinRead(VS_DREQ)) ; //Wait for DREQ to go high indicating IC is available
  SPI.beginTransaction (VS1053B_START);
  pinOutLow(VS_XCS); //Select control

  //SCI consists of instruction byte, address byte, and 16-bit data word.
  SPI.transfer(0x02); //Write instruction
  SPI.transfer(addressbyte);
  SPI.transfer(highbyte);
  SPI.transfer(lowbyte);
  while(!pinRead(VS_DREQ)) ; //Wait for DREQ to go high indicating command is complete
  pinOutHigh(VS_XCS); //Deselect Control
  SPI.endTransaction   ();
}

   // Plugin to put VS10XX into realtime MIDI mode
   // Originally from http://www.vlsi.fi/fileadmin/software/VS10XX/vs1053b-rtmidistart.zip
   // Permission to reproduce here granted by VLSI solution.
const PROGMEM unsigned short sVS1053b_Realtime_MIDI_Plugin[] = { /* [28] Compressed plugin */
  0x0007, 0x0001, 0x8050, 0x0006, 0x0014, 0x0030, 0x0715, 0xb080, /*    0 */
  0x3400, 0x0007, 0x9255, 0x3d00, 0x0024, 0x0030, 0x0295, 0x6890, /*    8 */
  0x3400, 0x0030, 0x0495, 0x3d00, 0x0024, 0x2908, 0x4d40, 0x0030, /*   10 */
  0x0200, 0x000a, 0x0001, 0x0050, 0x0003, 0x0001, 0xd800      // добавлена команда увел.частоты: d800->r3 (x4.5+1.5)
};              // 0x9800: x3.5+1.5,   0xa00: x4.0+0.0,   0xb800: x4.0+1.5,   0xc00: x4.5+0.0,   0xe00: x5.0+0.0

void VSLoadUserCode(void) {
  int i = 0;

  while (i<sizeof(sVS1053b_Realtime_MIDI_Plugin)/sizeof(sVS1053b_Realtime_MIDI_Plugin[0])) {
    unsigned short addr, n, val; // pgm_read_word_near(&glideStepArray[glide])
    addr = pgm_read_word_near(&sVS1053b_Realtime_MIDI_Plugin[i++]);
    n = pgm_read_word_near(&sVS1053b_Realtime_MIDI_Plugin[i++]);
    while (n--) {
      val = pgm_read_word_near(&sVS1053b_Realtime_MIDI_Plugin[i++]);
      VSWriteRegister(addr, val >> 8, val & 0xFF);
    }
  }
}

   //Sends a MIDI command/data. Doesn't check to see that cmd is greater than 127, or that data values are less than 127
void talkMIDI(byte cmd, byte data1, byte data2) {

  while (!pinRead(VS_DREQ));  // Wait for chip to be ready (Unlikely to be an issue with real time MIDI)
  SPI.beginTransaction (VS1053B_HiFreq);
  pinOutLow(VS_XDCS);
  SPI.transfer(0);
  SPI.transfer(cmd);
//  sendMIDI(cmd);
  //Some commands only have one data byte. All cmds less than 0xBn have 2 data bytes 
  //(sort of: http://253.ccarh.org/handout/midiprotocol/)
  if( (cmd & 0xF0) <= 0xB0 || (cmd & 0xF0) >= 0xE0) {
    SPI.transfer(0);
    SPI.transfer(data1);
    SPI.transfer(0);
    SPI.transfer(data2);
  } else {
    SPI.transfer(0);
    SPI.transfer(data1);
  }
  pinOutHigh(VS_XDCS);
  SPI.endTransaction ();
}

void VS1053B_setup() {
  pinOutHigh(VS_XCS); //Deselect Control
  pinModeOut(VS_XCS);

  pinOutHigh(VS_XDCS); //Deselect Data
  pinModeOut(VS_XDCS);

  pinOutLow(VS_RESET); //Put VS1053 into hardware reset
  pinModeOut(VS_RESET);

  pinModeIn(VS_DREQ);

  //Setup SPI for VS1053
//  pinMode(VS_SPI_CS, OUTPUT); //Pin 10 must be set as an output for the SPI communication to work
  SPI.begin();
////  SPI.setBitOrder(MSBFIRST);
////  SPI.setDataMode(SPI_MODE0);

  //From page 12 of datasheet, max SCI reads are CLKI/7. Input clock is 12.288MHz. 
  //Internal clock multiplier is 1.0x after power up. 
  //Therefore, max SPI speed is 1.75MHz. We will use 1MHz to be safe.
////  SPI.setClockDivider(SPI_CLOCK_DIV16); //Set SPI bus speed to 1MHz (16MHz / 16 = 1MHz)

//  SPI.setClockDivider(SPI_CLOCK_DIV64); //Set SPI bus speed to 500kHz (16MHz / 32 = 500kHz)
  
  SPI.transfer(0xFF); //Throw a dummy byte at the bus

  delayMicroseconds(1);
  pinOutHigh(VS_RESET); //Bring up VS1053
  
  VSLoadUserCode(); // if USE_PATCH_INIT
//  VSWriteRegister(3, 0xb8, 0x00); // register, lobyte, hibyte: 98: x3.5+1.5, b8: x4+1.5, a0: x4+0
  delay(1000); // (4)

//  VS1053B.SPISettings(VS_SPEED, MSBFIRST, SPI_MODE0);

  talkMIDI(0xB0, 0x79, 127); // Reset All Controllers
  talkMIDI(0xB0, 0x7B, 0); // All Notes Off
  talkMIDI(0xB0, 0x5B, 0x41); // External effects depth
  talkMIDI(0xB0, 0x5D, 0); // Chorus depth
  talkMIDI(0xB0, 0x40, 0); // Sustain pedal
  talkMIDI(0xB0, 0x00, 0); // Bank select
  talkMIDI(0xB0, 0x01, 0); // Modulation Wheel
  talkMIDI(0xB0, 0x0A, 0x37); // Pan
//  talkMIDI(0xC0, 0x38, 0); // Program number
  talkMIDI(0xE0, 0x00, 0x40); // Pitch Wheel
//  talkMIDI(0xB4, 0x40, 0); // 
//  Status  Index Argument  Description
//==========================================================
// Bn 78 00            All Sounds Off
// Bn 79 7F            Reset All Controllers
// Bn 7A 7F on/00 off  Local Control On/Off
// Bn 7B 00            All Notes Off
// Bn 7C 00            Omni Mode Off (All Notes Off)
// Bn 7D 00            Omni Mode On (All Notes Off)
// Bn 7E channels      Mono Mode On (Poly Mode Off)
// Bn 7F 00            Poly Mode On (Mono Mode Off)

// Controller # Function       Controller # Function
// 46 Sound variation          5B External effects depth
// 47 Timbre/harmonic content  5C Tremolo depth
// 48 Release time             5D Chorus depth
// 49 Attack time              5E Detune depth
// 4A Brightness               5F Phase depth
// 4B-4F No default
  
  talkMIDI(0xB0, 0x07, 0x7F); //  Main Volume
  talkMIDI(0xB0, 0, 0x00); //Default bank GM1
//  talkMIDI(0xB0, 0, 0x78); //Bank select drums
}

//Send a MIDI note-on message.  Like pressing a piano key
//channel ranges from 0-15
void noteOn(byte channel, byte note, byte attack_velocity) {
  talkMIDI( (0x90 | channel), note, attack_velocity);
}

//Send a MIDI note-off message.  Like releasing a piano key
void noteOff(byte channel, byte note, byte release_velocity) {
  talkMIDI( (0x80 | channel), note, release_velocity);
}

void sendMIDI(byte data)
{
  while (!pinRead(VS_DREQ));  // Wait for chip to be ready (Unlikely to be an issue with real time MIDI)
  SPI.beginTransaction (VS1053B_HiFreq);
  pinOutLow(VS_XDCS);
  SPI.transfer(0);
  SPI.transfer(data);
  pinOutHigh(VS_XDCS);
  SPI.endTransaction ();
} 

 

Dmti
Dmti аватар
Offline
Зарегистрирован: 13.10.2013

Библиотека для vs10xx, которую использую я:https://github.com/Seeed-Studio/Music_Shield . Вашу смогу попробовать только в воскресенье. Спасибо.

Глянул вашу библиотеку: 3 и 4 не подключены, подходит только вариант с плагином  SPI. Или подпояться к ножкам 33 и 34.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Я уже не помню, какие ножки за что отвечают, но если про последовательный порт, то он не разведен на самом шилде (также и на модуле, который показан ниже). Т.е. вариант только один - через SPI.

Dmti
Dmti аватар
Offline
Зарегистрирован: 13.10.2013

Начинаю думать что мой модуль вообще не способен воспроизводить MIDI. Перепробовал кучу вариантов, ни один не произвел ни звука.

dim3740
dim3740 аватар
Offline
Зарегистрирован: 25.03.2015

Подскажите, пожалуйста, куда подключить выход МИДИ клавы? К ардуино же? Если клава не ЮСБ, то видимо через отпрон прямо на RX? Но к коде я вообще не вижу чтения Uart.... 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

А ви с какой целью интересуетесь?

dim3740
dim3740 аватар
Offline
Зарегистрирован: 25.03.2015

В смысле?)) Тоже хочу сделать такое как тс..

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Ну, тогда вопросы к ТС.