/* * File: opravdicky FIR, ktery bude fungovat * Author: kubalik * * SKOUKNUTO 2024-03-11 a zda se to byt spravne * DALE UPRAVENO od 2025-10-12 * * POZOR !!! File se NESMI jmenovat stejne !!!!!! * * * * * * */ #include "p33EV32GM002.h" #pragma config FNOSC = FRCPLL // pracujeme s FRC oscilatorem 7.37MHz , s delickou, a nasledne s PLL // #pragma config FNOSC = FRC // tohle je v mem vzoroverm prikldu na oyeasois - as m oscilator pracujeme s FRC oscilatorem 7.37MHz #pragma config IESO = OFF // Start up device with user selected oscillator source #pragma config IOL1WAY = ON // Allow Only One reconfiguration pro PPS #pragma config FWDTEN = OFF // WDT and SWDTEN Disabled Watchdog vypnut #pragma config DMTEN = DISABLE // Dead Man Timer is Disabled and can be enabled by software #pragma config PWMLOCK = OFF // PWM registers may be written without key sequence #pragma config FCKSM = CSECMD // Clock Switching is enabled,Fail-safe Clock Monitor is disabled #pragma config OSCIOFNC = OFF // OSC2 is clock output #pragma config POSCMD = NONE // Primary Oscillator disabled // pin 10 -RA3 - nepouzivat OSC2 is clock output // tohle chci pouzit take v assemblerovske casti // proto je to globalni // KONECFILTR je definovan v include file koef.h #include "koef.h" const unsigned int konfilt = KONECFILTR ; // abych dostal tuhle konstantu do asm podprogramu const unsigned int filterkonec = (unsigned int) &filter[KONECFILTR] ; const unsigned int filterzac = (unsigned int) &filter[0] ; unsigned int delkafiltru = KONECFILTR ; // o 1 mene ney je skutecna delka, ale pro pouyiti pomoci repeat se to tak hodi signed _Fract hodnoty[KONECFILTR+1] __attribute__ ((space(ymemory))) ; // tohle bude ulozeno v Y space memory signed _Fract vzorek __attribute__ ((space(xmemory))) ; /* pole koeficientu filtru bude v X-space. Jinak to nejde, mam ho jako const signed _Fract filter[KONECFILTR+1] to znamena, ze je v EEPROM a pouzije se na nej PSV Z toho vyplyva, ze pole s hodnotami vyorku MUSI byt v Y space kvuli MAC prefetches Y space ma 2048 byte, promenna fixed je 2 byte, takze pole hodnoty muza byt nanejvyse 1024 prvku promenne, u kterych jsme neurcili, kam se maji nacpat (X space nebo Y space) si prekladac nekam da sam podle sveho uvazeni */ unsigned int fff ; const unsigned int hodnotykonec = (unsigned int) &hodnoty[KONECFILTR] ; const unsigned int hodnotyzac = (unsigned int) &hodnoty[0] ; void pokus(void) ; // int filt( _Fract vstup) ; int filt( unsigned int vstup) ; void nastavreg(void) ; void poslidoSPI( unsigned int CO ); void prepioscilator (void) ; void PPSinit(); void ADCinit(void); void T2init() ; void T3init() ; void SPI2init(void) ; int minulyvzorek ; // ????????????? a nemelo by to byt unsigned int ?????????? void main() { int i ; CORCONbits.SATA = 1 ; // zapiname saturaci pro akumulator A CORCONbits.US = 0 ; // nasobeni je signed CORCONbits.IF = 0 ; // format fractional CORCONbits.SATDW = 1 ; for (i=0;i<=KONECFILTR;i++) hodnoty[i] = 0 ; PPSinit() ; TRISA = 0 ; TRISB = 0 ; ANSELA = 0 ; ANSELB = 0 ; TRISAbits.TRISA0 = 1 ; // tady je vstup ADC ANSELAbits.ANSA0 = 1 ; T2init() ; ADCinit(); SPI2init(); T3init() ; prepnioscilator(); PORTBbits.RB14 = 1 ; PORTBbits.RB13 = 1 ; nastavreg(); INTCON2bits.GIE = 1 ; while(1) { i++ ; // hlavni akce se deje v preruseni od citace } } void T2init() { PMD1bits.T2MD = 0 ; IFS0bits.T2IF = 0 ; // tady proto, ze PMD potrebuje cas na zapnuti asm("clr TMR2"); PR2 = 8437 ; // generujeme 8 kHz T2CON=0x8000; /* 1000 0000 0000 0000 - 00 na bitech 54 - delime 1 // 135000 /2 /8 ANO , skouknuto na 135 MHz */ IEC0bits.T2IE=1; } void T3init() { PMD1bits.T3MD = 0 ; IFS0bits.T3IF = 0 ; // tady proto, ze PMD potrebuje cas na zapnuti asm("clr TMR3"); PR3 = 65535 ; // generujeme 4 Hz , no o malinko vice - SKOUKNUTO na 135 MHz T3CON=0x8030; // 1000 0000 0011 0000 - 11 na bitech 54 - delime 254 // 135000000 /2 /254 / 4 a to je 66437 , to uz preteklo IEC0bits.T3IE=1; } void ADCinit(void) { PMD1bits.AD1MD = 0 ; // AN61-Band Gap Voltage AN62-CTMU Temp Diode // AD1CON1 = 0x0407 ; // 0X0X X100 0000 0100 rucni odstartovani, vzorkovani zacne samo, unsigned integer, 12 bit AD1CON1 = 0x0707 ; // 0X0X X111 0000 0100 rucni odstartovani, vzorkovani zacne samo, signed fractional, 12 bit // bity 0 a 1 jsou 11 ????? snadjo, zkusime AD1CON2 = 0 ; // XXXX X0XX XX00 0000 AD1CON3 = 9 ; /* Fp je 130 / 2 = 65 MHz 117.6ns odpovida 8.5 MHz tak to nechame :10 , */ AD1CON4 = 0 ; // vypiname DMA AD1CHS0 = 0x0000 ; // 0000 0000 00BB BBBB 61 je 11 1101 PIN2 /AN0/RA0 IFS0bits.AD1IF = 0 ; IEC0bits.AD1IE = 0 ; // preruseni nebudeme pouzivat AD1CON1bits.ADON = 1 ; // zapinam prevodnik } void PPSinit() { // unlock: __builtin_write_OSCCONL(OSCCON & 0xBF) ; RPOR1bits.RP37R = 0x08 ; // mov.B WREG, RPOR1H ; PIN14 RB5 SDO RP37 RPOR2bits.RP38R = 0x09 ; //mov.B WREG, RPOR2L ; PIN15 RB6 SCK RP38 RPINR22bits.SCK2R = 0x26 ; // mov #0x26 , W0 ; PIN15 RB6 SCK // u master modu musi byt SCK vstupni i vystupni //lock: __builtin_write_OSCCONL(OSCCON | 0x40) ; } // ; tady dál je nastavení SPI void SPI2init(void) { unsigned int i ; i = SPI2BUF ; i = SPI2BUF ; i = SPI2BUF ; i = SPI2BUF ; i = SPI2BUF ; // SPI2CON1 // xxx0 0101 0010 0000 delime 128 to je 508 kHz pro hodiny / 16 je asi 32 kHz vysilani SPI zabere asi 1/4 vzorkovaciho untervalu // xxx0 0101 0011 1000 cke1 ckp0 SKOUKNUTO na 135 MHz // | |||| |||| |||| // | |||| |||| ||00 primary prescaller 64 // | |||| |||| || // | |||| |||1 10 second. prescaller deli 2 // | |||| ||| // | |||| ||1 Master mod // | |||| || // | |||| |0 CKP // | |||| | // | |||| 0 SSEN // | |||1 CKE // | ||| // | ||0 SMP tady je to jedno, nebudeme nic prijimat // | |1 MODE16 16 bitovy mod // | | // | 0 DISSDO // 0 DIUSSCK SPI2CON1 = 0x0538 ; // SPI2CON2 // 0xxx xxxx xxxx xxx0 // | | // | 0 = Enhanced buffer is disabled (Standard mode) // 0 = Framed SPIx support is disabled SPI2CON2 = 0 ; IPC8bits.SPI2IP = 5 ; // SPI1STAT // 0-x- -xxx x0xx xxxx // | | // | 0 = Overflow has not occurred // | // 1 = Enables the SPIx module and configures SCKx, SDOx, SDIx and SSx as serial port pins // ; ale zapneme to az nakonec SPI2STATbits.SPIROV = 0 ; SPI2STATbits.SPIEN = 1 ; // zapiname modul IFS2bits.SPI2IF = 0 ; IEC2bits.SPI2IE = 1 ; // povoluji preruseni IFS2bits.SPI2EIF = 0 ; IEC2bits.SPI2EIE = 1 ; } void prepnioscilator ( void ) { // tady dale nastavujeme frekvenci 135 MHz // 010 = FRCDIV FRC divided by 4 7.37 / 4 = 1,8425 // a PLLPRE deli 2 , min to nejde 0,92125 MHz // PLLPOST deli 2 135 MHz pred PPLPOST 135 * 2 = 270 // nasobit 293 270 / 0,92125 // do PLLFBD ulozime 293 - 2 = 291 // CLKDIV xxxx xxxx xxxx xxxx // ||| || | |||| // ||| || PLLPRE 00000 = Input divided by 2 min to nejde // ||| || // ||| PLLPOST 00 = Output divided by 2 // ||| // FRCDIV 010 = FRC divided by 4 // celkem 0000 0010 0000 0000 0x0200 CLKDIV = 0x0200 ; PLLFBD = 291 ; // startujeme prepnuti oscilatoru, je tu zapis do L i H casti OSCCON __builtin_write_OSCCONH(0x01); __builtin_write_OSCCONL(OSCCON | 0x01); } void poslidoSPI( unsigned int CO ) { unsigned int i ; PORTBbits.RB13 = 0 ; // CS prevodniku do 0 i = SPI2BUF ; i = SPI2BUF ; i = ( CO & 0x0fff ) | 0x1000 ; // prevodnik A, to je pin 8 , rozsah do 4,095V SPI2BUF = i ; } void __attribute__((interrupt, shadow, auto_psv)) _SPI2ErrInterrupt(void) { unsigned int i ; IFS2bits.SPI2EIF = 0 ; i = SPI2BUF ; i = SPI2BUF ; i = SPI2BUF ; i = SPI2BUF ; i = SPI2BUF ; SPI2STATbits.SPIEN = 0 ; SPI2STATbits.SPIROV = 0 ; SPI2STATbits.SPIEN = 1 ; } void __attribute__((interrupt, shadow, auto_psv)) _SPI2Interrupt(void) { IFS2bits.SPI2IF = 0 ; PORTBbits.RB13 = 1 ; // vracim CS od prevodniku } // vola se s per. 125 us, dela vzorkovaci kmitocet void __attribute__((interrupt, shadow, auto_psv)) _T2Interrupt(void) { IFS0bits.T2IF = 0 ; // vzorek = ADC1BUF0 ; fff = ADC1BUF0 ; // fff je pro transfer do podprogramu filt AD1CON1bits.SAMP = 0 ; // start prevodniku poslidoSPI( minulyvzorek + 2048 ) ; PORTBbits.RB15 = 1 ; // kvuli delce vypoctu, zobrazit na osc minulyvzorek = filt( fff); PORTBbits.RB15 = 0 ; } void __attribute__((interrupt, shadow, auto_psv)) _T3Interrupt(void) { IFS0bits.T3IF = 0 ; PORTBbits.RB14 = ! PORTBbits.RB14 ; // blika 1x za 1 sec, po prepnuti na 135 MHz blika rychleji }