Witam.
Natrafiłem wczoraj na problem z użyciem PWMa opartego o TIMER_A3 jako DAC. W czym rzecz?
Układzik, który aktualnie znajduje się na tapecie ma mieć możliwość wypowiadania krótkich sentencji głosowych za pomocą głośnika 50R podłączonego bez zbędnych elementów - najlepiej wprost na nogi procesora. Ponieważ już coś podobnego robiłem na AVRku wszystko szło sprawnie. Do czasu pierwszego uruchomienia dźwięku...
Okazało się bowiem, że DAC z PWMa co prawda odtwarza dźwięk PCM z poprawną częstotliwością próbkowania to w treści dźwiękowej pojawiają się dziwne wysokoczęstotliwościowe zakłócenia. Nie jest to szum kwantyzacji tylko jakieś niezidentyfikowane szpilki. Zatem ponownie sprawdziłem próbkę dźwiękową w CoolEdit czy nie wkradły się tam jakieś przekłamania podczas konwersji do danych RAW. Nic takiego nie występuje. Postanowiłem więc na szybko zaimportować program do AVR i tam... tą samą metodą próbka odtwarzana jest poprawnie.
Przypuszczam zatem, iż winę za całe zamieszanie ponosi brak układu buforowania rejestrów porównania TACCRx, co powoduje iż zapis do tych rejestrów w czasie trwania cyklu licznika generuje tzw. glitch-e (fałszywe wypełnienia) w przebiegu z PWM.
Czy rzeczywiście liczniki z MSP nie posiadają możliwości sprzętowego buforowania lub synchronizacji zapisu nowej wartości zawsze na początku pojedynczego cyklu liczenia? Gdyż w dokumentacji nie ma słowa na temat tego, iż PWMy z liczników są glitch free (o czym poniekąd chwali się Atmel).
Próbowałem już skorzystać z flagi TAIFG i poczekać z zapisem do TACCRx aż zostanie ona ustawiona, lecz efekt jest wtedy jeszcze gorszy - zniekształcenia się nasilają. Zamiast gongu jest garnek
Czy ma ktoś jakieś pomysły jak wyeliminować tą przypadłość? Robienie oversamplingu jak to pokazano w nocie aplikacyjnej MSP jest tu bardziej skomplikowane gdyż różnica pomiędzy nośną a próbką jest o wiele większa niż 4 razy, co znacznie wydłuży przerwanie.
Kodzik wygląda tak (dane próbki podcięto):
ps1. Próbkowanie jest 2kHz. Wydawać by się mogło, że to za mało, ale dźwięk składa się głównie z przebiegu 500Hz-600Hz - taki gong. Zatem te 2 kilo wystarcza w zupełności.
ps2. Głośnik jest podpięty bezpośrednio do dwóch nóg procesora i sterowany jest przeciwsobnie.
Natrafiłem wczoraj na problem z użyciem PWMa opartego o TIMER_A3 jako DAC. W czym rzecz?
Układzik, który aktualnie znajduje się na tapecie ma mieć możliwość wypowiadania krótkich sentencji głosowych za pomocą głośnika 50R podłączonego bez zbędnych elementów - najlepiej wprost na nogi procesora. Ponieważ już coś podobnego robiłem na AVRku wszystko szło sprawnie. Do czasu pierwszego uruchomienia dźwięku...
Okazało się bowiem, że DAC z PWMa co prawda odtwarza dźwięk PCM z poprawną częstotliwością próbkowania to w treści dźwiękowej pojawiają się dziwne wysokoczęstotliwościowe zakłócenia. Nie jest to szum kwantyzacji tylko jakieś niezidentyfikowane szpilki. Zatem ponownie sprawdziłem próbkę dźwiękową w CoolEdit czy nie wkradły się tam jakieś przekłamania podczas konwersji do danych RAW. Nic takiego nie występuje. Postanowiłem więc na szybko zaimportować program do AVR i tam... tą samą metodą próbka odtwarzana jest poprawnie.
Przypuszczam zatem, iż winę za całe zamieszanie ponosi brak układu buforowania rejestrów porównania TACCRx, co powoduje iż zapis do tych rejestrów w czasie trwania cyklu licznika generuje tzw. glitch-e (fałszywe wypełnienia) w przebiegu z PWM.
Czy rzeczywiście liczniki z MSP nie posiadają możliwości sprzętowego buforowania lub synchronizacji zapisu nowej wartości zawsze na początku pojedynczego cyklu liczenia? Gdyż w dokumentacji nie ma słowa na temat tego, iż PWMy z liczników są glitch free (o czym poniekąd chwali się Atmel).
Próbowałem już skorzystać z flagi TAIFG i poczekać z zapisem do TACCRx aż zostanie ona ustawiona, lecz efekt jest wtedy jeszcze gorszy - zniekształcenia się nasilają. Zamiast gongu jest garnek

