Generátor: Generovaní sinusového a trojúhelníkového průběhu

No tak pekne dakujem :slight_smile:
Tak este prikladam konecnu verziu aj s vypisom v ASM. Pravoverni ASM by este videli moznost optimalizovat kod pri plneni ukazatela nie z RAM ale z registrov, ale to su uz len marginalne opatrenia. Pod 0.6us na periodu sa myslim vyrazne nedostanu (>10%). Ale mozno to tu niekto predvedie, tesim sa :slight_smile:

samotny program slucky trva 0.6us a pri prednastaveni hodnot (jeden krat za periodu) 0.7us.

Hodnoty v poliach si musis prepocitat na 25vzoriek a na pozadovanu amplitudu ucitelom.

perioda sinusu je od 23.7 do 23.9us, tak ze priemer je 23.74us
(pocitane z desiatich period v simulatore).
Jedna vzorka sa napni za 1us, po niekolkych vzorkach za 0.8us tak, ze priemer je tych 0.9496us na vzorku aby na periodu bolo tych 23.74us.
Frekvencia je od pozadovanej o 1% vyssia, to by nemalo vadit. Vhodnejsie hodnoty som skusmo nenasiel.

Perioda trojuholnika je od 20,00us do 20,10us. Priemer z desiatich period je 20.00us.
Jedna vzorka sa naplni vzdy pravidelne za 0.8us.

#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>


#define SET(BAJT,BIT) ((BAJT) |= (1<<(BIT)))
#define TST(BAJT,BIT) ((BAJT) & (1<<(BIT)))

#define TRUE 0x00
#define FALSE 0xff
#define SINUS TRUE
#define TROJUHOLNIK FALSE
#define PREDVOLBA_CZ_SINUS 18 // 41.67kHz predv.18,vz25=42.12kHz, predv.18,vz26=40.48kHz, predv.17/vz26=42.74kHz, predv.17,vz27=41.15kHz
#define PREDVOLBA_CZ_TROJUHOLNIK 15 // 50kHz: predvolba 15,vz.25  

// pri rovnakom pocte vzoriek 25 a predvolbe 15 je vystupna frekvencia signalu 50kHz
// pri rovnakom pocte vzoriek 25 a predvolbe 18 je vystupna frekvencia signalu 42.12kHz, co je o 1% vyssia frekvencia aka bola pozadovana


#define POCET_VZORIEK 25

#define PORT_PRE_DA PORTB
#define SMER_PORT_PRE_DA DDRB

uint8_t generuj_signal = SINUS;
uint8_t stav_tlacitka_new,  stav_tlacitka_old, i;

uint8_t sinu  [POCET_VZORIEK] = {127,138,149,160,171,182,193,205,      //127-205
                     205,193,182,171,160,149,138,127,      //205-127
                     127,116,105,94,83,72,61,49,         //127-49
                     49,61,72,83,94,105,116,127};      //49-127

// trojuholnik s rovnakym poctom prvkov ako SINUS. 
uint8_t troj2  [POCET_VZORIEK] = {0,10,20,30,40,50,60,70,
                     80,90,100,110,120,130,140,150,  
                     160,150,140,130,120,110,100,90,    
                     80,70,60,50,40,30,20,10};   


volatile uint8_t *p_bajt_pom;

int main(void)
{
	register uint8_t i, j;
	register uint8_t *p_bajt;

	p_bajt_pom = (uint8_t *)sinu;
	p_bajt = (uint8_t *)p_bajt_pom;
		
//	predvolba = MAX_VZORKY_SINUS;
//	i = predvolba;
	i = POCET_VZORIEK;
	SMER_PORT_PRE_DA = 0xff;

   OCR2 = PREDVOLBA_CZ_SINUS;
   SET(TCCR2,WGM21);
   SET(TCCR2,CS20); // delicka 1

	while(1) {
		j = TIFR;
		if (TST(j, OCF2)) {
		   TIFR = j;
	      i--;
   		if (i == 0) {
				i = POCET_VZORIEK; 
				p_bajt = (uint8_t *)p_bajt_pom;
	      }
		   PORT_PRE_DA = *p_bajt;
    		p_bajt++;
		}
	}
}

// nech je tlacitko pripojene na pin s INT0 a dobre osetrene proti zakmitom
// frekvencia sa bude menit zmenou hodnoty v OCR2
ISR (INT0_vect) { 
	if (p_bajt_pom == (uint8_t *)sinu) {
		 p_bajt_pom = (uint8_t *)troj2;
       OCR2 = PREDVOLBA_CZ_SINUS;
	}	 
	else {
		p_bajt_pom = (uint8_t *)sinu;
      OCR2 = PREDVOLBA_CZ_TROJUHOLNIK;
	}
	return;   
}  

vypis strojoveho kodu z prekladaca.

