This is an old revision of the document!


Electric Guitar Effects Pedal

Introduction

This project is an electric guitar effects pedal built around the ATmega328P Xplained Mini development board.

The pedal receives the signal from an electric guitar, processes it using the microcontroller, and sends the modified signal further to an amplifier or audio system. The main effects chosen for this project are distortion and tremolo, together with a simple clean/bypass mode.

The project started from the idea that guitar pedals are both useful and interesting from a technical point of view. They are good examples of systems that combine analog electronics with embedded software. Instead of making a very complex multi-effect unit, the goal was to create something simpler, realistic, and possible to build by hand with common components.

This project is useful for us because it helps us apply concepts learned in the laboratories, such as ADC, PWM, timers, interrupts, GPIO, I2C, and UART, in a practical product. It can also be useful for other students or hobbyists who want to understand the basics of digital audio effects on a microcontroller.

General Description

The project can be split into a few simple functional blocks:

  • Input stage – receives the guitar signal through a jack connector.
  • Analog conditioning stage – prepares the signal for the microcontroller by shifting and filtering it.
  • ADC module – samples the guitar signal.
  • Control module – reads potentiometers, push buttons, and footswitch.
  • Effect processing module – applies the selected effect in software.
  • PWM output module – generates the processed output signal.
  • Output filter stage – smooths the PWM signal and sends it to the output jack.
  • User feedback module – can use an LCD or simple LEDs to indicate the current mode.
  • Debug module – sends data through UART for testing and debugging.

Suggested block diagram:

Signal flow:

Guitar Input → Analog Conditioning → ADC → Effect Processing → PWM Output → Output Filter → Guitar Amplifier

Control flow:

  • potentiometers adjust the effect parameters;
  • buttons select the active effect;
  • the footswitch enables or disables the pedal;
  • an optional LCD or LEDs show the active mode.

The interaction is simple: the input signal is first prepared so it can be safely read by the microcontroller. Then the ADC samples it, the firmware applies either distortion or tremolo, and the result is sent to the PWM output. After filtering, the output becomes an analog signal again and goes to the amplifier.

Hardware Design

Main components

  • 1 x ATmega328P Xplained Mini
  • 2 x 6.35 mm mono jack connectors
  • 1 x single-supply dual operational amplifier
  • 1 x 3PDT footswitch
  • 2 x push buttons
  • 2 or 3 x potentiometers
  • 1 x status LED
  • optional: 16×2 LCD with I2C backpack
  • resistors and capacitors
  • coupling capacitors
  • pull-up resistors
  • RC filter components
  • breadboard or perfboard

Input stage

The electric guitar produces an AC signal, but the ADC of the microcontroller works with positive voltages only. Because of this, the signal has to be adapted before sampling.

The analog conditioning stage contains:

  • an input capacitor for AC coupling;
  • a voltage divider that creates a mid-supply bias;
  • an op-amp stage for buffering or amplification;
  • optional filtering to reduce noise.

This stage is important because it makes the signal compatible with the ADC and improves stability during processing.

Processing unit

The main processing unit is the ATmega328P from the Xplained Mini board. It handles:

  • sampling of the guitar signal;
  • reading control inputs;
  • applying the selected effect;
  • generating the output with PWM;
  • communication through UART;
  • optional display updates.

Output stage

The output signal is generated as PWM. Since PWM is not directly suitable as an audio signal, it is passed through an RC low-pass filter. After filtering, the signal is sent to the output jack.

An op-amp buffer can also be used here to improve output stability.

Controls

The user controls are:

  • footswitch – turns effect on/off or bypasses it;
  • buttons – select effect mode;
  • potentiometers – change effect parameters;
  • LED – shows whether the pedal is active;
  • optional LCD – displays current mode and values.

