This commit is contained in:
thomas committed 2026-10-18 14:06:40 +02:00
commit 2c2202e60d
2491 files changed
+1295990

No files matched your search

+155
View File
@@ -0,0 +1,155 @@
#include "audio_analysis.h"
#include "arm_math.h"
#include <math.h>
#include <string.h>
#define FFT_SIZE AUDIO_ANALYSIS_FFT_SIZE
#define NUM_BINS AUDIO_ANALYSIS_NUM_BINS
/* --- Capture en double buffer (ping-pong), ecrite depuis le chemin audio temps
* reel, lue depuis la tache IHM. Un seul ecrivain, un seul lecteur : pas de verrou
* necessaire, meme principe que la FIFO audio principale. --- */
static float g_capture_buf[2][FFT_SIZE];
static uint32_t g_capture_fill_idx = 0;
static uint8_t g_capture_write_buf = 0;
static volatile uint8_t g_capture_ready_buf = 0xFFU; /* 0xFF = aucun buffer complet en attente */
static bool g_analysis_enabled = false;
/* --- Fenetre precalculee (a l'init uniquement, jamais recalculee en boucle) --- */
static float g_hann_window[FFT_SIZE];
/* --- FFT reelle CMSIS-DSP : instance initialisee une fois, buffers de travail --- */
static arm_rfft_fast_instance_f32 g_rfft_instance;
static float g_fft_work[FFT_SIZE]; /* echantillons fenetres ; ecrase (scratch) par arm_rfft_fast_f32 */
static float g_fft_out[FFT_SIZE]; /* spectre complexe empaquete, format CMSIS (voir plus bas) */
static float g_magnitudes_db[NUM_BINS]; /* seule la moitie 0..Fe/2 est conservee */
static float g_peak_freq_hz = 0.0f;
static void AudioAnalysis_BuildTables(void)
{
for (uint32_t i = 0; i < FFT_SIZE; i++)
{
/* Fenetre de Hann : reduit les fuites spectrales dues a la troncature du bloc. */
g_hann_window[i] = 0.5f - 0.5f * cosf(2.0f * (float)M_PI * (float)i / (float)(FFT_SIZE - 1U));
}
}
void AudioAnalysis_Init(void)
{
memset(g_capture_buf, 0, sizeof(g_capture_buf));
g_capture_fill_idx = 0;
g_capture_write_buf = 0;
g_capture_ready_buf = 0xFFU;
g_analysis_enabled = false;
memset(g_magnitudes_db, 0, sizeof(g_magnitudes_db));
AudioAnalysis_BuildTables();
arm_rfft_fast_init_f32(&g_rfft_instance, FFT_SIZE);
}
void AudioAnalysis_PushSample(float sample)
{
if (!g_analysis_enabled)
{
return;
}
g_capture_buf[g_capture_write_buf][g_capture_fill_idx] = sample;
g_capture_fill_idx++;
if (g_capture_fill_idx >= FFT_SIZE)
{
g_capture_fill_idx = 0;
g_capture_ready_buf = g_capture_write_buf;
g_capture_write_buf = 1U - g_capture_write_buf;
}
}
bool AudioAnalysis_Update(void)
{
if (!g_analysis_enabled)
{
return false;
}
uint8_t ready = g_capture_ready_buf;
if (ready == 0xFFU)
{
return false;
}
g_capture_ready_buf = 0xFFU;
for (uint32_t i = 0; i < FFT_SIZE; i++)
{
g_fft_work[i] = g_capture_buf[ready][i] * g_hann_window[i];
}
/* arm_rfft_fast_f32 (forward, ifftFlag=0) empaquete le spectre d'un signal reel
* en NUM_BINS paires {re,im}, sauf la premiere qui contient les deux seules
* valeurs reelles (DC et Nyquist) : g_fft_out[0]=X[0] (DC), g_fft_out[1]=X[N/2]
* (Nyquist, non utilise ici). Pour k=1..NUM_BINS-1 : re=g_fft_out[2k], im=g_fft_out[2k+1]. */
arm_rfft_fast_f32(&g_rfft_instance, g_fft_work, g_fft_out, 0);
/* Magnitude normalisee (une sinusoide plein-echelle donne ~0dB) puis convertie
* en dB, avec un plancher pour eviter log(0). Destine a un affichage visuel,
* pas a une mesure calibree. Seule la moitie 0..Fe/2 du spectre est conservee :
* le spectre d'un signal reel est symetrique, la seconde moitie n'apporte rien. */
/* Recherche du pic en meme temps que le calcul des magnitudes. Le bin 0 (continu,
* 0Hz) est ignore : une composante DC ne doit pas etre rapportee comme "frequence
* dominante". */
uint32_t peak_bin = 1U;
float peak_mag = 0.0f;
for (uint32_t i = 0; i < NUM_BINS; i++)
{
float re = (i == 0U) ? g_fft_out[0] : g_fft_out[2U * i];
float im = (i == 0U) ? 0.0f : g_fft_out[2U * i + 1U];
float mag = sqrtf(re * re + im * im) / ((float)FFT_SIZE / 4.0f);
if (i >= 1U && mag > peak_mag)
{
peak_mag = mag;
peak_bin = i;
}
if (mag < 1.0e-6f)
{
mag = 1.0e-6f;
}
g_magnitudes_db[i] = 20.0f * log10f(mag);
}
g_peak_freq_hz = (float)peak_bin * (float)AUDIO_ANALYSIS_SAMPLE_RATE_HZ / (float)FFT_SIZE;
return true;
}
const float *AudioAnalysis_GetMagnitudesDb(void)
{
return g_magnitudes_db;
}
float AudioAnalysis_GetPeakFrequencyHz(void)
{
return g_peak_freq_hz;
}
void AudioAnalysis_SetEnabled(bool enabled)
{
if (enabled && !g_analysis_enabled)
{
/* Redemarre une capture propre a chaque activation. */
g_capture_fill_idx = 0;
g_capture_write_buf = 0;
g_capture_ready_buf = 0xFFU;
}
g_analysis_enabled = enabled;
}
bool AudioAnalysis_IsEnabled(void)
{
return g_analysis_enabled;
}
+47
View File
@@ -0,0 +1,47 @@
#include "audio_effects.h"
static AudioEffectsParams g_params;
static FxOctaverState g_octaverState;
static FxEqualizerState g_eqState;
static FxOverdriveState g_overdriveState;
static FxSaturationState g_saturationState;
static FxEchoState g_echoState;
static FxReverbState g_reverbState;
void AudioEffects_Init(void)
{
g_params.audio_on_off = false;
g_params.master_volume = 0.0f;
FxOctaver_Init(&g_octaverState, &g_params.octaver);
FxEqualizer_Init(&g_eqState, &g_params.equalizer);
FxOverdrive_Init(&g_overdriveState, &g_params.overdrive);
FxSaturation_Init(&g_saturationState, &g_params.saturation);
FxEcho_Init(&g_echoState, &g_params.echo);
FxReverb_Init(&g_reverbState, &g_params.reverb);
}
float AudioEffects_Process(float input)
{
float sample = input;
sample = FxOctaver_Process(&g_octaverState, &g_params.octaver, sample);
sample = FxEqualizer_Process(&g_eqState, &g_params.equalizer, sample);
sample = FxOverdrive_Process(&g_overdriveState, &g_params.overdrive, sample);
sample = FxSaturation_Process(&g_saturationState, &g_params.saturation, sample);
sample = FxEcho_Process(&g_echoState, &g_params.echo, sample);
sample = FxReverb_Process(&g_reverbState, &g_params.reverb, sample);
/* Coupure de sortie : les effets continuent de tourner (pas de discontinuite
* d'etat au reactivation), seule la sortie audible est reduite au silence. */
if (!g_params.audio_on_off)
{
return 0.0f;
}
return sample * g_params.master_volume;
}
AudioEffectsParams *AudioEffects_GetParams(void)
{
return &g_params;
}
+89
View File
@@ -0,0 +1,89 @@
#include "audio_looper.h"
/* 5s a 48kHz en float = 937.5 Ko : ne rentre pas en RAM interne, place en EXTRAM (meme
* section/region que le framebuffer TouchGFX, cf. AudioLooperBuffer dans le script de
* link). Accede uniquement par ce coeur (pas de DMA dessus) : pas de probleme de
* coherence de cache a gerer explicitement. */
__attribute__((section("AudioLooperBuffer")))
static float g_buffer[AUDIO_LOOPER_MAX_SAMPLES];
typedef enum
{
LOOPER_IDLE = 0,
LOOPER_RECORDING,
LOOPER_PLAYBACK
} LooperState;
/* g_state est ecrit depuis la tache IHM (Start/Stop) et lu/ecrit depuis le contexte
* audio temps reel (Process) : meme principe "un seul ecrivain a la fois par variable,
* volatile pour le flag d'etat partage" que le reste du projet (cf. audio_analysis.c). */
static volatile LooperState g_state = LOOPER_IDLE;
static uint32_t g_record_len = 0; /* nb d'echantillons valides captures, fige au relachement */
static uint32_t g_write_idx = 0; /* ecrit uniquement depuis Process() en RECORDING */
static float g_read_pos = 0.0f; /* lu/ecrit uniquement depuis Process() en PLAYBACK */
void AudioLooper_Init(void)
{
g_state = LOOPER_IDLE;
g_record_len = 0;
g_write_idx = 0;
g_read_pos = 0.0f;
}
void AudioLooper_StartRecording(void)
{
g_write_idx = 0;
g_state = LOOPER_RECORDING;
}
void AudioLooper_StopRecordingAndPlay(void)
{
if (g_state != LOOPER_RECORDING)
{
return;
}
g_record_len = g_write_idx;
g_read_pos = 0.0f;
g_state = (g_record_len > 0U) ? LOOPER_PLAYBACK : LOOPER_IDLE;
}
float AudioLooper_Process(float sample_in)
{
switch (g_state)
{
case LOOPER_RECORDING:
if (g_write_idx < AUDIO_LOOPER_MAX_SAMPLES)
{
g_buffer[g_write_idx++] = sample_in;
}
/* Buffer plein (5s atteintes) : on cesse de capturer mais on reste en
* enregistrement, l'ecoute live continue jusqu'au relachement du bouton. */
return sample_in;
case LOOPER_PLAYBACK:
{
uint32_t idx0 = (uint32_t)g_read_pos;
if (idx0 >= g_record_len - 1U)
{
g_state = LOOPER_IDLE;
return sample_in;
}
/* Interpolation lineaire entre les deux echantillons encadrant la position de
* lecture fractionnaire : necessaire car AUDIO_LOOPER_PLAYBACK_RATIO avance le
* pointeur de lecture plus vite qu'un pas entier. */
float frac = g_read_pos - (float)idx0;
float s0 = g_buffer[idx0];
float s1 = g_buffer[idx0 + 1U];
float out = s0 + (s1 - s0) * frac;
g_read_pos += AUDIO_LOOPER_PLAYBACK_RATIO;
return out;
}
case LOOPER_IDLE:
default:
return sample_in;
}
}
+79
View File
@@ -0,0 +1,79 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* File Name : freertos.c
* Description : Code for freertos applications
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */
/* USER CODE END Variables */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */
extern portBASE_TYPE IdleTaskHook(void* p);
/* USER CODE END FunctionPrototypes */
/* Hook prototypes */
void vApplicationIdleHook(void);
/* USER CODE BEGIN 2 */
void vApplicationIdleHook( void )
{
/* vApplicationIdleHook() will only be called if configUSE_IDLE_HOOK is set
to 1 in FreeRTOSConfig.h. It will be called on each iteration of the idle
task. It is essential that code added to this hook function never attempts
to block in any way (for example, call xQueueReceive() with a block time
specified, or call vTaskDelay()). If the application makes use of the
vTaskDelete() API function (as this demo application does) then it is also
important that vApplicationIdleHook() is permitted to return to its calling
function, because it is the responsibility of the idle task to clean up
memory allocated by the kernel to any task that has since been deleted. */
vTaskSetApplicationTaskTag(NULL, IdleTaskHook);
}
/* USER CODE END 2 */
/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */
/* USER CODE END Application */
+38
View File
@@ -0,0 +1,38 @@
#include "fx_echo.h"
#include <string.h>
void FxEcho_Init(FxEchoState *state, FxEchoParams *params)
{
memset(state->buffer, 0, sizeof(state->buffer));
state->write_idx = 0;
params->enabled = false;
params->delay_ms = 300.0f;
params->feedback = 0.35f;
params->mix = 0.3f;
}
float FxEcho_Process(FxEchoState *state, const FxEchoParams *params, float input)
{
if (!params->enabled)
{
return input;
}
uint32_t delay_samples = (uint32_t)(params->delay_ms * (FX_ECHO_SAMPLE_RATE / 1000.0f));
if (delay_samples >= FX_ECHO_BUFFER_SIZE)
{
delay_samples = FX_ECHO_BUFFER_SIZE - 1U;
}
uint32_t read_idx = (state->write_idx + FX_ECHO_BUFFER_SIZE - delay_samples) % FX_ECHO_BUFFER_SIZE;
float delayed = (float)state->buffer[read_idx] / 32768.0f;
float to_store = input + delayed * params->feedback;
if (to_store > 1.0f) to_store = 1.0f;
if (to_store < -1.0f) to_store = -1.0f;
state->buffer[state->write_idx] = (int16_t)(to_store * 32767.0f);
state->write_idx = (state->write_idx + 1U) % FX_ECHO_BUFFER_SIZE;
return input * (1.0f - params->mix) + delayed * params->mix;
}
+82
View File
@@ -0,0 +1,82 @@
#include "fx_equalizer.h"
#include <math.h>
#include <stdint.h>
#define FX_EQ_SAMPLE_RATE 48000.0f
static const float fx_eq_default_freqs[FX_EQ_NUM_BANDS] =
{
31.0f, 62.0f, 125.0f, 250.0f, 500.0f, 1000.0f, 2000.0f, 4000.0f, 8000.0f, 16000.0f
};
void FxEqualizer_Init(FxEqualizerState *state, FxEqualizerParams *params)
{
params->enabled = true;
for (uint32_t i = 0; i < FX_EQ_NUM_BANDS; i++)
{
params->bands[i].freq_hz = fx_eq_default_freqs[i];
params->bands[i].gain_db = 0.0f;
params->bands[i].q = 1.0f;
state->band_state[i].last_freq_hz = -1.0f; /* force le calcul des coefficients au 1er sample */
state->band_state[i].last_gain_db = 0.0f;
state->band_state[i].last_q = 0.0f;
state->x1[i] = state->x2[i] = state->y1[i] = state->y2[i] = 0.0f;
}
// Pour couper les basses par defaukt et éviter les larsens :
params->bands[0].gain_db = -15.0f;
params->bands[1].gain_db = -10.0f;
params->bands[2].gain_db = -2.5f;
}
/* Filtre "peaking EQ" (cloche), formule de l'Audio EQ Cookbook (Robert Bristow-Johnson). */
static void FxEq_ComputeBandCoeffs(FxEqBandState *bs, const FxEqBand *band)
{
float A = powf(10.0f, band->gain_db / 40.0f);
float w0 = 2.0f * (float)M_PI * band->freq_hz / FX_EQ_SAMPLE_RATE;
float alpha = sinf(w0) / (2.0f * band->q);
float cosw0 = cosf(w0);
float a0 = 1.0f + alpha / A;
bs->b0 = (1.0f + alpha * A) / a0;
bs->b1 = (-2.0f * cosw0) / a0;
bs->b2 = (1.0f - alpha * A) / a0;
bs->a1 = (-2.0f * cosw0) / a0;
bs->a2 = (1.0f - alpha / A) / a0;
bs->last_freq_hz = band->freq_hz;
bs->last_gain_db = band->gain_db;
bs->last_q = band->q;
}
float FxEqualizer_Process(FxEqualizerState *state, const FxEqualizerParams *params, float input)
{
if (!params->enabled)
{
return input;
}
float y = input;
for (uint32_t i = 0; i < FX_EQ_NUM_BANDS; i++)
{
const FxEqBand *band = &params->bands[i];
FxEqBandState *bs = &state->band_state[i];
if (band->freq_hz != bs->last_freq_hz || band->gain_db != bs->last_gain_db || band->q != bs->last_q)
{
FxEq_ComputeBandCoeffs(bs, band);
}
float x = y;
y = bs->b0 * x + bs->b1 * state->x1[i] + bs->b2 * state->x2[i]
- bs->a1 * state->y1[i] - bs->a2 * state->y2[i];
state->x2[i] = state->x1[i];
state->x1[i] = x;
state->y2[i] = state->y1[i];
state->y1[i] = y;
}
return y;
}
+147
View File
@@ -0,0 +1,147 @@
#include "fx_octaver.h"
#include <math.h>
#define FX_OCTAVER_BUFFER_MASK (FX_OCTAVER_BUFFER_SIZE - 1U)
#define FX_OCTAVER_ENV_TABLE_SIZE 256U
/* Rapport de vitesse de lecture pour chaque voix : lire le buffer plus vite que
* l'ecriture multiplie la frequence (octave au-dessus), plus lentement la divise
* (octave en-dessous). */
static const float fx_octaver_ratios[FX_OCTAVER_NUM_VOICES] =
{
0.25f, /* -2 octaves */
0.5f, /* -1 octave */
2.0f, /* +1 octave */
4.0f /* +2 octaves */
};
/* Fenetre de Hann tabulee (evite un cosf() par grain et par echantillon). */
static float fx_octaver_env_table[FX_OCTAVER_ENV_TABLE_SIZE + 1U];
static bool fx_octaver_env_table_ready = false;
static void FxOctaver_BuildEnvTable(void)
{
if (fx_octaver_env_table_ready)
{
return;
}
for (uint32_t i = 0; i <= FX_OCTAVER_ENV_TABLE_SIZE; i++)
{
float phase = (float)i / (float)FX_OCTAVER_ENV_TABLE_SIZE;
fx_octaver_env_table[i] = 0.5f - 0.5f * cosf(2.0f * (float)M_PI * phase);
}
fx_octaver_env_table_ready = true;
}
static inline float FxOctaver_EnvLookup(float phase)
{
float pos = phase * (float)FX_OCTAVER_ENV_TABLE_SIZE;
uint32_t i0 = (uint32_t)pos;
if (i0 >= FX_OCTAVER_ENV_TABLE_SIZE)
{
i0 = FX_OCTAVER_ENV_TABLE_SIZE - 1U;
}
float frac = pos - (float)i0;
return fx_octaver_env_table[i0] * (1.0f - frac) + fx_octaver_env_table[i0 + 1U] * frac;
}
static inline float FxOctaver_ReadInterpolated(const float *buffer, uint32_t write_idx, float delay)
{
/* write_idx grandit sans jamais etre replie (compteur perpetuel) ; le convertir
* directement en float finirait par perdre en precision (un float ne represente
* exactement les entiers que jusqu'a ~16.7 millions, soit quelques minutes a
* 48kHz). On calcule donc la position de lecture uniquement a partir de l'index
* DEJA REPLIE dans le buffer, qui reste toujours petit. */
float write_pos = (float)(write_idx & FX_OCTAVER_BUFFER_MASK);
float read_pos = write_pos - delay;
while (read_pos < 0.0f)
{
read_pos += (float)FX_OCTAVER_BUFFER_SIZE;
}
uint32_t i0 = (uint32_t)read_pos & FX_OCTAVER_BUFFER_MASK;
uint32_t i1 = (i0 + 1U) & FX_OCTAVER_BUFFER_MASK;
float frac = read_pos - (float)(uint32_t)read_pos;
return buffer[i0] * (1.0f - frac) + buffer[i1] * frac;
}
/* Lecteur de grains a deux pointeurs en fondu croise : chaque pointeur avance
* (ou recule) dans le buffer a une vitesse "ratio" differente de celle de
* l'ecriture, ce qui change la hauteur percue. Les deux grains sont toujours
* en opposition de phase exacte (decales d'un demi-grain a l'origine, et le
* meme increment est applique aux deux avant chaque repli) : la fenetre de
* Hann du second grain vaut donc toujours 1 moins celle du premier, ce qui
* garantit un niveau de sortie constant pendant le fondu et evite un second
* calcul de fenetre. */
static float FxOctaver_ProcessVoice(FxOctaverVoiceState *vs, const float *buffer, uint32_t write_idx, float ratio)
{
float step = 1.0f - ratio;
for (uint32_t g = 0; g < 2U; g++)
{
vs->delay[g] += step;
if (vs->delay[g] >= (float)FX_OCTAVER_GRAIN_SIZE)
{
vs->delay[g] -= (float)FX_OCTAVER_GRAIN_SIZE;
}
else if (vs->delay[g] < 0.0f)
{
vs->delay[g] += (float)FX_OCTAVER_GRAIN_SIZE;
}
}
float phase0 = vs->delay[0] / (float)FX_OCTAVER_GRAIN_SIZE;
float env0 = FxOctaver_EnvLookup(phase0);
float env1 = 1.0f - env0;
float sample0 = FxOctaver_ReadInterpolated(buffer, write_idx, vs->delay[0]);
float sample1 = FxOctaver_ReadInterpolated(buffer, write_idx, vs->delay[1]);
return env0 * sample0 + env1 * sample1;
}
void FxOctaver_Init(FxOctaverState *state, FxOctaverParams *params)
{
params->enabled = false;
params->level_down2 = 0.0f;
params->level_down1 = 0.0f;
params->level_dry = 1.0f;
params->level_up1 = 0.0f;
params->level_up2 = 0.0f;
for (uint32_t i = 0; i < FX_OCTAVER_BUFFER_SIZE; i++)
{
state->buffer[i] = 0.0f;
}
state->write_idx = 0U;
for (uint32_t v = 0; v < FX_OCTAVER_NUM_VOICES; v++)
{
state->voices[v].delay[0] = 0.0f;
state->voices[v].delay[1] = (float)FX_OCTAVER_GRAIN_SIZE * 0.5f;
}
FxOctaver_BuildEnvTable();
}
float FxOctaver_Process(FxOctaverState *state, const FxOctaverParams *params, float input)
{
if (!params->enabled)
{
return input;
}
state->buffer[state->write_idx & FX_OCTAVER_BUFFER_MASK] = input;
float down2 = FxOctaver_ProcessVoice(&state->voices[0], state->buffer, state->write_idx, fx_octaver_ratios[0]);
float down1 = FxOctaver_ProcessVoice(&state->voices[1], state->buffer, state->write_idx, fx_octaver_ratios[1]);
float up1 = FxOctaver_ProcessVoice(&state->voices[2], state->buffer, state->write_idx, fx_octaver_ratios[2]);
float up2 = FxOctaver_ProcessVoice(&state->voices[3], state->buffer, state->write_idx, fx_octaver_ratios[3]);
state->write_idx++;
return input * params->level_dry
+ down2 * params->level_down2
+ down1 * params->level_down1
+ up1 * params->level_up1
+ up2 * params->level_up2;
}
+39
View File
@@ -0,0 +1,39 @@
#include "fx_overdrive.h"
#include <math.h>
void FxOverdrive_Init(FxOverdriveState *state, FxOverdriveParams *params)
{
state->tone_lp_state = 0.0f;
params->enabled = false;
params->drive = 0.4f;
params->tone = 0.6f;
params->level = 0.7f;
}
float FxOverdrive_Process(FxOverdriveState *state, const FxOverdriveParams *params, float input)
{
if (!params->enabled)
{
return input;
}
float driven = input * (1.0f + params->drive * 20.0f);
/* Ecretage asymetrique (exponentiel) : plus caracteristique/agressif qu'un tanh symetrique. */
float shaped;
if (driven >= 0.0f)
{
shaped = 1.0f - expf(-driven);
}
else
{
shaped = -1.0f + expf(driven);
}
/* Filtre passe-bas une pole pour la tonalite : coefficient = tone (0..1). */
float coeff = 0.05f + params->tone * 0.9f;
state->tone_lp_state += coeff * (shaped - state->tone_lp_state);
return state->tone_lp_state * params->level;
}
+114
View File
@@ -0,0 +1,114 @@
#include "fx_reverb.h"
#include <string.h>
/* Lignes a retard inspirees de Freeverb (Jezar), redimensionnees de 44.1kHz vers 48kHz. */
#define FX_REVERB_COMB0 1215U
#define FX_REVERB_COMB1 1293U
#define FX_REVERB_COMB2 1390U
#define FX_REVERB_COMB3 1476U
#define FX_REVERB_COMB4 1548U
#define FX_REVERB_COMB5 1623U
#define FX_REVERB_COMB6 1695U
#define FX_REVERB_COMB7 1761U
#define FX_REVERB_ALLPASS0 605U
#define FX_REVERB_ALLPASS1 480U
#define FX_REVERB_ALLPASS2 371U
#define FX_REVERB_ALLPASS3 245U
static float fx_reverb_comb_buf0[FX_REVERB_COMB0];
static float fx_reverb_comb_buf1[FX_REVERB_COMB1];
static float fx_reverb_comb_buf2[FX_REVERB_COMB2];
static float fx_reverb_comb_buf3[FX_REVERB_COMB3];
static float fx_reverb_comb_buf4[FX_REVERB_COMB4];
static float fx_reverb_comb_buf5[FX_REVERB_COMB5];
static float fx_reverb_comb_buf6[FX_REVERB_COMB6];
static float fx_reverb_comb_buf7[FX_REVERB_COMB7];
static float fx_reverb_allpass_buf0[FX_REVERB_ALLPASS0];
static float fx_reverb_allpass_buf1[FX_REVERB_ALLPASS1];
static float fx_reverb_allpass_buf2[FX_REVERB_ALLPASS2];
static float fx_reverb_allpass_buf3[FX_REVERB_ALLPASS3];
static float FxComb_Process(FxCombState *c, float input, float feedback, float damp1, float damp2)
{
float output = c->buffer[c->idx];
c->filter_store = (output * damp2) + (c->filter_store * damp1);
c->buffer[c->idx] = input + (c->filter_store * feedback);
c->idx = (c->idx + 1U) % c->size;
return output;
}
static float FxAllpass_Process(FxAllpassState *a, float input, float feedback)
{
float buf_out = a->buffer[a->idx];
float output = -input + buf_out;
a->buffer[a->idx] = input + buf_out * feedback;
a->idx = (a->idx + 1U) % a->size;
return output;
}
void FxReverb_Init(FxReverbState *state, FxReverbParams *params)
{
params->enabled = false;
params->room_size = 0.5f;
params->damping = 0.5f;
params->mix = 0.3f;
float *comb_buffers[FX_REVERB_NUM_COMBS] = {
fx_reverb_comb_buf0, fx_reverb_comb_buf1, fx_reverb_comb_buf2, fx_reverb_comb_buf3,
fx_reverb_comb_buf4, fx_reverb_comb_buf5, fx_reverb_comb_buf6, fx_reverb_comb_buf7
};
uint32_t comb_sizes[FX_REVERB_NUM_COMBS] = {
FX_REVERB_COMB0, FX_REVERB_COMB1, FX_REVERB_COMB2, FX_REVERB_COMB3,
FX_REVERB_COMB4, FX_REVERB_COMB5, FX_REVERB_COMB6, FX_REVERB_COMB7
};
for (uint32_t i = 0; i < FX_REVERB_NUM_COMBS; i++)
{
state->combs[i].buffer = comb_buffers[i];
state->combs[i].size = comb_sizes[i];
state->combs[i].idx = 0;
state->combs[i].filter_store = 0.0f;
memset(comb_buffers[i], 0, comb_sizes[i] * sizeof(float));
}
float *allpass_buffers[FX_REVERB_NUM_ALLPASS] = {
fx_reverb_allpass_buf0, fx_reverb_allpass_buf1, fx_reverb_allpass_buf2, fx_reverb_allpass_buf3
};
uint32_t allpass_sizes[FX_REVERB_NUM_ALLPASS] = {
FX_REVERB_ALLPASS0, FX_REVERB_ALLPASS1, FX_REVERB_ALLPASS2, FX_REVERB_ALLPASS3
};
for (uint32_t i = 0; i < FX_REVERB_NUM_ALLPASS; i++)
{
state->allpass[i].buffer = allpass_buffers[i];
state->allpass[i].size = allpass_sizes[i];
state->allpass[i].idx = 0;
memset(allpass_buffers[i], 0, allpass_sizes[i] * sizeof(float));
}
}
float FxReverb_Process(FxReverbState *state, const FxReverbParams *params, float input)
{
if (!params->enabled)
{
return input;
}
float feedback = 0.28f + params->room_size * 0.7f;
float damp1 = params->damping * 0.4f;
float damp2 = 1.0f - damp1;
float out = 0.0f;
for (uint32_t i = 0; i < FX_REVERB_NUM_COMBS; i++)
{
out += FxComb_Process(&state->combs[i], input, feedback, damp1, damp2);
}
out /= (float)FX_REVERB_NUM_COMBS;
for (uint32_t i = 0; i < FX_REVERB_NUM_ALLPASS; i++)
{
out = FxAllpass_Process(&state->allpass[i], out, 0.5f);
}
return input * (1.0f - params->mix) + out * params->mix;
}
+32
View File
@@ -0,0 +1,32 @@
#include "fx_saturation.h"
#include <math.h>
#define FX_SATURATION_DC_BLOCK_R 0.995f
void FxSaturation_Init(FxSaturationState *state, FxSaturationParams *params)
{
state->dc_block_x1 = 0.0f;
state->dc_block_y1 = 0.0f;
params->enabled = false;
params->drive = 0.3f;
params->level = 0.8f;
}
float FxSaturation_Process(FxSaturationState *state, const FxSaturationParams *params, float input)
{
if (!params->enabled)
{
return input;
}
float driven = input * (1.0f + params->drive * 12.0f);
float shaped = tanhf(driven);
/* Le tanh sur un signal non symetrique introduit un leger DC : filtre bloqueur de DC. */
float y = shaped - state->dc_block_x1 + FX_SATURATION_DC_BLOCK_R * state->dc_block_y1;
state->dc_block_x1 = shaped;
state->dc_block_y1 = y;
return y * params->level;
}
File diff suppressed because it is too large. Load diff
+803
View File
@@ -0,0 +1,803 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32h7rsxx_hal_msp.c
* @brief This file provides code for the MSP Initialization
* and de-Initialization codes.
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
extern DMA_NodeTypeDef Node_GPDMA1_Channel0;
extern DMA_QListTypeDef List_GPDMA1_Channel0;
extern DMA_HandleTypeDef handle_GPDMA1_Channel0;
extern DMA_HandleTypeDef handle_HPDMA1_Channel1;
extern DMA_HandleTypeDef handle_HPDMA1_Channel0;
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN TD */
/* USER CODE END TD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN Define */
/* USER CODE END Define */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN Macro */
/* USER CODE END Macro */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* External functions --------------------------------------------------------*/
/* USER CODE BEGIN ExternalFunctions */
/* USER CODE END ExternalFunctions */
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* Initializes the Global MSP.
*/
void HAL_MspInit(void)
{
/* USER CODE BEGIN MspInit 0 */
/* USER CODE END MspInit 0 */
/* System interrupt init*/
/* PendSV_IRQn interrupt configuration */
HAL_NVIC_SetPriority(PendSV_IRQn, 15, 0);
/* USER CODE BEGIN MspInit 1 */
/* USER CODE END MspInit 1 */
}
/**
* @brief MDF MSP Initialization
* This function configures the hardware resources used in this example
* @param hmdf: MDF handle pointer
* @retval None
*/
void HAL_MDF_MspInit(MDF_HandleTypeDef* hmdf)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
DMA_NodeConfTypeDef NodeConfig;
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
if(IS_MDF_ALL_INSTANCE(hmdf->Instance))
{
/* USER CODE BEGIN ADF1_MspInit 0 */
/* USER CODE END ADF1_MspInit 0 */
/** Initializes the peripherals clock
*/
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADF1;
PeriphClkInit.Adf1ClockSelection = RCC_ADF1CLKSOURCE_PLL2P;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
/* Peripheral clock enable */
__HAL_RCC_ADF1_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
/**ADF1 GPIO Configuration
PE2 ------> ADF1_CCK0
PD6 ------> ADF1_SDI0
*/
GPIO_InitStruct.Pin = ADF1_CK_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; // était LOW : bien trop lent pour piloter proprement une horloge à 6-12MHz+ vers le micro PDM
GPIO_InitStruct.Alternate = GPIO_AF1_ADF1;
HAL_GPIO_Init(ADF1_CK_GPIO_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = ADF1_D_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF3_ADF1;
HAL_GPIO_Init(ADF1_D_GPIO_Port, &GPIO_InitStruct);
/* ADF1 DMA Init */
/* GPDMA1_REQUEST_ADF1_FLT0 Init */
NodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;
NodeConfig.Init.Request = GPDMA1_REQUEST_ADF1_FLT0;
NodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
NodeConfig.Init.Direction = DMA_PERIPH_TO_MEMORY;
NodeConfig.Init.SrcInc = DMA_SINC_FIXED;
NodeConfig.Init.DestInc = DMA_DINC_INCREMENTED;
NodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_WORD;
NodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_WORD;
NodeConfig.Init.SrcBurstLength = 1;
NodeConfig.Init.DestBurstLength = 1;
NodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT1;
NodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
NodeConfig.Init.Mode = DMA_NORMAL;
NodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;
NodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
NodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;
if (HAL_DMAEx_List_BuildNode(&NodeConfig, &Node_GPDMA1_Channel0) != HAL_OK)
{
Error_Handler();
}
if (HAL_DMAEx_List_InsertNode(&List_GPDMA1_Channel0, NULL, &Node_GPDMA1_Channel0) != HAL_OK)
{
Error_Handler();
}
if (HAL_DMAEx_List_SetCircularMode(&List_GPDMA1_Channel0) != HAL_OK)
{
Error_Handler();
}
handle_GPDMA1_Channel0.Instance = GPDMA1_Channel0;
handle_GPDMA1_Channel0.InitLinkedList.Priority = DMA_HIGH_PRIORITY;
handle_GPDMA1_Channel0.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;
handle_GPDMA1_Channel0.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT1;
handle_GPDMA1_Channel0.InitLinkedList.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
handle_GPDMA1_Channel0.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;
if (HAL_DMAEx_List_Init(&handle_GPDMA1_Channel0) != HAL_OK)
{
Error_Handler();
}
if (HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel0, &List_GPDMA1_Channel0) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(hmdf, hdma, handle_GPDMA1_Channel0);
if (HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel0, DMA_CHANNEL_NPRIV) != HAL_OK)
{
Error_Handler();
}
/* ADF1 interrupt Init */
HAL_NVIC_SetPriority(ADF1_FLT0_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(ADF1_FLT0_IRQn);
/* USER CODE BEGIN ADF1_MspInit 1 */
/* USER CODE END ADF1_MspInit 1 */
}
}
/**
* @brief MDF MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param hmdf: MDF handle pointer
* @retval None
*/
void HAL_MDF_MspDeInit(MDF_HandleTypeDef* hmdf)
{
if(IS_MDF_ALL_INSTANCE(hmdf->Instance))
{
/* USER CODE BEGIN ADF1_MspDeInit 0 */
/* USER CODE END ADF1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_ADF1_CLK_DISABLE();
/**ADF1 GPIO Configuration
PE2 ------> ADF1_CCK0
PD6 ------> ADF1_SDI0
*/
HAL_GPIO_DeInit(ADF1_CK_GPIO_Port, ADF1_CK_Pin);
HAL_GPIO_DeInit(ADF1_D_GPIO_Port, ADF1_D_Pin);
/* ADF1 DMA DeInit */
HAL_DMA_DeInit(hmdf->hdma);
/* ADF1 interrupt DeInit */
HAL_NVIC_DisableIRQ(ADF1_FLT0_IRQn);
/* USER CODE BEGIN ADF1_MspDeInit 1 */
/* USER CODE END ADF1_MspDeInit 1 */
}
}
/**
* @brief CRC MSP Initialization
* This function configures the hardware resources used in this example
* @param hcrc: CRC handle pointer
* @retval None
*/
void HAL_CRC_MspInit(CRC_HandleTypeDef* hcrc)
{
if(hcrc->Instance==CRC)
{
/* USER CODE BEGIN CRC_MspInit 0 */
/* USER CODE END CRC_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_CRC_CLK_ENABLE();
/* USER CODE BEGIN CRC_MspInit 1 */
/* USER CODE END CRC_MspInit 1 */
}
}
/**
* @brief CRC MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param hcrc: CRC handle pointer
* @retval None
*/
void HAL_CRC_MspDeInit(CRC_HandleTypeDef* hcrc)
{
if(hcrc->Instance==CRC)
{
/* USER CODE BEGIN CRC_MspDeInit 0 */
/* USER CODE END CRC_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_CRC_CLK_DISABLE();
/* USER CODE BEGIN CRC_MspDeInit 1 */
/* USER CODE END CRC_MspDeInit 1 */
}
}
/**
* @brief DMA2D MSP Initialization
* This function configures the hardware resources used in this example
* @param hdma2d: DMA2D handle pointer
* @retval None
*/
void HAL_DMA2D_MspInit(DMA2D_HandleTypeDef* hdma2d)
{
if(hdma2d->Instance==DMA2D)
{
/* USER CODE BEGIN DMA2D_MspInit 0 */
/* USER CODE END DMA2D_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_DMA2D_CLK_ENABLE();
/* DMA2D interrupt Init */
HAL_NVIC_SetPriority(DMA2D_IRQn, 5, 0);
/* USER CODE BEGIN DMA2D_MspInit 1 */
/* USER CODE END DMA2D_MspInit 1 */
}
}
/**
* @brief DMA2D MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param hdma2d: DMA2D handle pointer
* @retval None
*/
void HAL_DMA2D_MspDeInit(DMA2D_HandleTypeDef* hdma2d)
{
if(hdma2d->Instance==DMA2D)
{
/* USER CODE BEGIN DMA2D_MspDeInit 0 */
/* USER CODE END DMA2D_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_DMA2D_CLK_DISABLE();
/* DMA2D interrupt DeInit */
HAL_NVIC_DisableIRQ(DMA2D_IRQn);
/* USER CODE BEGIN DMA2D_MspDeInit 1 */
/* USER CODE END DMA2D_MspDeInit 1 */
}
}
/**
* @brief GPU2D MSP Initialization
* This function configures the hardware resources used in this example
* @param hgpu2d: GPU2D handle pointer
* @retval None
*/
void HAL_GPU2D_MspInit(GPU2D_HandleTypeDef* hgpu2d)
{
if(hgpu2d->Instance==GPU2D)
{
/* USER CODE BEGIN GPU2D_MspInit 0 */
/* USER CODE END GPU2D_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_GPU2D_CLK_ENABLE();
/* GPU2D interrupt Init */
HAL_NVIC_SetPriority(GPU2D_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(GPU2D_IRQn);
HAL_NVIC_SetPriority(GPU2D_ER_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(GPU2D_ER_IRQn);
/* USER CODE BEGIN GPU2D_MspInit 1 */
/* USER CODE END GPU2D_MspInit 1 */
}
}
/**
* @brief GPU2D MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param hgpu2d: GPU2D handle pointer
* @retval None
*/
void HAL_GPU2D_MspDeInit(GPU2D_HandleTypeDef* hgpu2d)
{
if(hgpu2d->Instance==GPU2D)
{
/* USER CODE BEGIN GPU2D_MspDeInit 0 */
/* USER CODE END GPU2D_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_GPU2D_CLK_DISABLE();
/* GPU2D interrupt DeInit */
HAL_NVIC_DisableIRQ(GPU2D_IRQn);
HAL_NVIC_DisableIRQ(GPU2D_ER_IRQn);
/* USER CODE BEGIN GPU2D_MspDeInit 1 */
/* USER CODE END GPU2D_MspDeInit 1 */
}
}
/**
* @brief I2C MSP Initialization
* This function configures the hardware resources used in this example
* @param hi2c: I2C handle pointer
* @retval None
*/
void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
if(hi2c->Instance==I2C1)
{
/* USER CODE BEGIN I2C1_MspInit 0 */
/* USER CODE END I2C1_MspInit 0 */
/** Initializes the peripherals clock
*/
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_I2C1_I3C1;
PeriphClkInit.I2c1_I3c1ClockSelection = RCC_I2C1_I3C1CLKSOURCE_PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
__HAL_RCC_GPIOB_CLK_ENABLE();
/**I2C1 GPIO Configuration
PB9 ------> I2C1_SDA
PB6 ------> I2C1_SCL
*/
GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* Peripheral clock enable */
__HAL_RCC_I2C1_CLK_ENABLE();
/* USER CODE BEGIN I2C1_MspInit 1 */
/* USER CODE END I2C1_MspInit 1 */
}
}
/**
* @brief I2C MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param hi2c: I2C handle pointer
* @retval None
*/
void HAL_I2C_MspDeInit(I2C_HandleTypeDef* hi2c)
{
if(hi2c->Instance==I2C1)
{
/* USER CODE BEGIN I2C1_MspDeInit 0 */
/* USER CODE END I2C1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_I2C1_CLK_DISABLE();
/**I2C1 GPIO Configuration
PB9 ------> I2C1_SDA
PB6 ------> I2C1_SCL
*/
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_9);
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_6);
/* USER CODE BEGIN I2C1_MspDeInit 1 */
/* USER CODE END I2C1_MspDeInit 1 */
}
}
/**
* @brief JPEG MSP Initialization
* This function configures the hardware resources used in this example
* @param hjpeg: JPEG handle pointer
* @retval None
*/
void HAL_JPEG_MspInit(JPEG_HandleTypeDef* hjpeg)
{
DMA_DataHandlingConfTypeDef DataHandlingConfig;
if(hjpeg->Instance==JPEG)
{
/* USER CODE BEGIN JPEG_MspInit 0 */
/* USER CODE END JPEG_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_JPEG_CLK_ENABLE();
/* JPEG DMA Init */
/* HPDMA1_REQUEST_JPEG_TX Init */
handle_HPDMA1_Channel1.Instance = HPDMA1_Channel1;
handle_HPDMA1_Channel1.Init.Request = HPDMA1_REQUEST_JPEG_TX;
handle_HPDMA1_Channel1.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
handle_HPDMA1_Channel1.Init.Direction = DMA_PERIPH_TO_MEMORY;
handle_HPDMA1_Channel1.Init.SrcInc = DMA_SINC_FIXED;
handle_HPDMA1_Channel1.Init.DestInc = DMA_DINC_INCREMENTED;
handle_HPDMA1_Channel1.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_WORD;
handle_HPDMA1_Channel1.Init.DestDataWidth = DMA_DEST_DATAWIDTH_WORD;
handle_HPDMA1_Channel1.Init.Priority = DMA_HIGH_PRIORITY;
handle_HPDMA1_Channel1.Init.SrcBurstLength = 8;
handle_HPDMA1_Channel1.Init.DestBurstLength = 8;
handle_HPDMA1_Channel1.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT1|DMA_DEST_ALLOCATED_PORT0;
handle_HPDMA1_Channel1.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
handle_HPDMA1_Channel1.Init.Mode = DMA_NORMAL;
if (HAL_DMA_Init(&handle_HPDMA1_Channel1) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(hjpeg, hdmaout, handle_HPDMA1_Channel1);
if (HAL_DMA_ConfigChannelAttributes(&handle_HPDMA1_Channel1, DMA_CHANNEL_NPRIV) != HAL_OK)
{
Error_Handler();
}
/* HPDMA1_REQUEST_JPEG_RX Init */
handle_HPDMA1_Channel0.Instance = HPDMA1_Channel0;
handle_HPDMA1_Channel0.Init.Request = HPDMA1_REQUEST_JPEG_RX;
handle_HPDMA1_Channel0.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
handle_HPDMA1_Channel0.Init.Direction = DMA_MEMORY_TO_PERIPH;
handle_HPDMA1_Channel0.Init.SrcInc = DMA_SINC_INCREMENTED;
handle_HPDMA1_Channel0.Init.DestInc = DMA_DINC_FIXED;
handle_HPDMA1_Channel0.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_BYTE;
handle_HPDMA1_Channel0.Init.DestDataWidth = DMA_DEST_DATAWIDTH_WORD;
handle_HPDMA1_Channel0.Init.Priority = DMA_HIGH_PRIORITY;
handle_HPDMA1_Channel0.Init.SrcBurstLength = 8;
handle_HPDMA1_Channel0.Init.DestBurstLength = 8;
handle_HPDMA1_Channel0.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT1;
handle_HPDMA1_Channel0.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
handle_HPDMA1_Channel0.Init.Mode = DMA_NORMAL;
if (HAL_DMA_Init(&handle_HPDMA1_Channel0) != HAL_OK)
{
Error_Handler();
}
DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
DataHandlingConfig.DataAlignment = DMA_DATA_PACK;
if (HAL_DMAEx_ConfigDataHandling(&handle_HPDMA1_Channel0, &DataHandlingConfig) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(hjpeg, hdmain, handle_HPDMA1_Channel0);
if (HAL_DMA_ConfigChannelAttributes(&handle_HPDMA1_Channel0, DMA_CHANNEL_NPRIV) != HAL_OK)
{
Error_Handler();
}
/* JPEG interrupt Init */
HAL_NVIC_SetPriority(JPEG_IRQn, 8, 0);
HAL_NVIC_EnableIRQ(JPEG_IRQn);
/* USER CODE BEGIN JPEG_MspInit 1 */
/* USER CODE END JPEG_MspInit 1 */
}
}
/**
* @brief JPEG MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param hjpeg: JPEG handle pointer
* @retval None
*/
void HAL_JPEG_MspDeInit(JPEG_HandleTypeDef* hjpeg)
{
if(hjpeg->Instance==JPEG)
{
/* USER CODE BEGIN JPEG_MspDeInit 0 */
/* USER CODE END JPEG_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_JPEG_CLK_DISABLE();
/* JPEG DMA DeInit */
HAL_DMA_DeInit(hjpeg->hdmaout);
HAL_DMA_DeInit(hjpeg->hdmain);
/* JPEG interrupt DeInit */
HAL_NVIC_DisableIRQ(JPEG_IRQn);
/* USER CODE BEGIN JPEG_MspDeInit 1 */
/* USER CODE END JPEG_MspDeInit 1 */
}
}
/**
* @brief LTDC MSP Initialization
* This function configures the hardware resources used in this example
* @param hltdc: LTDC handle pointer
* @retval None
*/
void HAL_LTDC_MspInit(LTDC_HandleTypeDef* hltdc)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
if(hltdc->Instance==LTDC)
{
/* USER CODE BEGIN LTDC_MspInit 0 */
/* USER CODE END LTDC_MspInit 0 */
/** Initializes the peripherals clock
*/
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LTDC;
PeriphClkInit.LtdcClockSelection = RCC_LTDCCLKSOURCE_PLL3R;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
/* Peripheral clock enable */
__HAL_RCC_LTDC_CLK_ENABLE();
__HAL_RCC_GPIOF_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**LTDC GPIO Configuration
PF0 ------> LTDC_R2
PG0 ------> LTDC_R7
PB3(JTDO/TRACESWO) ------> LTDC_R4
PG2 ------> LTDC_HSYNC
PE11 ------> LTDC_VSYNC
PA12 ------> LTDC_B2
PA11 ------> LTDC_B3
PB4(NJTRST) ------> LTDC_R3
PA9 ------> LTDC_B5
PG1 ------> LTDC_R6
PA10 ------> LTDC_B4
PG14 ------> LTDC_B1
PA8 ------> LTDC_B6
PG13 ------> LTDC_CLK
PA15(JTDI) ------> LTDC_R5
PF7 ------> LTDC_G0
PF9 ------> LTDC_R0
PF10 ------> LTDC_R1
PB12 ------> LTDC_G5
PA0 ------> LTDC_G3
PA1 ------> LTDC_G2
PF11 ------> LTDC_B0
PB14 ------> LTDC_DE
PB15 ------> LTDC_G7
PF15 ------> LTDC_G1
PB11 ------> LTDC_G6
PB13 ------> LTDC_G4
PA6 ------> LTDC_B7
*/
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF11_LTDC;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_2|GPIO_PIN_1|GPIO_PIN_14
|GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF13_LTDC;
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_12|GPIO_PIN_14
|GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF13_LTDC;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF11_LTDC;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_11|GPIO_PIN_8|GPIO_PIN_15
|GPIO_PIN_0|GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF13_LTDC;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF14_LTDC;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_9|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF13_LTDC;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF14_LTDC;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_15|GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF10_LTDC;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF12_LTDC;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* LTDC interrupt Init */
HAL_NVIC_SetPriority(LTDC_IRQn, 5, 0);
/* USER CODE BEGIN LTDC_MspInit 1 */
/* USER CODE END LTDC_MspInit 1 */
}
}
/**
* @brief LTDC MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param hltdc: LTDC handle pointer
* @retval None
*/
void HAL_LTDC_MspDeInit(LTDC_HandleTypeDef* hltdc)
{
if(hltdc->Instance==LTDC)
{
/* USER CODE BEGIN LTDC_MspDeInit 0 */
/* USER CODE END LTDC_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_LTDC_CLK_DISABLE();
/**LTDC GPIO Configuration
PF0 ------> LTDC_R2
PG0 ------> LTDC_R7
PB3(JTDO/TRACESWO) ------> LTDC_R4
PG2 ------> LTDC_HSYNC
PE11 ------> LTDC_VSYNC
PA12 ------> LTDC_B2
PA11 ------> LTDC_B3
PB4(NJTRST) ------> LTDC_R3
PA9 ------> LTDC_B5
PG1 ------> LTDC_R6
PA10 ------> LTDC_B4
PG14 ------> LTDC_B1
PA8 ------> LTDC_B6
PG13 ------> LTDC_CLK
PA15(JTDI) ------> LTDC_R5
PF7 ------> LTDC_G0
PF9 ------> LTDC_R0
PF10 ------> LTDC_R1
PB12 ------> LTDC_G5
PA0 ------> LTDC_G3
PA1 ------> LTDC_G2
PF11 ------> LTDC_B0
PB14 ------> LTDC_DE
PB15 ------> LTDC_G7
PF15 ------> LTDC_G1
PB11 ------> LTDC_G6
PB13 ------> LTDC_G4
PA6 ------> LTDC_B7
*/
HAL_GPIO_DeInit(GPIOF, GPIO_PIN_0|GPIO_PIN_7|GPIO_PIN_9|GPIO_PIN_10
|GPIO_PIN_11|GPIO_PIN_15);
HAL_GPIO_DeInit(GPIOG, GPIO_PIN_0|GPIO_PIN_2|GPIO_PIN_1|GPIO_PIN_14
|GPIO_PIN_13);
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_12|GPIO_PIN_14
|GPIO_PIN_15|GPIO_PIN_11|GPIO_PIN_13);
HAL_GPIO_DeInit(GPIOE, GPIO_PIN_11);
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_12|GPIO_PIN_11|GPIO_PIN_9|GPIO_PIN_10
|GPIO_PIN_8|GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1
|GPIO_PIN_6);
/* LTDC interrupt DeInit */
HAL_NVIC_DisableIRQ(LTDC_IRQn);
/* USER CODE BEGIN LTDC_MspDeInit 1 */
/* USER CODE END LTDC_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
@@ -0,0 +1,192 @@
/**
******************************************************************************
* @file stm32h7rsxx_hal_timebase_tim.c
* @author MCD Application Team
* @brief Template for HAL time base based on the peripheral hardware TIM6.
*
* This file override the native HAL time base functions (defined as weak)
* the TIM time base:
* + Initializes the TIM6 peripheral to generate a Period elapsed Event each 1ms
* + HAL_IncTick is called inside HAL_TIM_PeriodElapsedCallback ie each 1ms
*
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "stm32h7rsxx_hal.h"
/** @addtogroup STM32H7RSxx_HAL_Driver
* @{
*/
/** @addtogroup HAL_TimeBase
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define TIM_CNT_FREQ 1000000U /* Timer counter frequency : 1 MHz */
#define TIM_FREQ 1000U /* Timer frequency : 1 kHz => to have 1 ms interrupt */
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
TIM_HandleTypeDef htim6;
/* Private function prototypes -----------------------------------------------*/
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1U)
void TimeBase_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
/* Private functions ---------------------------------------------------------*/
/**
* @brief This function configures the TIM6 as a time base source.
* The time source is configured to have 1ms time base with a dedicated
* Tick interrupt priority.
* @note This function is called automatically at the beginning of program after
* reset by HAL_Init() or at any time when clock is configured, by HAL_RCC_ClockConfig().
* @param TickPriority Tick interrupt priority.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
RCC_ClkInitTypeDef clkconfig;
uint32_t uwTimclock;
uint32_t uwAPB1Prescaler;
uint32_t uwPrescalerValue;
uint32_t pFLatency;
HAL_StatusTypeDef Status;
/* Enable TIM6 clock */
__HAL_RCC_TIM6_CLK_ENABLE();
/* Get clock configuration */
HAL_RCC_GetClockConfig(&clkconfig, &pFLatency);
/* Get APB1 prescaler */
uwAPB1Prescaler = clkconfig.APB1CLKDivider;
/* Compute TIM6 clock */
if (uwAPB1Prescaler == RCC_APB1_DIV1)
{
uwTimclock = HAL_RCC_GetPCLK1Freq();
}
else if (uwAPB1Prescaler == RCC_APB1_DIV2)
{
uwTimclock = 2UL * HAL_RCC_GetPCLK1Freq();
}
else
{
if (__HAL_RCC_GET_TIMCLKPRESCALER() == RCC_TIMPRES_DISABLE)
{
uwTimclock = 2UL * HAL_RCC_GetPCLK1Freq();
}
else
{
uwTimclock = 4UL * HAL_RCC_GetPCLK1Freq();
}
}
/* Compute the prescaler value to have TIM6 counter clock equal to TIM_CNT_FREQ */
uwPrescalerValue = (uint32_t)((uwTimclock / TIM_CNT_FREQ) - 1U);
/* Initialize TIM6 */
htim6.Instance = TIM6;
/* Initialize TIMx peripheral as follow:
+ Period = [uwTickFreq * (TIM_CNT_FREQ/TIM_FREQ) - 1]. to have a (uwTickFreq/TIM_FREQ) s time base.
+ Prescaler = (uwTimclock/TIM_CNT_FREQ - 1) to have a TIM_CNT_FREQ counter clock.
+ ClockDivision = 0
+ Counter direction = Up
*/
htim6.Init.Period = ((uint32_t)uwTickFreq * (TIM_CNT_FREQ / TIM_FREQ)) - 1U;
htim6.Init.Prescaler = uwPrescalerValue;
htim6.Init.ClockDivision = 0;
htim6.Init.CounterMode = TIM_COUNTERMODE_UP;
htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
Status = HAL_TIM_Base_Init(&htim6);
if (Status == HAL_OK)
{
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1U)
HAL_TIM_RegisterCallback(&htim6, HAL_TIM_PERIOD_ELAPSED_CB_ID, TimeBase_TIM_PeriodElapsedCallback);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
/* Start the TIM time Base generation in interrupt mode */
Status = HAL_TIM_Base_Start_IT(&htim6);
if (Status == HAL_OK)
{
if (TickPriority < (1UL << __NVIC_PRIO_BITS))
{
/* Configure the TIM6 global Interrupt priority */
HAL_NVIC_SetPriority(TIM6_IRQn, TickPriority, 0);
/* Enable the TIM6 global Interrupt */
HAL_NVIC_EnableIRQ(TIM6_IRQn);
uwTickPrio = TickPriority;
}
else
{
Status = HAL_ERROR;
}
}
}
/* Return function status */
return Status;
}
/**
* @brief Suspend Tick increment.
* @note Disable the tick increment by disabling TIM6 update interrupt.
* @retval None
*/
void HAL_SuspendTick(void)
{
/* Disable TIM6 update interrupt */
__HAL_TIM_DISABLE_IT(&htim6, TIM_IT_UPDATE);
}
/**
* @brief Resume Tick increment.
* @note Enable the tick increment by enabling TIM6 update interrupt.
* @retval None
*/
void HAL_ResumeTick(void)
{
/* Enable TIM6 update interrupt */
__HAL_TIM_ENABLE_IT(&htim6, TIM_IT_UPDATE);
}
/**
* @brief Period elapsed callback in non blocking mode
* @note This function is called when TIM6 interrupt took place, inside
* HAL_TIM6_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
* a global variable "uwTick" used as application time base.
* @param htim TIM handle
* @retval None
*/
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1U)
void TimeBase_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(htim);
HAL_IncTick();
}
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
/**
* @}
*/
/**
* @}
*/
+337
View File
@@ -0,0 +1,337 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32h7rsxx_it.c
* @brief Interrupt Service Routines.
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32h7rsxx_it.h"
#include "stm32h7s78_discovery_audio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN TD */
/* USER CODE END TD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/* External variables --------------------------------------------------------*/
extern DMA_NodeTypeDef Node_GPDMA1_Channel0;
extern DMA_QListTypeDef List_GPDMA1_Channel0;
extern DMA_HandleTypeDef handle_GPDMA1_Channel0;
extern MDF_HandleTypeDef AdfHandle0;
extern DMA2D_HandleTypeDef hdma2d;
extern GPU2D_HandleTypeDef hgpu2d;
extern DMA_HandleTypeDef handle_HPDMA1_Channel1;
extern DMA_HandleTypeDef handle_HPDMA1_Channel0;
extern JPEG_HandleTypeDef hjpeg;
extern LTDC_HandleTypeDef hltdc;
extern TIM_HandleTypeDef htim6;
extern DMA_HandleTypeDef hDmaI2sTx;
/* USER CODE BEGIN EV */
/* USER CODE END EV */
/******************************************************************************/
/* Cortex Processor Interruption and Exception Handlers */
/******************************************************************************/
/**
* @brief This function handles Non maskable interrupt.
*/
void NMI_Handler(void)
{
/* USER CODE BEGIN NonMaskableInt_IRQn 0 */
/* USER CODE END NonMaskableInt_IRQn 0 */
/* USER CODE BEGIN NonMaskableInt_IRQn 1 */
while (1)
{
}
/* USER CODE END NonMaskableInt_IRQn 1 */
}
/**
* @brief This function handles Hard fault interrupt.
*/
void HardFault_Handler(void)
{
/* USER CODE BEGIN HardFault_IRQn 0 */
/* USER CODE END HardFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_HardFault_IRQn 0 */
/* USER CODE END W1_HardFault_IRQn 0 */
}
}
/**
* @brief This function handles Memory management fault.
*/
void MemManage_Handler(void)
{
/* USER CODE BEGIN MemoryManagement_IRQn 0 */
/* USER CODE END MemoryManagement_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
/* USER CODE END W1_MemoryManagement_IRQn 0 */
}
}
/**
* @brief This function handles Pre-fetch fault, memory access fault.
*/
void BusFault_Handler(void)
{
/* USER CODE BEGIN BusFault_IRQn 0 */
/* USER CODE END BusFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_BusFault_IRQn 0 */
/* USER CODE END W1_BusFault_IRQn 0 */
}
}
/**
* @brief This function handles Undefined instruction or illegal state.
*/
void UsageFault_Handler(void)
{
/* USER CODE BEGIN UsageFault_IRQn 0 */
/* USER CODE END UsageFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_UsageFault_IRQn 0 */
/* USER CODE END W1_UsageFault_IRQn 0 */
}
}
/**
* @brief This function handles Debug monitor.
*/
void DebugMon_Handler(void)
{
/* USER CODE BEGIN DebugMonitor_IRQn 0 */
/* USER CODE END DebugMonitor_IRQn 0 */
/* USER CODE BEGIN DebugMonitor_IRQn 1 */
/* USER CODE END DebugMonitor_IRQn 1 */
}
/******************************************************************************/
/* STM32H7RSxx Peripheral Interrupt Handlers */
/* Add here the Interrupt Handlers for the used peripherals. */
/* For the available peripheral interrupt handler names, */
/* please refer to the startup file (startup_stm32h7rsxx.s). */
/******************************************************************************/
/**
* @brief This function handles EXTI line3 interrupt.
*/
void EXTI3_IRQHandler(void)
{
/* USER CODE BEGIN EXTI3_IRQn 0 */
/* USER CODE END EXTI3_IRQn 0 */
HAL_GPIO_EXTI_IRQHandler(TP_IRQ_Pin);
/* USER CODE BEGIN EXTI3_IRQn 1 */
/* USER CODE END EXTI3_IRQn 1 */
}
/**
* @brief This function handles GPDMA1 Channel 0 global interrupt.
*/
void GPDMA1_Channel0_IRQHandler(void)
{
/* USER CODE BEGIN GPDMA1_Channel0_IRQn 0 */
/* USER CODE END GPDMA1_Channel0_IRQn 0 */
HAL_DMA_IRQHandler(&handle_GPDMA1_Channel0);
/* USER CODE BEGIN GPDMA1_Channel0_IRQn 1 */
/* USER CODE END GPDMA1_Channel0_IRQn 1 */
}
void GPDMA1_Channel2_IRQHandler(void)
{
BSP_AUDIO_OUT_IRQHandler(0, AUDIO_OUT_HEADPHONE);
}
/**
* @brief This function handles TIM6 global interrupt.
*/
void TIM6_IRQHandler(void)
{
/* USER CODE BEGIN TIM6_IRQn 0 */
/* USER CODE END TIM6_IRQn 0 */
HAL_TIM_IRQHandler(&htim6);
/* USER CODE BEGIN TIM6_IRQn 1 */
/* USER CODE END TIM6_IRQn 1 */
}
/**
* @brief This function handles HPDMA1 Channel 0 global interrupt.
*/
void HPDMA1_Channel0_IRQHandler(void)
{
/* USER CODE BEGIN HPDMA1_Channel0_IRQn 0 */
/* USER CODE END HPDMA1_Channel0_IRQn 0 */
HAL_DMA_IRQHandler(&handle_HPDMA1_Channel0);
/* USER CODE BEGIN HPDMA1_Channel0_IRQn 1 */
/* USER CODE END HPDMA1_Channel0_IRQn 1 */
}
/**
* @brief This function handles HPDMA1 Channel 1 global interrupt.
*/
void HPDMA1_Channel1_IRQHandler(void)
{
/* USER CODE BEGIN HPDMA1_Channel1_IRQn 0 */
/* USER CODE END HPDMA1_Channel1_IRQn 0 */
HAL_DMA_IRQHandler(&handle_HPDMA1_Channel1);
/* USER CODE BEGIN HPDMA1_Channel1_IRQn 1 */
/* USER CODE END HPDMA1_Channel1_IRQn 1 */
}
/**
* @brief This function handles LTDC global interrupt.
*/
void LTDC_IRQHandler(void)
{
/* USER CODE BEGIN LTDC_IRQn 0 */
/* USER CODE END LTDC_IRQn 0 */
HAL_LTDC_IRQHandler(&hltdc);
/* USER CODE BEGIN LTDC_IRQn 1 */
/* USER CODE END LTDC_IRQn 1 */
}
/**
* @brief This function handles DMA2D global interrupt.
*/
void DMA2D_IRQHandler(void)
{
/* USER CODE BEGIN DMA2D_IRQn 0 */
/* USER CODE END DMA2D_IRQn 0 */
HAL_DMA2D_IRQHandler(&hdma2d);
/* USER CODE BEGIN DMA2D_IRQn 1 */
/* USER CODE END DMA2D_IRQn 1 */
}
/**
* @brief This function handles JPEG global interrupt.
*/
void JPEG_IRQHandler(void)
{
/* USER CODE BEGIN JPEG_IRQn 0 */
/* USER CODE END JPEG_IRQn 0 */
HAL_JPEG_IRQHandler(&hjpeg);
/* USER CODE BEGIN JPEG_IRQn 1 */
/* USER CODE END JPEG_IRQn 1 */
}
/**
* @brief This function handles ADF1 Filter 0 global Interrupt.
*/
void ADF1_FLT0_IRQHandler(void)
{
/* USER CODE BEGIN ADF1_FLT0_IRQn 0 */
/* USER CODE END ADF1_FLT0_IRQn 0 */
HAL_MDF_IRQHandler(&AdfHandle0);
/* USER CODE BEGIN ADF1_FLT0_IRQn 1 */
/* USER CODE END ADF1_FLT0_IRQn 1 */
}
/**
* @brief This function handles GPU2D global interrupt.
*/
void GPU2D_IRQHandler(void)
{
/* USER CODE BEGIN GPU2D_IRQn 0 */
/* USER CODE END GPU2D_IRQn 0 */
HAL_GPU2D_IRQHandler(&hgpu2d);
/* USER CODE BEGIN GPU2D_IRQn 1 */
/* USER CODE END GPU2D_IRQn 1 */
}
/**
* @brief This function handles GPU2D Error interrupt.
*/
void GPU2D_ER_IRQHandler(void)
{
/* USER CODE BEGIN GPU2D_ER_IRQn 0 */
/* USER CODE END GPU2D_ER_IRQn 0 */
HAL_GPU2D_ER_IRQHandler(&hgpu2d);
/* USER CODE BEGIN GPU2D_ER_IRQn 1 */
/* USER CODE END GPU2D_ER_IRQn 1 */
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
+304
View File
@@ -0,0 +1,304 @@
/**
******************************************************************************
* @file system_stm32h7rsxx.c
* @author MCD Application Team
* @brief CMSIS Cortex-M7 Device Peripheral Access Layer System Source File
******************************************************************************
* @attention
*
* Copyright (c) 2022 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*
* This file provides two functions and one global variable to be called from
* user application:
* - SystemInit(): This function is called at startup just after reset and
* before branch to main program. This call is made inside
* the "startup_stm32h7rsxx.s" file.
*
* - SystemCoreClock variable: Contains the core clock (sys_cpu_ck), it can
* be used by the user application to setup the
* SysTick timer or configure other parameters.
*
* - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must
* be called whenever the core clock is changed
* during program execution.
*
* After each device reset the HSI (64 MHz) is used as system clock source.
* Then SystemInit() function is called, in "startup_stm32h7rsxx.s" file, to
* optionally configure the system clock before to branch to main program.
*
*=============================================================================
*/
/** @addtogroup CMSIS
* @{
*/
/** @addtogroup STM32H7RSxx_System
* @{
*/
/** @addtogroup STM32H7RSxx_System_Private_Includes
* @{
*/
#include "stm32h7rsxx.h"
#include <math.h>
/**
* @}
*/
/** @addtogroup STM32H7RSxx_System_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @addtogroup STM32H7RSxx_System_Private_Defines
* @{
*/
#if !defined (HSE_VALUE)
#define HSE_VALUE 24000000UL /*!< Value of the High-Speed External oscillator in Hz */
#endif /* HSE_VALUE */
#if !defined (HSI_VALUE)
#define HSI_VALUE 64000000UL /*!< Value of the High-Speed Internal oscillator in Hz */
#endif /* HSI_VALUE */
#if !defined (CSI_VALUE)
#define CSI_VALUE 4000000UL /*!< Value of the Low-power Internal oscillator in Hz */
#endif /* CSI_VALUE */
/* Note: Following vector table addresses must be defined in line with linker
configuration. */
/*!< Uncomment the following line or define USER_VECT_TAB_ADDRESS at compiler level if you need
to relocate the vector table anywhere in Flash or Sram, else the vector table is kept at
the automatic remap of the selected boot address */
/* #define USER_VECT_TAB_ADDRESS */
#if defined(USER_VECT_TAB_ADDRESS)
/*!< Uncomment the following line or define VECT_TAB_SRAM at compiler level if you need
to relocate your vector Table in Sram else user remap will be done in Flash. */
/* #define VECT_TAB_SRAM */
#if defined(VECT_TAB_SRAM)
#if !defined(VECT_TAB_BASE_ADDRESS)
#define VECT_TAB_BASE_ADDRESS ITCM_BASE /*!< Vector Table base address field.
This value must be a multiple of 0x400. */
#endif
#if !defined(VECT_TAB_OFFSET)
#define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field.
This value must be a multiple of 0x400. */
#endif
#else
#if !defined(VECT_TAB_BASE_ADDRESS)
#define VECT_TAB_BASE_ADDRESS FLASH_BASE /*!< Vector Table base address field.
This value must be a multiple of 0x400. */
#endif
#if !defined(VECT_TAB_OFFSET)
#define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field.
This value must be a multiple of 0x400. */
#endif
#endif /* VECT_TAB_SRAM */
#endif /* USER_VECT_TAB_ADDRESS */
/******************************************************************************/
/**
* @}
*/
/** @addtogroup STM32H7RSxx_System_Private_Macros
* @{
*/
/**
* @}
*/
/** @addtogroup STM32H7RSxx_System_Private_Variables
* @{
*/
/* The SystemCoreClock variable is updated in two ways:
1) by calling CMSIS function SystemCoreClockUpdate()
2) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
Note: If you use this function to configure the system clock; then there
is no need to call the first function listed above, since SystemCoreClock
variable is updated automatically.
*/
uint32_t SystemCoreClock = HSI_VALUE;
/**
* @}
*/
/** @addtogroup STM32H7RSxx_System_Private_FunctionPrototypes
* @{
*/
/**
* @}
*/
/** @addtogroup STM32H7RSxx_System_Private_Functions
* @{
*/
/**
* @brief Setup the microcontroller system.
* @retval None
*/
void SystemInit(void)
{
/* Configure the Vector Table location -------------------------------------*/
#if defined(USER_VECT_TAB_ADDRESS)
SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET;
#endif
/* FPU settings ------------------------------------------------------------*/
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |= ((3UL << 20U)|(3UL << 22U)); /* set CP10 and CP11 Full Access */
#endif
}
/**
* @brief Update SystemCoreClock variable according to RCC registers values.
* The SystemCoreClock variable contains the core clock (sys_cpu_ck), it can
* be used by the user application to setup the SysTick timer or configure
* other parameters.
*
* @note Each time the core clock changes, this function must be called
* to update SystemCoreClock variable value. Otherwise, any configuration
* based on this variable will be incorrect.
*
* @note - The system frequency computed by this function is not the real
* frequency in the chip. It is calculated based on the predefined
* constant and the selected clock source:
*
* - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*)
*
* - If SYSCLK source is CSI, SystemCoreClock will contain the CSI_VALUE(**)
*
* - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(***)
*
* - If SYSCLK source is PLL, SystemCoreClock will contain the HSI_VALUE(*)
* or CSI_VALUE(**) or HSE_VALUE(***) multiplied/divided by the PLL factors.
*
* (*) HSI_VALUE is a constant defined in stm32h7rsxx_hal.h file (default value
* 64 MHz) but the real value may vary depending on the variations
* in voltage and temperature.
*
* (**) CSI_VALUE is a constant defined in stm32h7rsxx_hal.h file (default value
* 4 MHz) but the real value may vary depending on the variations
* in voltage and temperature.
*
* (***) HSE_VALUE is a constant defined in stm32h7rsxx_hal.h file (default value
* 24 MHz), user has to ensure that HSE_VALUE is same as the real
* frequency of the crystal used. Otherwise, this function may
* have wrong result.
*
* - The result of this function could be not correct when using fractional
* value for HSE crystal.
*
* @retval None
*/
void SystemCoreClockUpdate(void)
{
uint32_t sysclk, hsivalue, pllsource, pllm, pllp, core_presc;
float_t pllfracn, pllvco;
/* Get SYSCLK source -------------------------------------------------------*/
switch (RCC->CFGR & RCC_CFGR_SWS)
{
case 0x00: /* HSI used as system clock source (default after reset) */
sysclk = (HSI_VALUE >> ((RCC->CR & RCC_CR_HSIDIV) >> RCC_CR_HSIDIV_Pos));
break;
case 0x08: /* CSI used as system clock source */
sysclk = CSI_VALUE;
break;
case 0x10: /* HSE used as system clock source */
sysclk = HSE_VALUE;
break;
case 0x18: /* PLL1 used as system clock source */
/* PLL1_VCO = (HSE_VALUE or HSI_VALUE or CSI_VALUE/ PLLM) * PLLN
SYSCLK = PLL1_VCO / PLL1R
*/
pllsource = (RCC->PLLCKSELR & RCC_PLLCKSELR_PLLSRC);
pllm = ((RCC->PLLCKSELR & RCC_PLLCKSELR_DIVM1) >> RCC_PLLCKSELR_DIVM1_Pos) ;
if ((RCC->PLLCFGR & RCC_PLLCFGR_PLL1FRACEN) != 0U)
{
pllfracn = (float_t)(uint32_t)(((RCC->PLL1FRACR & RCC_PLL1FRACR_FRACN)>> RCC_PLL1FRACR_FRACN_Pos));
}
else
{
pllfracn = (float_t)0U;
}
if (pllm != 0U)
{
switch (pllsource)
{
case 0x02: /* HSE used as PLL1 clock source */
pllvco = ((float_t)HSE_VALUE / (float_t)pllm) * ((float_t)(uint32_t)(RCC->PLL1DIVR1 & RCC_PLL1DIVR1_DIVN) + (pllfracn/(float_t)0x2000) +(float_t)1 );
break;
case 0x01: /* CSI used as PLL1 clock source */
pllvco = ((float_t)CSI_VALUE / (float_t)pllm) * ((float_t)(uint32_t)(RCC->PLL1DIVR1 & RCC_PLL1DIVR1_DIVN) + (pllfracn/(float_t)0x2000) +(float_t)1 );
break;
case 0x00: /* HSI used as PLL1 clock source */
default:
hsivalue = (HSI_VALUE >> ((RCC->CR & RCC_CR_HSIDIV) >> RCC_CR_HSIDIV_Pos));
pllvco = ( (float_t)hsivalue / (float_t)pllm) * ((float_t)(uint32_t)(RCC->PLL1DIVR1 & RCC_PLL1DIVR1_DIVN) + (pllfracn/(float_t)0x2000) +(float_t)1 );
break;
}
pllp = (((RCC->PLL1DIVR1 & RCC_PLL1DIVR1_DIVP) >> RCC_PLL1DIVR1_DIVP_Pos) + 1U ) ;
sysclk = (uint32_t)(float_t)(pllvco/(float_t)pllp);
}
else
{
sysclk = 0U;
}
break;
default: /* Unexpected, default to HSI used as system clock source (default after reset) */
sysclk = (HSI_VALUE >> ((RCC->CR & RCC_CR_HSIDIV) >> RCC_CR_HSIDIV_Pos));
break;
}
/* system clock frequency : CM7 CPU frequency */
core_presc = (RCC->CDCFGR & RCC_CDCFGR_CPRE);
if (core_presc >= 8U)
{
SystemCoreClock = (sysclk >> (core_presc - RCC_CDCFGR_CPRE_3 + 1U));
}
else
{
SystemCoreClock = sysclk;
}
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/