Czy ma ktoś jakieś pomysły jak wyeliminować tą przypadłość? Robienie oversamplingu jak to pokazano w nocie aplikacyjnej MSP jest tu bardziej skomplikowane gdyż różnica pomiędzy nośną a próbką jest o wiele większa niż 4 razy, co znacznie wydłuży przerwanie.
Kodzik wygląda tak (dane próbki podcięto):
Code:
#include "msp430x21x2.h"
#define TEST BIT1 // P2
#define BUZZ BIT3 // P2
#define BUZZH BIT4 // P2
#define DONGLEN 4530
const unsigned char dong[] = {
2, 2, 244, 252, 24, 3, 218, 0, 52, 251, (itd...)
};
unsigned int volatile buf_pointer = 0; // wskaźnik w buforze
unsigned int volatile play_sample = 0; // stan odgrywania
unsigned char one_byte; // próbka do obróbki
// ##################################################################
void do_config(void)
{
DCOCTL = CALDCO_8MHZ; // DCO 8MHz
BCSCTL1 = CALBC1_8MHZ;
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog
// P2 = mix
P2DIR |= BUZZ | BUZZH; // wejścia(0)-wyjścia(1)
P2OUT = BUZZ; // stany początkowe (buzzer off)
P2SEL = 0x18; // 0b00011000 // funkcja podstawowa, P2.3-P2.4 timer
// ustawienie pracy TIMER_A0 - generator dźwięku
TA0CCR0 = 0x00FF; // pełne wychylenie licznika
TA0CCR1 = 0x00FF; // rejestry porównania zero wypełnienia
TA0CCR2 = 0x0000;
TA0CCTL1 = CM_0 | CCIS_2 | OUTMOD_2; // ustaw PWM - wysoki->niski
TA0CCTL2 = CM_0 | CCIS_2 | OUTMOD_6; // niski->wysoki
TA0CTL = TASSEL_2 | ID_0 | MC_1; // szybki PWM 31kHz
// ustawienie pracy TIMER_A1 - generator czasu
TA1CCR0 = 1500;
TA1CTL = TASSEL_2 | ID_1 | MC_1 | TAIE; // próbkowanie ok. 2kHz
}
// ##################################################################
int main(void)
{
do_config(); // przeprowadź niezbędne konfiguracje peryferii
__enable_interrupt(); // przerwania włącz
while(1)
{
if ((P2IN & TEST) == TEST) // czy wejście aktywne?
play_sample = 1;
}
}
// #######################################################################
// ISR Timer1_A1 Interrupt Vector (TAIV)
#pragma vector=TIMER1_A1_VECTOR
__interrupt void Timer1_A1(void)
{
switch(TA1IV)
{
case 0x0A : // TA1OVF przepełnienie
if(play_sample == 1)
{
one_byte = dong[buf_pointer++]; // odczytaj jeden bajt z bufora
if(buf_pointer == DONGLEN)
{
buf_pointer = 0;
play_sample = 0;
TA0CCR1 = 0x00FF; // zeruj przebieg z DAC
TA0CCR2 = 0x0000;
}
one_byte = one_byte + 127; // korekcja danych
TA0CCR1 = one_byte; // i do DAC
TA0CCR2 = one_byte;
}
break;
}
}
ps1. Próbkowanie jest 2kHz. Wydawać by się mogło, że to za mało, ale dźwięk składa się głównie z przebiegu 500Hz-600Hz - taki gong. Zatem te 2 kilo wystarcza w zupełności.
ps2. Głośnik jest podpięty bezpośrednio do dwóch nóg procesora i sterowany jest przeciwsobnie.