Proposed pin usage

  • PC0 / ADC0 – guitar input
  • PC1 / ADC1 – potentiometer 1
  • PC2 / ADC2 – potentiometer 2
  • PC3 / ADC3 – potentiometer 3, if needed
  • PC4 / SDA – optional LCD
  • PC5 / SCL – optional LCD
  • PD5 or PD6 – PWM output
  • PD2 – footswitch / interrupt input
  • PD3 – button input / second interrupt
  • PD0 / RX – UART
  • PD1 / TX – UART
  • PB5 – onboard LED or status output

Schematics and diagrams

Software Design

Development environment

The firmware will be written in C/C++ using an AVR-compatible development environment:

  • PlatformIO
  • avr-gcc

External libraries

The project will try to keep the code as simple as possible. Only a few external libraries may be used:

  • standard AVR libraries;
  • optional LCD I2C library;
  • basic UART helper functions for debug.

Most of the main logic will be implemented manually.

Laboratory concepts used

This project includes functionality from multiple laboratories:

  • GPIO – LED, buttons, footswitch
  • ADC – input signal and potentiometers
  • Timers – timing for tremolo and audio update
  • PWM – audio output
  • Interrupts – ADC complete interrupt and optional button/footswitch interrupts
  • UART – serial debugging
  • I2C – optional LCD communication

Software structure

The firmware can be organized into the following modules:

  • `main.c`
  • `adc.c / adc.h`
  • `effects.c / effects.h`
  • `controls.c / controls.h`
  • `pwm.c / pwm.h`
  • `uart.c / uart.h`

Main logic

The general execution flow is:

  1. initialize peripherals;
  2. configure ADC;
  3. configure timer and PWM output;
  4. initialize buttons, LED, and optional LCD;
  5. start sampling the input signal;
  6. process each sample depending on the selected mode;
  7. update output;
  8. update controls and debug information in the main loop.

Effect modes

Clean / bypass

This mode sends the input further without applying a strong audio effect. In the final hardware version, the footswitch may also provide real hardware bypass.

Distortion

Distortion is implemented by increasing the amplitude of the signal and clipping it when it goes above a threshold.

Example logic:

  • read sample;
  • remove bias;
  • multiply by gain;
  • clip positive and negative peaks;
  • restore bias;
  • send to output.

The distortion intensity is controlled by a potentiometer.

Tremolo

Tremolo changes the signal amplitude periodically. It is implemented by multiplying the input signal with a slowly changing factor generated in software.

Parameters:

  • speed
  • depth

The modulation can be generated using a counter or a lookup table.

Results Obtained

At this stage, the project has a complete design plan and a clear implementation direction.

The expected final result is a working prototype that:

  • receives electric guitar signal;
  • offers clean/bypass mode;
  • offers distortion effect;
  • offers tremolo effect;
  • uses potentiometers for parameter control;
  • uses buttons and footswitch for interaction;
  • uses LED and optionally LCD for feedback;
  • can send debug data over UART.

After implementation, this section will include:

  • photos of the prototype;
  • screenshots or photos of the interface;
  • notes about sound quality and stability;
  • practical test results with guitar and amplifier.

Conclusions

The project is a realistic embedded application that combines hardware and software in a clear and useful way.

Its main advantage is that it remains simple enough to be built by hand while still including important concepts from the laboratory. Instead of trying to implement many difficult effects, the project focuses on two effects that are easier to understand and demonstrate: distortion and tremolo.

Download

The following files will be uploaded when the implementation is finished:

Example files:

  • `guitar_pedal_sources.zip`
  • `guitar_pedal_schematics.pdf`
  • `README.md`
  • `CHANGELOG.txt`

Journal

#define F_CPU 16000000UL

#include <avr/io.h> #include <avr/interrupt.h> #include <avr/pgmspace.h> #include <util/atomic.h> #include <util/delay.h> #include <stdint.h>

===================================================== PIN DEFINITIONS ===================================================== #define STATUS_LED PB5 #define BUTTON_EFFECT PD2 INT0 #define BUTTON_MODE PD3 INT1 #define PWM_OUT PD5 OC0B

