Implementación
Implementación
La generación de sonido hace uso de una serie de definiciones y tipos que no están disponibles públicamente en la librería CWIID por lo que habrá que copiarlos al código fuente del programa que se escriba:
#define SEQ_LEN(seq) (sizeof(seq)/sizeof(struct write_seq))
#define RPT_SPEAKER_ENABLE 0x14
#define RPT_SPEAKER_DATA 0x18
#define RPT_SPEAKER_MUTE 0x19
#define SOUND_BUF_LEN 21enum write_seq_type {
WRITE_SEQ_RPT,
WRITE_SEQ_MEM
};struct write_seq {
enum write_seq_type type;
uint32_t report_offset;
const void *data;
uint16_t len;
uint8_t flags;
};
La inicialización del altavoz se realiza mediante el siguiente proceso:
- Habilitar el altavoz mediante envío de 0x04 al report 0x14.
- Silenciar el altavoz mediante envío de 0x04 al report 0x19.
- Escribir 0x01 en el registro 0xa20009.
- Escribir 0x08 en el registro 0xa20001.
- Escribir la configuración en los registros 0xa20001 a 0xa20008.
- Escribir 0x01 en el registro 0xa20008.
- Deshacer el 2º paso mediante envío de 0x00 al report 0x19.
Es posible que los pasos 3 y 4 deban omitirse para que el altavoz se inicialice correctamente.
Los 7 bytes de configuración son los siguientes: 00 FF RR RR VV 00 00.
- FF es el formato de codificación usado, 0x40 para PCM de 8 bits y 0x00 para ADPCM de 4 bits.
- RR RR indican la frecuencia de muestreo, su valor será 12000000/frecuencia_muestreo para PCM y 6000000/frecuencia_muestreo para ADPCM.
El primer byte contiene el menos significativo y el segundo el más significativo. - VV es el volumen. Su rango va de 0x00 a 0xFF para PCM de 8 bits y de 0x00 a 0x40 para ADPCM de 4 bits.
Una posible secuencia de inicialización sería:
struct write_seq speaker_enable_seq[] = {
{WRITE_SEQ_RPT, RPT_SPEAKER_ENABLE, (const void *)"\x04", 1, 0},
{WRITE_SEQ_RPT, RPT_SPEAKER_MUTE, (const void *)"\x04", 1, 0},
{WRITE_SEQ_MEM, 0xA20009, (const void *)"\x01", 1, CWIID_RW_REG},
{WRITE_SEQ_MEM, 0xA20001, (const void *)"\x08", 1, CWIID_RW_REG},
{WRITE_SEQ_MEM, 0xA20001, (const void *)"\x00\x00\x00\x0e\x10\x00\x00", 7, CWIID_RW_REG},
{WRITE_SEQ_MEM, 0xA20008, (const void *)"\x01", 1, CWIID_RW_REG},
{WRITE_SEQ_RPT, RPT_SPEAKER_MUTE, (const void *)"\x00", 1, 0}
};
Y se enviaría mediante:
if (exec_write_seq(wiimote, SEQ_LEN(speaker_enable_seq), speaker_enable_seq)) {printf("Error al habilitar el altavoz\n");}
Una vez inicializado el altavoz se deben enviar las muestras de sonido al ritmo adecuado mediante:
if (cwiid_send_rpt(wiimote, 0, RPT_SPEAKER_DATA, SOUND_BUF_LEN, buf)) {printf("Error\n");}
Siendo buf el paquete de datos a enviar. Debe ser un array de unsigned char con una longitud mínima de 21 elementos, el primero indicará el número de bits sin tenerse en cuenta a sí mismo, el resto contienen las muestras del sonido a reproducir.
Un ejemplo de paquete de datos:
unsigned char buf[SOUND_BUF_LEN] = { 0xA0, 0xCC, 0x33, 0xCC, 0x33, 0xCC, 0x33, 0xCC, 0x33, 0xCC, 0x33, 0xCC, 0x33, 0xCC, 0x33, 0xCC, 0x33, 0xCC, 0x33, 0xCC, 0x33};
Finalizado su uso, el altavoz debe deshabilitarse mediante la siguiente secuencia:
- Silenciar el altavoz mediante envío de 0x04 al report 0x19.
- Escribir 0x00 en el registro 0xa20009.
- Escribir 0x00 en el registro 0xa20001.
- Deshabilitar el altavoz mediante envío de 0x00 al report 0x14.
Esta secuencia se traduce en:
struct write_seq speaker_disable_seq[] = {
{WRITE_SEQ_RPT, RPT_SPEAKER_MUTE, (const void *)"\x04", 1, 0},
{WRITE_SEQ_MEM, 0xA20009, (const void *)"\x00", 1, CWIID_RW_REG},
{WRITE_SEQ_MEM, 0xA20001, (const void *)"\x00", 1, CWIID_RW_REG},
{WRITE_SEQ_RPT, RPT_SPEAKER_ENABLE, (const void *)"\x00", 1, 0}
};
Y se envía mediante:
if (exec_write_seq(wiimote, SEQ_LEN(speaker_disable_seq), speaker_disable_seq)) {printf("Error al deshabilitar el altavoz\n");}