Giter Site home page Giter Site logo

musical-embedded-system's Introduction

Hey 👋, I'm Gustavo Braga!

I have a degree in computer engineering, with a focus on computer graphics and computer vision 👨🏽‍💻. Currently working with web 3.0 and innovation 💡. I have experience in building innovative solutions 📐 using spatial computing, digital twins and machine learning with the newest devices in the market like Hololens, Magic Leap and Oculus. Besides that, I am experienced in 3d and point cloud data manipulation 📋, shaders and multithreading processes. I also build games using Unity/Unreal/Godot 🕹.

Extremelly passionate about visual simulations 🧬 using compute shaders, fragment shaders and VFX Graph. Fascinated by ilusions and computer graphics challenges. 📡

You can check out my visual experiments, simulations, games and more here! 🚀 Feel free to message me at [email protected].📧

Some of my work with bio inspired simulations using shaders 🐞

3D Boids 3D CA Physarum
Alt Text Alt Text Alt Text
Clusters Primordial Particle System Multiple Neighborhood Cellular Automata
Alt Text Alt Text Alt Text
Reaction Diffusion Game of Life 3D Diffusion Limited Aggregation
Alt Text Alt Text Alt Text

And much more at my page.

musical-embedded-system's People

Contributors

andrekwr avatar gustavobb avatar

Stargazers

 avatar

Watchers

 avatar  avatar

Forkers

andrekwr

musical-embedded-system's Issues

Uso de elseif

if (frequency <= min + range) pio_clear(LED1_PIO, LED1_PIO_IDX_MASK);
if (frequency > min + range && frequency <= min + 2*range) pio_clear(LED2_PIO, LED2_PIO_IDX_MASK);
if (frequency > min + 2*range) pio_clear(LED3_PIO, LED3_PIO_IDX_MASK);

Neste trecho, dá para ver, que sempre ocorrerá a condição verdadeira apenas em um dos if's em um dado instante. Do jeito que está, com 3 if's independentes, o código gerado pelo compilador terá no mínimo 3 verificações de condição, sendo que só é necessário um.

Para evitar isso, basta usar else if, já que caso o primeiro if não ocorra (caso falso), ele tenta o segundo assim por diante.

	if (frequency <= min + range) pio_clear(LED1_PIO, LED1_PIO_IDX_MASK);
	else if (frequency > min + range && frequency <= min + 2*range) pio_clear(LED2_PIO, LED2_PIO_IDX_MASK);
	else if (frequency > min + 2*range) pio_clear(LED3_PIO, LED3_PIO_IDX_MASK);

Vantagens:

  • Performance, imagine que fosse uma rotina critica, você colocando o primeiro if com a condição mais provável de ocorrer, você poderia nesse trecho ganhar até 3x de performance, já que normalmente faria apenas uma condição ao invés de no mínimo 3.
  • Fica claro ao desenvolvedor, que apenas uma das condições ocorrerá, sem ter que analisar o que está dentro da condição do if. Facilidade de leitura.

Criar um define para cada prioridade

NVIC_EnableIRQ(BUT1_PIO_ID);
NVIC_SetPriority(BUT1_PIO_ID, 0);
pio_handler_set(BUT2_PIO, BUT2_PIO_ID, BUT2_PIO_IDX_MASK, PIO_IT_FALL_EDGE, but_play_callback);
pio_enable_interrupt(BUT2_PIO, BUT2_PIO_IDX_MASK);
NVIC_EnableIRQ(BUT2_PIO_ID);
NVIC_SetPriority(BUT2_PIO_ID, 0);
pio_handler_set(BUT3_PIO, BUT3_PIO_ID, BUT3_PIO_IDX_MASK, PIO_IT_FALL_EDGE, but_next_callback);
pio_enable_interrupt(BUT3_PIO, BUT3_PIO_IDX_MASK);
NVIC_EnableIRQ(BUT3_PIO_ID);
NVIC_SetPriority(BUT3_PIO_ID, 0);