#define ADC_AUDIO 0 PC0 / ADC0 #define ADC_GAIN 1 PC1 / ADC1 #define ADC_TREMOLO 2 PC2 / ADC2 OLED pins pe PORTB #define OLED_SCL PB0 #define OLED_SDA PB1 #define OLED_RST PB2 #define OLED_DC PB4

#define OLED_PORT PORTB #define OLED_DDR DDRB

#define OLED_WIDTH 128 #define OLED_PAGES 8 8 pentru 128×64; daca e 128×32 pune 4

AUDIO TUNING

Gain-urile sunt in Q4: 16 = 1x 32 = 2x 64 = 4x 80 = 5x 128 = 8x Pentru ca ai deja zgomot mare, distortion-ul este intentionat subtil.

#define CLEAN_GAIN_Q4 64 clean ramane 4x #define TREM_GAIN_Q4 80 tremolo putin mai tare

#define DIST_GAIN_MIN_Q4 96 6x #define DIST_GAIN_MAX_Q4 180 11.25x, distortion mai clar

#define DIST_CLIP_MAX_8BIT 46 clipping mai vizibil #define DIST_CLIP_MIN_8BIT 18 clipping mai agresiv la pot mare

#define NOISE_GATE_10BIT 4 #define AUDIO_SMOOTH_SHIFT 0 mai direct, mai puternic, dar si mai zgomotos

EFFECT STATE

#define EFFECT_DIST 0 #define EFFECT_TREM 1

volatile uint8_t effect_enabled = 0; volatile uint8_t selected_effect = EFFECT_DIST;

volatile uint8_t effect_button_event = 0; volatile uint8_t mode_button_event = 0;

volatile uint32_t g_millis = 0;

volatile uint32_t last_effect_interrupt_ms = 0; volatile uint32_t last_mode_interrupt_ms = 0;

#define DEBOUNCE_MS 50

valori citite din potentiometre, 0..255 volatile uint8_t pot_gain_raw = 128; volatile uint8_t pot_tremolo_raw = 128; parametri audio derivati din potentiometre volatile uint8_t g_dist_gain_q4 = DIST_GAIN_MIN_Q4; volatile uint8_t g_dist_clip = DIST_CLIP_MAX_8BIT; volatile uint8_t g_trem_step = 8;

pentru ADC multiplexing volatile uint8_t current_adc_channel = ADC_AUDIO; volatile uint8_t adc_skip_sample = 0; volatile uint16_t audio_sample_counter = 0;

SMALL UTILS

static inline uint16_t abs16(int16_t x) {

  return (x < 0) ? (uint16_t)(-x) : (uint16_t)x;

}

static inline int16_t clamp_i16(int16_t x, int16_t min_value, int16_t max_value) {

  if (x < min_value)
  {
      return min_value;
  }
  if (x > max_value)
  {
      return max_value;
  }
  return x;

}

===================================================== TIMER1: 1 ms system clock ===================================================== void timer1_init_1ms(void) { TCCR1A = 0; TCCR1B = 0; 16 MHz / 64 = 250 kHz

  // 250 ticks = 1 ms
  OCR1A = 249;
  TCCR1B |= (1 << WGM12);              // CTC mode
  TCCR1B |= (1 << CS11) | (1 << CS10); // prescaler 64
  TIMSK1 |= (1 << OCIE1A);

}

ISR(TIMER1_COMPA_vect) {

  g_millis++;

}

uint32_t millis_get(void) {

  uint32_t value;
  ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
  {
      value = g_millis;
  }
  return value;

}

===================================================== BUTTONS: INT0 / INT1 ===================================================== void buttons_init(void) { PD2, PD3 input

  DDRD &= ~(1 << BUTTON_EFFECT);
  DDRD &= ~(1 << BUTTON_MODE);
  // internal pull-up
  PORTD |= (1 << BUTTON_EFFECT);
  PORTD |= (1 << BUTTON_MODE);
  // INT0 falling edge
  EICRA |= (1 << ISC01);
  EICRA &= ~(1 << ISC00);
  // INT1 falling edge
  EICRA |= (1 << ISC11);
  EICRA &= ~(1 << ISC10);
  // clear old flags
  EIFR |= (1 << INTF0) | (1 << INTF1);
  // enable INT0, INT1
  EIMSK |= (1 << INT0) | (1 << INT1);

}