43:       {
+0000002F:   E6E0        LDI       R30,0x60       Load immediate
+00000030:   E0F0        LDI       R31,0x00       Load immediate
+00000031:   93F00094    STS       0x0094,R31     Store direct to data space
+00000033:   93E00093    STS       0x0093,R30     Store direct to data space
53:       	SMER_PORT_PRE_DA = 0xff;
+00000035:   EF8F        SER       R24            Set Register
+00000036:   BB87        OUT       0x17,R24       Out to I/O location
55:          OCR2 = PREDVOLBA_CZ_SINUS;
+00000037:   E182        LDI       R24,0x12       Load immediate
+00000038:   BD83        OUT       0x23,R24       Out to I/O location
56:          SET(TCCR2,WGM21);
+00000039:   B585        IN        R24,0x25       In from I/O location
+0000003A:   6088        ORI       R24,0x08       Logical OR with immediate
+0000003B:   BD85        OUT       0x25,R24       Out to I/O location
57:          SET(TCCR2,CS20); // delicka 1
+0000003C:   B585        IN        R24,0x25       In from I/O location
+0000003D:   6081        ORI       R24,0x01       Logical OR with immediate
+0000003E:   BD85        OUT       0x25,R24       Out to I/O location
52:       	i = POCET_VZORIEK;
+0000003F:   E199        LDI       R25,0x19       Load immediate
62:       		j = TIFR;
+00000040:   B788        IN        R24,0x38       In from I/O location
63:       		if (TST(j, OCF2)) {
+00000041:   FF87        SBRS      R24,7          Skip if bit in register set
+00000042:   CFFD        RJMP      PC-0x0002      Relative jump
64:       		   TIFR = j;
+00000043:   BF88        OUT       0x38,R24       Out to I/O location
65:       	      i--;
+00000044:   5091        SUBI      R25,0x01       Subtract immediate
67:          		if (i == 0) {
+00000045:   F419        BRNE      PC+0x04        Branch if not equal
69:       				p_bajt = (uint8_t *)p_bajt_pom;
+00000046:   E6E0        LDI       R30,0x60       Load immediate
+00000047:   E0F0        LDI       R31,0x00       Load immediate
68:       				i = POCET_VZORIEK; 
+00000048:   E199        LDI       R25,0x19       Load immediate
71:       		   PORT_PRE_DA = *p_bajt;
+00000049:   9181        LD        R24,Z+         Load indirect and postincrement
+0000004A:   BB88        OUT       0x18,R24       Out to I/O location
+0000004B:   CFF4        RJMP      PC-0x000B      Relative jump
@0000004C: __vector_1
79:       ISR (INT0_vect) { 
+0000004C:   921F        PUSH      R1             Push register on stack
+0000004D:   920F        PUSH      R0             Push register on stack
+0000004E:   B60F        IN        R0,0x3F        In from I/O location
+0000004F:   920F        PUSH      R0             Push register on stack
+00000050:   2411        CLR       R1             Clear Register
+00000051:   932F        PUSH      R18            Push register on stack
+00000052:   938F        PUSH      R24            Push register on stack
+00000053:   939F        PUSH      R25            Push register on stack
80:       	if (p_bajt_pom == (uint8_t *)sinu) {
+00000054:   91800093    LDS       R24,0x0093     Load direct from data space
+00000056:   91900094    LDS       R25,0x0094     Load direct from data space
+00000058:   E020        LDI       R18,0x00       Load immediate
+00000059:   3680        CPI       R24,0x60       Compare with immediate
+0000005A:   0792        CPC       R25,R18        Compare with carry
+0000005B:   F081        BREQ      PC+0x11        Branch if equal
85:       		p_bajt_pom = (uint8_t *)sinu;
+0000005C:   E680        LDI       R24,0x60       Load immediate
+0000005D:   E090        LDI       R25,0x00       Load immediate
+0000005E:   93900094    STS       0x0094,R25     Store direct to data space
+00000060:   93800093    STS       0x0093,R24     Store direct to data space
86:             OCR2 = PREDVOLBA_CZ_TROJUHOLNIK;
+00000062:   E08F        LDI       R24,0x0F       Load immediate
+00000063:   BD83        OUT       0x23,R24       Out to I/O location
89:       }  
+00000064:   919F        POP       R25            Pop register from stack
+00000065:   918F        POP       R24            Pop register from stack
+00000066:   912F        POP       R18            Pop register from stack
+00000067:   900F        POP       R0             Pop register from stack
+00000068:   BE0F        OUT       0x3F,R0        Out to I/O location
+00000069:   900F        POP       R0             Pop register from stack
+0000006A:   901F        POP       R1             Pop register from stack
+0000006B:   9518        RETI                     Interrupt return
81:       		 p_bajt_pom = (uint8_t *)troj2;
+0000006C:   E789        LDI       R24,0x79       Load immediate
+0000006D:   E090        LDI       R25,0x00       Load immediate
+0000006E:   93900094    STS       0x0094,R25     Store direct to data space
+00000070:   93800093    STS       0x0093,R24     Store direct to data space
82:              OCR2 = PREDVOLBA_CZ_SINUS;
+00000072:   E182        LDI       R24,0x12       Load immediate
+00000073:   BD83        OUT       0x23,R24       Out to I/O location
89:       }  
+00000074:   919F        POP       R25            Pop register from stack
+00000075:   918F        POP       R24            Pop register from stack
+00000076:   912F        POP       R18            Pop register from stack
+00000077:   900F        POP       R0             Pop register from stack
+00000078:   BE0F        OUT       0x3F,R0        Out to I/O location
+00000079:   900F        POP       R0             Pop register from stack
+0000007A:   901F        POP       R1             Pop register from stack
+0000007B:   9518        RETI                     Interrupt return
89:       } 

Rozhodenie signalu pocas spracovanie interuptu od tlacitka nevidim ako problem, lebo aj tak chcem menit typ signalu, tak na tych par mikrosekundach rozhodenia casovaca aj tak nezalezi.

Tot vsjo, drzim Ti palce :slight_smile: