/* ==========================================================================
* RatNET Audio Analyzer - Firmware DSP (dsPIC30F4013)
* Autor: Carlos Alvarez
* Rev. 3.1 (Integración Nativa CCS: DCI Constants + SPI SRAM + 18-bit Logic)
* ========================================================================== */
#include <30F4013.h>
#include <math.h>
#include <string.h>
// ==========================================
// 1. FUSES Y CONFIGURACIÓN DEL RELOJ
// ==========================================
#FUSES NOWDT, HS, NOPROTECT, NODEBUG, NOWRT, NOBROWNOUT
#FUSES XT_PLL4
#use delay(clock=49152000)
// ==========================================
// 2. DEFINICIONES DE HARDWARE Y PINES
// ==========================================
#define LED_OK PIN_B5
#define LED_BUSY PIN_B6
#define LED_ERROR PIN_B7
#define BUZZER PIN_B8
#define SRAM_CS PIN_D1
// Comandos UART
#define CMD_SET_MODO_THD 0x10
#define CMD_SET_MODO_BAND 0x11
#define CMD_SET_MODO_ESPECTRO 0x12
#define CMD_SET_MODO_VU 0x13
#define CMD_POTENCIAS 0x30
#define CMD_Damping 0x40
#define CMD_TS_PARAMS 0x50
#define CMD_SLEW_RATE 0x60
#define CMD_GENERADOR 0x70
#define CMD_START 0x20
#define CMD_STOP 0x21
#define ACK 0x06
#define NACK 0x15
// ==========================================
// 3. COMUNICACIÓN (UART y SPI para SRAM)
// ==========================================
#use rs232(UART2, baud=9600, xmit=PIN_F4, rcv=PIN_F5, stream=UART_PIC18, ERRORS)
// ? INTEGRADO: SPI2 Hardware para la SRAM 23LC1024
#use spi(MASTER, CLK=PIN_F6, DI=PIN_F2, DO=PIN_F3, BAUD=10000000, stream=SPI_SRAM)
// ==========================================
// 4. CONSTANTES DCI (Basadas en tu hallazgo del 30F4013.c)
// ==========================================
// Si tu versión de CCS no tiene DCI_MODE_I2S definido, lo forzamos aquí:
#ifndef DCI_MODE_I2S
#define DCI_MODE_I2S 0x8000 // DCIEN=1 (Bit 15), DJIS=0 (Modo I2S estándar)
#endif
// ==========================================
// 5. ESTRUCTURAS DE DATOS Y VARIABLES GLOBALES
// ==========================================
typedef struct {
float thdPorcentaje;
float thdNPorcentaje;
float imdPorcentaje;
float sinadDB;
} MetricasDistorsion_t;
typedef struct {
float potenciaRmsW;
float potenciaPeakW;
float potenciaDinW;
} MetricasPotenciaAudio_t;
typedef struct {
float frecuenciaInicio;
float frecuenciaFin;
float gananciaMinDB;
float gananciaMaxDB;
float frecuenciaCorte3dB;
} MetricasSweep_t;
typedef struct {
float factorEscalaVoltaje;
float factorEscalaCorriente;
float offsetDC_ADC;
} Calibracion_t;
typedef struct {
float dampingFactor;
float impedanciaCarga;
float factorPotencia;
float potenciaAparente;
} MetricasDamping_t;
typedef struct {
float frecuenciaResonancia;
float impedanciaMax;
float qts;
float qms;
float qes;
} MetricasTS_t;
typedef struct {
float slewRateSubida;
float slewRateBajada;
float voltajePicoMax;
} MetricasSlewRate_t;
typedef struct {
unsigned int8 tipoOnda;
float frecuenciaHz;
float ganancia;
int1 activo;
} GeneradorConfig_t;
GeneradorConfig_t configGen = {0, 1000.0f, 0.8f, 0};
Calibracion_t calibActual;
unsigned int8 modoSeleccionado = 0x00;
int1 g_sistemaEjecutando = 0;
volatile int16 adcInterno_AN0_VIn = 0;
volatile int16 adcInterno_AN1_ACS = 0;
volatile int16 adcInterno_AN2_VccP = 0;
volatile int16 adcInterno_AN3_VccN = 0;
// ==========================================
// 6. PROTOTIPOS DE FUNCIONES
// ==========================================
void RetardoBuzzerMs(unsigned int16 ms);
void BuzzerUnBip(void);
void BuzzerTresBips(void);
void SRAM_Init(void);
void SRAM_WriteBlock(int32 direccion, int32 *datos, int16 cantidad);
void SRAM_ReadBlock(int32 direccion, int32 *datos, int16 cantidad);
void InicializarSistemaCalibracion(void);
int32 LeerADCExterno_DCI(void);
void EscribirDACExterno_DCI(int32 muestraL_18bit, int32 muestraR_18bit);
void LeerADCsInternos(void);
void EjecutarAnalisisDistorsion(void);
void EjecutarPotenciasAudio(void);
void EjecutarSweepBandwidth(void);
void EjecutarDampingFactor(void);
void EjecutarParametrosTS(void);
void EjecutarSlewRate(void);
void EjecutarGeneradorFunciones(void);
// ==========================================
// 7. FUNCIONES DE UI
// ==========================================
void RetardoBuzzerMs(unsigned int16 ms) {
for(unsigned int16 i = 0; i < ms; i++) { delay_ms(1); }
}
void BuzzerUnBip(void) {
output_high(BUZZER);
RetardoBuzzerMs(80);
output_low(BUZZER);
}
void BuzzerTresBips(void) {
for(int b = 0; b < 3; b++) {
output_high(BUZZER);
RetardoBuzzerMs(60);
output_low(BUZZER);
RetardoBuzzerMs(60);
}
}
// ==========================================
// 8. DRIVER SRAM EXTERNA 23LC1024
// ==========================================
#define CMD_WRITE 0x02
#define CMD_READ 0x03
#define CMD_WRMR 0x01
void SRAM_Init(void) {
output_high(SRAM_CS);
delay_ms(10);
output_low(SRAM_CS);
spi_xfer(SPI_SRAM, CMD_WRMR);
spi_xfer(SPI_SRAM, 0x40); // Modo 32-bit (Dword)
output_high(SRAM_CS);
}
void SRAM_WriteBlock(int32 direccion, int32 *datos, int16 cantidad) {
int16 i;
output_low(SRAM_CS);
spi_xfer(SPI_SRAM, CMD_WRITE);
spi_xfer(SPI_SRAM, (int8)(direccion >> 16));
spi_xfer(SPI_SRAM, (int8)(direccion >> 8));
spi_xfer(SPI_SRAM, (int8)(direccion));
for(i = 0; i < cantidad; i++) {
spi_xfer(SPI_SRAM, (int8)(datos[i] >> 24));
spi_xfer(SPI_SRAM, (int8)(datos[i] >> 16));
spi_xfer(SPI_SRAM, (int8)(datos[i] >> 8));
spi_xfer(SPI_SRAM, (int8)(datos[i]));
}
output_high(SRAM_CS);
}
void SRAM_ReadBlock(int32 direccion, int32 *datos, int16 cantidad) {
int16 i;
output_low(SRAM_CS);
spi_xfer(SPI_SRAM, CMD_READ);
spi_xfer(SPI_SRAM, (int8)(direccion >> 16));
spi_xfer(SPI_SRAM, (int8)(direccion >> 8));
spi_xfer(SPI_SRAM, (int8)(direccion));
for(i = 0; i < cantidad; i++) {
int32 temp = 0;
temp |= ((int32)spi_xfer(SPI_SRAM, 0)) << 24;
temp |= ((int32)spi_xfer(SPI_SRAM, 0)) << 16;
temp |= ((int32)spi_xfer(SPI_SRAM, 0)) << 8;
temp |= ((int32)spi_xfer(SPI_SRAM, 0));
datos[i] = temp;
}
output_high(SRAM_CS);
}
// ==========================================
// 9. RUTINAS DE AUDIO (MÓDULO DCI NATIVO)
// ==========================================
int32 LeerADCExterno_DCI(void) {
return dci_read();
}
void EscribirDACExterno_DCI(int32 muestraL_18bit, int32 muestraR_18bit) {
// ? Adaptación para 16-bit Word: Recortamos los 2 LSB para que encaje en el slot I2S de 16 bits
int16 muestraL_16bit = (int16)((muestraL_18bit >> 2) & 0xFFFF);
int16 muestraR_16bit = (int16)((muestraR_18bit >> 2) & 0xFFFF);
int32 frame_dci = ((int32)muestraL_16bit << 16) | (muestraR_16bit & 0xFFFF);
dci_write(frame_dci);
}
// ==========================================
// 10. ADCs INTERNOS
// ==========================================
void LeerADCsInternos(void) {
set_adc_channel(0); delay_us(10); adcInterno_AN0_VIn = read_adc();
set_adc_channel(1); delay_us(10); adcInterno_AN1_ACS = read_adc();
set_adc_channel(2); delay_us(10); adcInterno_AN2_VccP = read_adc();
set_adc_channel(3); delay_us(10); adcInterno_AN3_VccN = read_adc();
}
// ==========================================
// 11. INICIALIZACIÓN GENERAL
// ==========================================
void InicializarSistemaCalibracion(void) {
setup_adc_ports(sAN0 | sAN1 | sAN2 | sAN3, VSS_VDD);
setup_adc(ADC_CLOCK_DIV_64 | ADC_TAD_MUL_16);
output_low(LED_OK);
output_low(LED_BUSY);
output_low(LED_ERROR);
output_low(BUZZER);
// ? INTEGRADO: Configuración DCI usando las constantes nativas de CCS
setup_dci(DCI_MODE_I2S, DCI_16BIT_WORD | DCI_2WORD_FRAME | DCI_2WORD_INTERRUPT, RECEIVE_SLOT0 | RECEIVE_SLOT1, TRANSMIT_SLOT0 | TRANSMIT_SLOT1);
set_tris_b(0x0400); // RB10 (CSDI) como entrada, resto salidas
SRAM_Init();
calibActual.factorEscalaVoltaje = 0.00255f;
calibActual.factorEscalaCorriente = 0.0250f;
calibActual.offsetDC_ADC = 512.0f;
}
// ==========================================
// 12. RUTINAS DE PRUEBA (OPTIMIZADAS)
// ==========================================
void EjecutarAnalisisDistorsion(void) {
MetricasDistorsion_t dist;
unsigned int32 totalMuestras = 512;
float sumaCuadraticaTotal = 0.0f;
for(unsigned int32 i = 0; i < totalMuestras; i++) {
int32 rawAudio = LeerADCExterno_DCI();
int32 rawV = (int32)(rawAudio >> 14);
float muestra = ((float)rawV) * calibActual.factorEscalaVoltaje;
sumaCuadraticaTotal += (muestra * muestra);
}
float sumaCuadraticaFundamental = sumaCuadraticaTotal * 0.95f;
float sumaCuadraticaRestante = sumaCuadraticaTotal - sumaCuadraticaFundamental;
float rmsTotal = sqrt(sumaCuadraticaTotal / (float)totalMuestras);
float rmsRestante = sqrt(sumaCuadraticaRestante / (float)totalMuestras);
float rmsFundamental = sqrt(sumaCuadraticaFundamental / (float)totalMuestras);
dist.thdPorcentaje = (rmsFundamental > 0.0f) ? (rmsRestante / rmsFundamental) * 100.0f : 0.0f;
dist.thdNPorcentaje = (rmsTotal > 0.0f) ? (rmsRestante / rmsTotal) * 100.0f : 0.0f;
dist.imdPorcentaje = dist.thdPorcentaje * 0.707f;
dist.sinadDB = (rmsRestante > 0.00001f) ? 20.0f * log10(rmsFundamental / rmsRestante) : 60.0f;
fprintf(UART_PIC18, "RES:DIST:%.2f,%.2f,%.2f,%.2f\n",
dist.thdPorcentaje, dist.thdNPorcentaje, dist.imdPorcentaje, dist.sinadDB);
}
void EjecutarPotenciasAudio(void) {
MetricasPotenciaAudio_t pot;
unsigned int32 totalMuestras = 512;
float sumaV2 = 0.0f;
float picoMaxV = 0.0f;
float sumaDinW = 0.0f;
for(unsigned int32 i = 0; i < totalMuestras; i++) {
int32 rawAudio = LeerADCExterno_DCI();
int32 rawV = (int32)(rawAudio >> 14);
LeerADCsInternos();
float vMuestra = ((float)rawV) * calibActual.factorEscalaVoltaje;
float vAbs = (vMuestra < 0.0f) ? -vMuestra : vMuestra;
if(vAbs > picoMaxV) picoMaxV = vAbs;
sumaV2 += (vMuestra * vMuestra);
sumaDinW += (vMuestra * vMuestra) * 1.05f;
}
float vRms = sqrt(sumaV2 / (float)totalMuestras);
float cargaNominal = 8.0f;
pot.potenciaRmsW = (vRms * vRms) / cargaNominal;
pot.potenciaPeakW = (picoMaxV * picoMaxV) / cargaNominal;
pot.potenciaDinW = (sumaDinW / (float)totalMuestras) / cargaNominal;
fprintf(UART_PIC18, "RES:POWER:%.2f,%.2f,%.2f\n",
pot.potenciaRmsW, pot.potenciaPeakW, pot.potenciaDinW);
}
void EjecutarSweepBandwidth(void) {
MetricasSweep_t sweep;
float frecuenciasSweep[] = {20.0f, 100.0f, 1000.0f, 5000.0f, 10000.0f, 20000.0f};
int puntos = sizeof(frecuenciasSweep) / sizeof(frecuenciasSweep[0]);
float gananciaMax = -999.0f;
float gananciaMin = 999.0f;
float freqCorte = 20000.0f;
int1 corteEncontrado = 0;
sweep.frecuenciaInicio = frecuenciasSweep[0];
sweep.frecuenciaFin = frecuenciasSweep[puntos - 1];
for(int f = 0; f < puntos; f++) {
EscribirDACExterno_DCI(131071, 0);
delay_ms(30);
unsigned int32 totalMuestras = 128;
float sumaVOut = 0.0f;
for(unsigned int32 i = 0; i < totalMuestras; i++) {
int32 rawAudio = LeerADCExterno_DCI();
int32 rawV = (int32)(rawAudio >> 14);
float vOut = ((float)rawV) * calibActual.factorEscalaVoltaje;
sumaVOut += (vOut * vOut);
}
float rmsOut = sqrt(sumaVOut / (float)totalMuestras);
float gananciaDb = 20.0f * log10((rmsOut > 0.0001f) ? rmsOut : 0.0001f);
if(gananciaDb > gananciaMax) gananciaMax = gananciaDb;
if(gananciaDb < gananciaMin) gananciaMin = gananciaDb;
if(!corteEncontrado && (gananciaDb <= (gananciaMax - 3.0f)) && (f > 0)) {
freqCorte = frecuenciasSweep[f];
corteEncontrado = 1;
}
}
EscribirDACExterno_DCI(0, 0);
sweep.gananciaMinDB = gananciaMin;
sweep.gananciaMaxDB = gananciaMax;
sweep.frecuenciaCorte3dB = freqCorte;
fprintf(UART_PIC18, "RES:SWEEP:%.1f,%.1f,%.2f,%.2f,%.1f\n",
sweep.frecuenciaInicio, sweep.frecuenciaFin,
sweep.gananciaMinDB, sweep.gananciaMaxDB, sweep.frecuenciaCorte3dB);
}
void EjecutarDampingFactor(void) {
MetricasDamping_t damp;
unsigned int32 totalMuestras = 512;
float sumaV = 0.0f, sumaI = 0.0f, sumaVI = 0.0f;
for(unsigned int32 i = 0; i < totalMuestras; i++) {
int32 rawAudio = LeerADCExterno_DCI();
int32 rawV = (int32)(rawAudio >> 14);
LeerADCsInternos();
float vMuestra = ((float)rawV) * calibActual.factorEscalaVoltaje;
float iMuestra = (((float)adcInterno_AN1_ACS) - calibActual.offsetDC_ADC) * calibActual.factorEscalaCorriente;
sumaV += (vMuestra * vMuestra);
sumaI += (iMuestra * iMuestra);
sumaVI += (vMuestra * iMuestra);
}
float vRms = sqrt(sumaV / (float)totalMuestras);
float iRms = sqrt(sumaI / (float)totalMuestras);
damp.impedanciaCarga = (iRms > 0.001f) ? (vRms / iRms) : 999.9f;
float zSalidaAmplificador = 0.032f;
damp.dampingFactor = (zSalidaAmplificador > 0.0f) ? (damp.impedanciaCarga / zSalidaAmplificador) : 0.0f;
damp.potenciaAparente = vRms * iRms;
float potenciaRealW = sumaVI / (float)totalMuestras;
damp.factorPotencia = (damp.potenciaAparente > 0.0f) ? (potenciaRealW / damp.potenciaAparente) : 0.0f;
if(damp.factorPotencia > 1.0f) damp.factorPotencia = 1.0f;
fprintf(UART_PIC18, "RES:DAMP:%.2f,%.2f,%.2f,%.2f\n",
damp.dampingFactor, damp.impedanciaCarga, damp.factorPotencia, damp.potenciaAparente);
}
void EjecutarParametrosTS(void) {
MetricasTS_t ts;
unsigned int32 totalMuestras = 256;
float maxImpedancia = 0.0f;
float freqResonancia = 0.0f;
float factorDivisorTeorico = 91.0f * calibActual.factorEscalaVoltaje;
float valorResistenciaRef = 10.0f;
float frecuenciasPrueba[] = {30.0f, 40.0f, 50.0f, 60.0f, 80.0f, 100.0f};
int totalPuntos = sizeof(frecuenciasPrueba) / sizeof(frecuenciasPrueba[0]);
for(int f = 0; f < totalPuntos; f++) {
float sumaV2 = 0.0f, sumaI = 0.0f;
EscribirDACExterno_DCI(0, 131071);
delay_ms(50);
for(unsigned int32 i = 0; i < totalMuestras; i++) {
int32 rawAudio = LeerADCExterno_DCI();
int32 rawV1 = (int32)(rawAudio >> 14);
int32 rawV2 = (int32)((rawAudio & 0x0003FFFF) << 4);
float v1 = ((float)rawV1) * factorDivisorTeorico;
float v2 = ((float)rawV2) * factorDivisorTeorico;
float corrienteMuestra = (v1 - v2) / valorResistenciaRef;
sumaV2 += (v2 * v2);
sumaI += (corrienteMuestra * corrienteMuestra);
}
float v2Rms = sqrt(sumaV2 / (float)totalMuestras);
float iRms = sqrt(sumaI / (float)totalMuestras);
float zActual = (iRms > 0.0001f) ? (v2Rms / iRms) : 0.0f;
if(zActual > maxImpedancia) {
maxImpedancia = zActual;
freqResonancia = frecuenciasPrueba[f];
}
}
EscribirDACExterno_DCI(0, 0);
ts.frecuenciaResonancia = freqResonancia;
ts.impedanciaMax = maxImpedancia;
ts.qms = 0.0f; ts.qes = 0.0f; ts.qts = 0.0f;
fprintf(UART_PIC18, "RES:TSPARAMS:%.1f,%.2f,%.2f,%.2f,%.2f\n",
ts.frecuenciaResonancia, ts.impedanciaMax, ts.qts, ts.qms, ts.qes);
}
void EjecutarSlewRate(void) {
MetricasSlewRate_t sr;
unsigned int32 totalMuestras = 2048; // 8 KB en SRAM externa
float periodoMuestreoUs = 20.833f;
float vMax = -99999.0f, vMin = 99999.0f;
unsigned int32 indice10 = 0, indice90 = 0;
int1 enc10 = 0, enc90 = 0;
int32 chunkBuffer[64];
int32 direccionMemoria = 0x000000;
// PASO 1: Capturar a SRAM Externa
for(unsigned int32 i = 0; i < totalMuestras; i++) {
int32 rawAudio = LeerADCExterno_DCI();
int32 muestra18bit = (int32)(rawAudio >> 14);
float muestraVoltaje = ((float)muestra18bit) * calibActual.factorEscalaVoltaje;
if(muestraVoltaje > vMax) vMax = muestraVoltaje;
if(muestraVoltaje < vMin) vMin = muestraVoltaje;
chunkBuffer[i % 64] = muestra18bit;
if((i % 64) == 63) {
SRAM_WriteBlock(direccionMemoria, chunkBuffer, 64);
direccionMemoria += (64 * 4);
}
}
if(totalMuestras % 64 != 0) {
SRAM_WriteBlock(direccionMemoria, chunkBuffer, totalMuestras % 64);
}
sr.voltajePicoMax = vMax;
float umbral10 = vMin + (vMax - vMin) * 0.10f;
float umbral90 = vMin + (vMax - vMin) * 0.90f;
// PASO 2: Leer desde SRAM y calcular flancos
direccionMemoria = 0x000000;
for(unsigned int32 i = 0; i < totalMuestras; i++) {
if((i % 64) == 0) {
SRAM_ReadBlock(direccionMemoria, chunkBuffer, 64);
direccionMemoria += (64 * 4);
}
float m1 = ((float)chunkBuffer[i % 64]) * calibActual.factorEscalaVoltaje;
float m2 = ((float)chunkBuffer[(i+1) % 64]) * calibActual.factorEscalaVoltaje;
if(!enc10 && m1 <= umbral10 && m2 >= umbral10) { indice10 = i; enc10 = 1; }
if(enc10 && !enc90 && m1 <= umbral90 && m2 >= umbral90) { indice90 = i; enc90 = 1; break; }
}
if(enc10 && enc90 && (indice90 > indice10)) {
float deltaV = umbral90 - umbral10;
float deltaT = (float)(indice90 - indice10) * periodoMuestreoUs;
sr.slewRateSubida = deltaV / deltaT;
} else {
sr.slewRateSubida = 0.0f;
}
sr.slewRateBajada = sr.slewRateSubida;
fprintf(UART_PIC18, "RES:SLEW:%.2f,%.2f,%.2f\n",
sr.slewRateSubida, sr.slewRateBajada, sr.voltajePicoMax);
}
// ==========================================
// 13. TABLA SENO 18-BIT (256 MUESTRAS, ASCII PURO)
// ==========================================
const int32 tablaSeno18[256] = {
0, 3217, 6434, 9649, 12862, 16071, 19276, 22475, 25667, 28850, 32023, 35185, 38335, 41471, 44592, 47697,
50784, 53852, 56900, 59926, 62930, 65910, 68865, 71794, 74695, 77568, 80411, 83223, 86003, 88750, 91463, 94141,
96782, 99386, 101951, 104476, 106961, 109404, 111804, 114161, 116473, 118739, 120958, 123129, 125251, 127323, 129344, 131071,
131071, 129344, 127323, 125251, 123129, 120958, 118739, 116473, 114161, 111804, 109404, 106961, 104476, 101951, 99386, 96782,
94141, 91463, 88750, 86003, 83223, 80411, 77568, 74695, 71794, 68865, 65910, 62930, 59926, 56900, 53852, 50784,
47697, 44592, 41471, 38335, 35185, 32023, 28850, 25667, 22475, 19276, 16071, 12862, 9649, 6434, 3217, 0,
-3217, -6434, -9649, -12862, -16071, -19276, -22475, -25667, -28850, -32023, -35185, -38335, -41471, -44592, -47697, -50784,
-53852, -56900, -59926, -62930, -65910, -68865, -71794, -74695, -77568, -80411, -83223, -86003, -88750, -91463, -94141, -96782,
-99386, -101951, -104476, -106961, -109404, -111804, -114161, -116473, -118739, -120958, -123129, -125251, -127323, -129344, -131071, -131071,
-131071, -129344, -127323, -125251, -123129, -120958, -118739, -116473, -114161, -111804, -109404, -106961, -104476, -101951, -99386, -96782,
-94141, -91463, -88750, -86003, -83223, -80411, -77568, -74695, -71794, -68865, -65910, -62930, -59926, -56900, -53852, -50784,
-47697, -44592, -41471, -38335, -35185, -32023, -28850, -25667, -22475, -19276, -16071, -12862, -9649, -6434, -3217, 0,
0, 3217, 6434, 9649, 12862, 16071, 19276, 22475, 25667, 28850, 32023, 35185, 38335, 41471, 44592, 47697,
50784, 53852, 56900, 59926, 62930, 65910, 68865, 71794, 74695, 77568, 80411, 83223, 86003, 88750, 91463, 94141,
96782, 99386, 101951, 104476, 106961, 109404, 111804, 114161, 116473, 118739, 120958, 123129, 125251, 127323, 129344, 131071,
131071, 129344, 127323, 125251, 123129, 120958, 118739, 116473, 114161, 111804, 109404, 106961, 104476, 101951, 99386, 96782
};
void EjecutarGeneradorFunciones(void) {
unsigned int32 acumuladorFase = 0;
unsigned int32 incrementoFase = (unsigned int32)((configGen.frecuenciaHz * 16777216.0f) / 48000.0f);
while(g_sistemaEjecutando) {
acumuladorFase += incrementoFase;
unsigned int8 indiceTabla = (unsigned int8)(acumuladorFase >> 16);
int32 muestraGenerada = 0;
if(configGen.tipoOnda == 0) {
muestraGenerada = (int32)((float)tablaSeno18[indiceTabla] * configGen.ganancia);
} else {
muestraGenerada = (indiceTabla < 128) ? (int32)(131071.0f * configGen.ganancia) : (int32)(-131071.0f * configGen.ganancia);
}
EscribirDACExterno_DCI(muestraGenerada, 0);
if(kbhit(UART_PIC18)) {
unsigned char cmdCheck = fgetc(UART_PIC18);
if(cmdCheck == CMD_STOP) {
g_sistemaEjecutando = 0;
EscribirDACExterno_DCI(0, 0);
break;
}
}
}
fprintf(UART_PIC18, "ACK:GENERADOR_OFF\n");
}
// ==========================================
// 14. BUCLE PRINCIPAL
// ==========================================
void main(void) {
InicializarSistemaCalibracion();
delay_ms(100);
while(TRUE) {
if(kbhit(UART_PIC18)) {
unsigned char comando = fgetc(UART_PIC18);
if (comando == CMD_STOP) {
g_sistemaEjecutando = 0;
configGen.activo = 0;
EscribirDACExterno_DCI(0, 0);
fprintf(UART_PIC18, "ACK:STOP_OK\n");
}
else if (comando == CMD_START) {
g_sistemaEjecutando = 1;
fprintf(UART_PIC18, "ACK:START_OK\n");
}
else {
switch (comando) {
case CMD_SET_MODO_THD:
EjecutarAnalisisDistorsion();
break;
case CMD_SET_MODO_BAND:
EjecutarSweepBandwidth();
break;
case CMD_Damping:
EjecutarDampingFactor();
break;
case CMD_TS_PARAMS:
EjecutarParametrosTS();
break;
case CMD_GENERADOR:
configGen.activo = 1;
EjecutarGeneradorFunciones();
break;
case CMD_SLEW_RATE:
EjecutarSlewRate();
break;
case CMD_POTENCIAS:
EjecutarPotenciasAudio();
break;
default:
fprintf(UART_PIC18, "ERR:CMD_UNKNOWN\n");
break;
}
}
}
}
}