ISR(INT0_vect) {

  uint32_t now = g_millis;
  if ((uint32_t)(now - last_effect_interrupt_ms) >= DEBOUNCE_MS)
  {
      effect_button_event = 1;
      last_effect_interrupt_ms = now;
  }

}

ISR(INT1_vect) {

  uint32_t now = g_millis;
  if ((uint32_t)(now - last_mode_interrupt_ms) >= DEBOUNCE_MS)
  {
      mode_button_event = 1;
      last_mode_interrupt_ms = now;
  }

}

===================================================== PWM OUTPUT: PD5 / OC0B ===================================================== void pwm_init_pd5(void) { DDRD |= (1 « PWM_OUT); Timer0 Fast PWM, 8-bit

  // OC0B non-inverting pe PD5
  // PWM freq = 16 MHz / 256 = 62.5 kHz
  TCCR0A = (1 << COM0B1) | (1 << WGM01) | (1 << WGM00);
  TCCR0B = (1 << CS00);
  OCR0B = 128;

}

===================================================== ADC: audio + potentiometers ===================================================== void adc_select_channel(uint8_t channel) { ADMUX = (1 « REFS0) | (channel & 0x0F); } void adc_init(void) { current_adc_channel = ADC_AUDIO; AVcc reference, ADC0 first

  adc_select_channel(ADC_AUDIO);
  // ADC enable, ADC interrupt, auto trigger, prescaler 64
  // ADC clock = 16 MHz / 64 = 250 kHz
  ADCSRA = (1 << ADEN)  |
           (1 << ADIE)  |
           (1 << ADATE) |
           (1 << ADPS2) |
           (1 << ADPS1);
  // free running mode
  ADCSRB = 0;
  // disable digital input buffers on ADC0, ADC1, ADC2
  DIDR0 = (1 << ADC0D) | (1 << ADC1D) | (1 << ADC2D);
  // start conversions
  ADCSRA |= (1 << ADSC);

}