Exemplo

// (Colocar este define junto com os outros do botão)
#define BUT2_PRIORITY 6

NVIC_SetPriority(BUT2_PIO_ID, BUT2_PRIORITY);

Vantagens:

  • Fica explicito junto com as demais configurações do botão, permitindo fácil alteração da prioridade se necessário.
  • Evita número "mágico" no meio do código, ficando bem óbvio o que se trata (código se auto documenta).

Declaração de mais de uma variável definindo valor.

int note_duration, range = (song.max_value - song.min_value)/3;;

Essa forma de declaração é altamente não recomendada, pois é fácil levar a um simples erro.

Qual o valor de range? Realmente, é (song.max_value - song.min_value)/3;

Agora... qual o valor de note_duration?

Se você disse igual ao range... Você errou! O valor é indefinido ou zero (dependendo do compilador). Pois ele só define valor a variável range.

Por este motivo, nunca é recomendado definir mais de duas variáveis com um valor em C.
Não fazer isso

int a, b = 3;

e sim

int a = 3;
int b = 3;

ou

int a, b;
a = 3;
b = 3;

Fontes:
Google - Projetos em C/C++ (Chrome, e entre outros)

Gnome - Linux - Projetos em C

Poderia por a condição no while e se livrar do if/break. Poderia ter um sleep.

while (1) if (but_play_flag || but_prev_flag || but_next_flag) break;

while( !(but_play_flag || but_prev_flag || but_next_flag) );

Enquanto não pressionar nenhum dos botões, fica preso no While.

Ainda nesse lugar, poderia ser feito o seguinte:

pmc_sleep(...);
while( !(but_play_flag || but_prev_flag || but_next_flag) );

Como os flags são acionados por interrupção, ele iria acordar, processar o while logo em seguida. Economizando energia.

Defines para números mágicos ou comentário mais elaborado

int delay = 1000000 / frequency;

O que representa o valor 100000?

Assim, sei que representa a conta de uma nota musical, provavelmente em tempo. No entanto, ao bater o olho, fica dificil saber, estes 100000 seria o que 100 segundos? 100 milissegundos?
100 us?

Enfim, deixar o código mais comentado ou usar defines para dizer o que são essas variáveis tem suas vantagens:

Fica mais fácil para entender o que está sendo feito
Permite ajuste fino pelo usuário fácil apenas alterando um define

Poderia ter uma função draw_music_status

gfx_mono_draw_string("PAUSE", 50, 20, &sysfont);

Que tal?

void draw_music_status(char* status) {
    gfx_mono_draw_string(status, 50, 20, &sysfont);
}

Usar para PLAY e PAUSE.

Vantagens:

  • Separa lógica de processamento da lógica de exibição.
  • Para alterar a interface visual no OLED, basta alterar uma função, ficando bem claro, o seu uso. Evitando ter código repetido espalhado.

Criar uma função para configurar o struct de cada música.