===================================================== AUDIO PROCESSING ===================================================== void audio_process_sample(uint16_t raw10) { static int32_t dc_q8 = 1); } void oled_clear(void) { for (uint8_t page = 0; page < OLED_PAGES; page++) { oled_set_cursor(page, 0); for (uint8_t col = 0; col < OLED_WIDTH; col++) { oled_data(0x00); } } } void oled_init(void) { OLED_DDR |= (1 « OLED_SCL) | (1 « OLED_SDA) | (1 « OLED_RST) | (1 « OLED_DC); oled_pin_low(OLED_SCL); oled_pin_low(OLED_SDA); oled_reset(); oled_command(0xAE); display OFF

  oled_command(0xD5);
  oled_command(0x80);
  oled_command(0xA8);
  oled_command(0x3F); // 128x64
  oled_command(0xD3);
  oled_command(0x00);
  oled_command(0x40);
  oled_command(0x8D);
  oled_command(0x14);
  oled_command(0x20);
  oled_command(0x00);
  oled_command(0xA1);
  oled_command(0xC8);
  oled_command(0xDA);
  oled_command(0x12);
  oled_command(0x81);
  oled_command(0xCF);
  oled_command(0xD9);
  oled_command(0xF1);
  oled_command(0xDB);
  oled_command(0x40);
  oled_command(0xA4);
  oled_command(0xA6);
  oled_command(0xAF);
  oled_clear();

} ===================================================== OLED FONT MINIMAL 5×7 ===================================================== const uint8_t FONT_SPACE[5] PROGMEM = {0x00,0x00,0x00,0x00,0x00}; const uint8_t FONT_COLON[5] PROGMEM = {0x00,0x36,0x36,0x00,0x00}; const uint8_t FONT_A[5] PROGMEM = {0x7E,0x11,0x11,0x11,0x7E}; const uint8_t FONT_C[5] PROGMEM = {0x3E,0x41,0x41,0x41,0x22}; const uint8_t FONT_D[5] PROGMEM = {0x7F,0x41,0x41,0x22,0x1C}; const uint8_t FONT_E[5] PROGMEM = {0x7F,0x49,0x49,0x49,0x41}; const uint8_t FONT_F[5] PROGMEM = {0x7F,0x09,0x09,0x09,0x01}; const uint8_t FONT_I[5] PROGMEM = {0x00,0x41,0x7F,0x41,0x00}; const uint8_t FONT_L[5] PROGMEM = {0x7F,0x40,0x40,0x40,0x40}; const uint8_t FONT_M[5] PROGMEM = {0x7F,0x02,0x0C,0x02,0x7F}; const uint8_t FONT_N[5] PROGMEM = {0x7F,0x04,0x08,0x10,0x7F}; const uint8_t FONT_O[5] PROGMEM = {0x3E,0x41,0x41,0x41,0x3E}; const uint8_t FONT_P[5] PROGMEM = {0x7F,0x09,0x09,0x09,0x06}; const uint8_t FONT_R[5] PROGMEM = {0x7F,0x09,0x19,0x29,0x46}; const uint8_t FONT_S[5] PROGMEM = {0x46,0x49,0x49,0x49,0x31}; const uint8_t FONT_T[5] PROGMEM = {0x01,0x01,0x7F,0x01,0x01}; const uint8_t FONT_X[5] PROGMEM = {0x63,0x14,0x08,0x14,0x63}; const uint8_t* get_char_bitmap(char c) { switch © { case 'A': return FONT_A; case 'C': return FONT_C; case 'D': return FONT_D; case 'E': return FONT_E; case 'F': return FONT_F; case 'I': return FONT_I; case 'L': return FONT_L; case 'M': return FONT_M; case 'N': return FONT_N; case 'O': return FONT_O; case 'P': return FONT_P; case 'R': return FONT_R; case 'S': return FONT_S; case 'T': return FONT_T; case 'X': return FONT_X; case ':': return FONT_COLON; case ' ': return FONT_SPACE; default: return FONT_SPACE; } } void oled_print_char(char c) { const uint8_t* bitmap = get_char_bitmap©; for (uint8_t i = 0; i < 5; i++) { oled_data(pgm_read_byte(&bitmap[i])); } oled_data(0x00); } void oled_print(const char* text) { while (*text) { oled_print_char(*text); text++; } } void oled_print_at(uint8_t page, uint8_t column, const char* text) { oled_set_cursor(page, column); oled_print(text); } void oled_show_status(uint8_t pedal_on, uint8_t effect) { oled_clear(); oled_print_at(1, 0, “PEDAL:”); if (pedal_on) { oled_print(“ON”); } else { oled_print(“OFF”); } oled_print_at(3, 0, “FX:”); if (effect == EFFECT_DIST) { oled_print(“DIST”); } else { oled_print(“TREM”); } } ===================================================== CONTROL PARAMETER UPDATE ===================================================== void update_audio_parameters_from_pots(void) {

  uint8_t gain = pot_gain_raw;
  uint8_t trem = pot_tremolo_raw;
  // distortion gain subtil
  uint8_t dist_gain = DIST_GAIN_MIN_Q4 +
      (uint8_t)(((uint16_t)gain * (DIST_GAIN_MAX_Q4 - DIST_GAIN_MIN_Q4)) / 255);
  // la gain mare, clip-ul scade putin
  uint8_t dist_clip = DIST_CLIP_MAX_8BIT -
      (uint8_t)(((uint16_t)gain * (DIST_CLIP_MAX_8BIT - DIST_CLIP_MIN_8BIT)) / 255);
  // tremolo speed: aproximativ lent -> rapid
  uint8_t trem_step = 2 + (uint8_t)(((uint16_t)trem * 60) / 255);
  g_dist_gain_q4 = dist_gain;
  g_dist_clip = dist_clip;
  g_trem_step = trem_step;

} ===================================================== STATUS LED ===================================================== void status_led_update(void) { static uint32_t last_toggle_ms = 0; static uint8_t led_state = 0; uint32_t now = millis_get(); if (!effect_enabled) { PORTB &= ~(1 « STATUS_LED); led_state = 0; return; } if (selected_effect == EFFECT_DIST) { PORTB |= (1 « STATUS_LED); return; } Tremolo mode: blink status LED

  if ((uint32_t)(now - last_toggle_ms) >= 250)
  {
      last_toggle_ms = now;
      led_state = !led_state;
      if (led_state)
      {
          PORTB |= (1 << STATUS_LED);
      }
      else
      {
          PORTB &= ~(1 << STATUS_LED);
      }
  }

} ===================================================== MAIN ===================================================== int main(void) { status LED

  DDRB |= (1 << STATUS_LED);
  // Init output and controls
  pwm_init_pd5();
  // OLED init inainte de audio interrupts
  oled_init();
  oled_show_status(effect_enabled, selected_effect);
  timer1_init_1ms();
  buttons_init();
  adc_init();
  sei();
  uint32_t last_params_update_ms = 0;
  uint8_t screen_update_needed = 1;
  while (1)
  {
      uint8_t local_effect_event = 0;
      uint8_t local_mode_event = 0;
      ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
      {
          if (effect_button_event)
          {
              local_effect_event = 1;
              effect_button_event = 0;
          }
          if (mode_button_event)
          {
              local_mode_event = 1;
              mode_button_event = 0;
          }
      }
      if (local_effect_event)
      {
          effect_enabled = !effect_enabled;
          screen_update_needed = 1;
      }
      if (local_mode_event)
      {
          if (selected_effect == EFFECT_DIST)
          {
              selected_effect = EFFECT_TREM;
          }
          else
          {
              selected_effect = EFFECT_DIST;
          }
          screen_update_needed = 1;
      }
      uint32_t now = millis_get();
      if ((uint32_t)(now - last_params_update_ms) >= 20)
      {
          last_params_update_ms = now;
          update_audio_parameters_from_pots();
      }
      if (screen_update_needed)
      {
          screen_update_needed = 0;
          oled_show_status(effect_enabled, selected_effect);
      }
      status_led_update();
  }

} ===== Bibliography/Resources ====== Export to PDF

1) int32_t)512 « 8);
  static int16_t smoothed_pwm = 128;
  static uint16_t trem_phase = 0;
  // DC removal foarte lent.
  // Semnalul este centrat in jur de 512, dar bias-ul real poate varia.
  dc_q8 += ((((int32_t)raw10 << 8) - dc_q8) >> 10);
  int16_t centered10 = (int16_t)((((int32_t)raw10 << 8) - dc_q8) >> 8);
  // noise gate foarte bland
  uint16_t ax = abs16(centered10);
  if (ax < NOISE_GATE_10BIT)
  {
      centered10 = 0;
  }
  else if (ax < (NOISE_GATE_10BIT * 2))
  {
      centered10 /= 2;
  }
  uint8_t local_enabled = effect_enabled;
  uint8_t local_effect = selected_effect;
  int16_t y = 0;
  if (!local_enabled)
  {
      // Software bypass / clean passthrough
      y = ((int32_t)centered10 * CLEAN_GAIN_Q4) >> 6;
  }
  else if (local_effect == EFFECT_DIST)
  {
      // Distortion subtil:
      // 1. boost moderat
      // 2. soft clipping simetric
      uint8_t gain_q4 = g_dist_gain_q4;
      uint8_t clip_value = g_dist_clip;
      y = ((int32_t)centered10 * gain_q4) >> 6;
      if (y > clip_value)
      {
          y = clip_value;
      }
      else if (y < -(int16_t)clip_value)
      {
          y = -(int16_t)clip_value;
      }
      // limit final mai larg, dar cu clipping clar
      y = clamp_i16(y, -125, 125);
  }
  else
  {
      // Tremolo:
      // clean signal * LFO triunghiular
      y = ((int32_t)centered10 * TREM_GAIN_Q4) >> 6;
      trem_phase += g_trem_step;
      uint8_t tri;
      if (trem_phase & 0x8000)
      {
          tri = (uint8_t)((65535 - trem_phase) >> 8); // 127..0
      }
      else
      {
          tri = (uint8_t)(trem_phase >> 8);           // 0..127
      }
      // tremolo mai pronuntat: volum intre ~15% si ~100%
      uint8_t modulation = 40 + ((uint16_t)tri * 215) / 127;
      y = ((int32_t)y * modulation) >> 8;
  }
  y = clamp_i16(y, -120, 120);
  int16_t target_pwm = 128 + y;
  if (target_pwm < 0)
  {
      target_pwm = 0;
  }
  else if (target_pwm > 255)
  {
      target_pwm = 255;
  }