mario_main_song.max_value = mario_main[0];
mario_main_song.min_value = mario_main[0];
for (int i = 0; i < sizeof(mario_main) / sizeof(int); i++) {
mario_main_song.music[i] = mario_main[i];
mario_main_song.tempo[i] = mario_main_tempo[i];
if (mario_main_song.max_value < mario_main[i]) mario_main_song.max_value = mario_main[i];
if (mario_main_song.min_value > mario_main[i] && mario_main[i] != 0) mario_main_song.min_value = mario_main[i];
}
mario_main_song.velocity = 0.15;
pirates_of_the_caribean_song.max_value = pirates_of_the_caribean[0];
pirates_of_the_caribean_song.min_value = pirates_of_the_caribean[0];
for (int i = 0; i < sizeof(pirates_of_the_caribean) / sizeof(int); i++) {
pirates_of_the_caribean_song.music[i] = pirates_of_the_caribean[i];
pirates_of_the_caribean_song.tempo[i] = pirates_of_the_caribean_tempo[i];
if (pirates_of_the_caribean_song.max_value < pirates_of_the_caribean[i]) pirates_of_the_caribean_song.max_value = pirates_of_the_caribean[i];
if (pirates_of_the_caribean_song.min_value > pirates_of_the_caribean[i] && pirates_of_the_caribean[i] != 0) pirates_of_the_caribean_song.min_value = pirates_of_the_caribean[i];
}
pirates_of_the_caribean_song.velocity = 1.5;
underworld_mario_song.max_value = underworld_mario[0];
underworld_mario_song.min_value = underworld_mario[0];
for (int i = 0; i < sizeof(underworld_mario) / sizeof(int); i++) {
underworld_mario_song.music[i] = underworld_mario[i];
underworld_mario_song.tempo[i] = underworld_mario_tempo[i];
if (underworld_mario_song.max_value < underworld_mario[i]) underworld_mario_song.max_value = underworld_mario[i];
if (underworld_mario_song.min_value > underworld_mario[i] && underworld_mario[i] != 0) underworld_mario_song.min_value = underworld_mario[i];
}
underworld_mario_song.velocity = 1;

Que tal?

void setup_music_values(Song_to_play *song, int song_data[], int song_size; int song_time[]; int velocity) {
       song->max_value = song_data[0];
       song->min_value = song_data[0];
       
      for (int i = 0; i < song_size; i++) {
		
		song->music[I] = song_data[i];
		song->tempo[i] = song_time[i];
		
		if (song->max_value < song_data[i]) song->max_value = song_data[i];
		if (song->min_value > song_data[i] && song_data[i] != 0) song->min_value = song_data[i];
	}
	song->velocity = velocity;	
} 	

Agora basta usar:

      setup_music_values(&mario_main_song, mario_main, sizeof(mario_main) / sizeof(int), mario_main_tempo, 0.15);

Observe que pode usar a função para todas músicas.

Vantagens:

  • Evita repetição de código (menor manutenção).
  • Evita erros (na hora de copiar e colar, alteração).
  • Quer mudar alguma configuração pra todas músicas? Basta mexer na função.
  • Facilidade de inserir/remover músicas.

Grandes vetores constantes de dados

int pirates_of_the_caribean[] = {
NOTE_E4, NOTE_G4, NOTE_A4, NOTE_A4, 0,
NOTE_A4, NOTE_B4, NOTE_C5, NOTE_C5, 0,
NOTE_C5, NOTE_D5, NOTE_B4, NOTE_B4, 0,
NOTE_A4, NOTE_G4, NOTE_A4, 0,
NOTE_E4, NOTE_G4, NOTE_A4, NOTE_A4, 0,
NOTE_A4, NOTE_B4, NOTE_C5, NOTE_C5, 0,
NOTE_C5, NOTE_D5, NOTE_B4, NOTE_B4, 0,
NOTE_A4, NOTE_G4, NOTE_A4, 0,

No arquivo musicas.h existem diversos vetores com informações constantes (uma vez definido, nunca é alterado).

Uma grande recomendação de quando trabalhamos com sistemas embarcados, e também acaba sendo uma excelente prática de programação, sempre que tivermos dados constantes que não alteram (imutáveis), declarar eles com a propriedade const.

Exemplo:

const int pirate_tempo[] = ...

Quais as vantagens para um sistema embarcado?
Bom, o nosso SAME70, é uma CPU com 2048KB de ROM e 384KB de RAM (fonte) Quando você não utiliza a propriedade const, o compilador assume, que o vetor pode ser alterado a qualquer instante, por este motivo, ele é armazenado na RAM do processador. Agora, com o const, estes dados serão armazenados na ROM! Já que eles não se alteram! Dando uma enorme economia de memória RAM.

Lembre-se que geralmente em sistemas embarcados, um dos maiores gargalos é a quantidade de memória RAM disponível (RAM = custo = aumenta preço).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.