#if AUDIO_SMOOTH_SHIFT > 0
  smoothed_pwm += ((target_pwm - smoothed_pwm) >> AUDIO_SMOOTH_SHIFT);
  OCR0B = (uint8_t)smoothed_pwm;
#else
  OCR0B = (uint8_t)target_pwm;
#endif } ISR(ADC_vect) {
  uint16_t value = ADC;
  // Dupa schimbarea canalului ADC, aruncam prima mostra.
  if (adc_skip_sample)
  {
      adc_skip_sample = 0;
      return;
  }
  if (current_adc_channel == ADC_AUDIO)
  {
      audio_process_sample(value);
      audio_sample_counter++;
      // Din cand in cand citim potentiometrele.
      // Nu le citim continuu, ca sa pastram audio-ul cat mai stabil.
      if (audio_sample_counter >= 256)
      {
          audio_sample_counter = 0;
          current_adc_channel = ADC_GAIN;
          adc_select_channel(ADC_GAIN);
          adc_skip_sample = 1;
      }
  }
  else if (current_adc_channel == ADC_GAIN)
  {
      pot_gain_raw = (uint8_t)(value >> 2);
      current_adc_channel = ADC_TREMOLO;
      adc_select_channel(ADC_TREMOLO);
      adc_skip_sample = 1;
  }
  else
  {
      pot_tremolo_raw = (uint8_t)(value >> 2);
      current_adc_channel = ADC_AUDIO;
      adc_select_channel(ADC_AUDIO);
      adc_skip_sample = 1;
  }
} ===================================================== OLED LOW LEVEL ===================================================== static void oled_pin_high(uint8_t pin) { OLED_PORT |= (1 « pin); } static void oled_pin_low(uint8_t pin) { OLED_PORT &= ~(1 « pin); } void oled_spi_write(uint8_t data) { for (uint8_t i = 0; i < 8; i++) { if (data & 0x80) { oled_pin_high(OLED_SDA); } else { oled_pin_low(OLED_SDA); } oled_pin_high(OLED_SCL); oled_pin_low(OLED_SCL); data «= 1; } } void oled_command(uint8_t cmd) { oled_pin_low(OLED_DC); oled_spi_write(cmd); } void oled_data(uint8_t data) { oled_pin_high(OLED_DC); oled_spi_write(data); } void oled_reset(void) { oled_pin_low(OLED_RST); _delay_ms(50); oled_pin_high(OLED_RST); _delay_ms(50); } void oled_set_cursor(uint8_t page, uint8_t column) { oled_command(0xB0 + page); oled_command(0x00 + (column & 0x0F)); oled_command(0x10 + ((column » 4) & 0x0F
pm/prj2026/ciprian.popescu0411/remus.berevoescu.1779871993.txt.gz · Last modified: 2026/05/27 11:53 by remus.berevoescu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0