I2C NavKey + AD9850

я думаю мы по разному понимаем это выражение)))

это значит я великий, и вам мне нечего сказать, только пытаться игнорировать, мне приятно, и я тронут)))

в аналоговые, не цифровые! опечаточка…

в целом тема однозначно интересная)))

это хорошо или плохо ?)))

Не понимаешь - так узнай, или спроси, ты ж такой продвинутый.

Green1 угу, буду еще спрашивать почему аннигиляция пробелов называется форматированием… меня ии засмеет….
или наоборот дофига пробелов это форматирование… фиг знает о чем вы… я вообще нубяра, я умею форматировать харды….

это у него троллинг такой, разработчиков

remosYa в наши неспокойные времена, троллить может кто угодно, и кого угодно, при чем оба тролля могут не видеть полноты картины, и им не помешает троллить другого только по своей теме…. так что не известно кто в теме еще и тролль, надо читать, анализировать….

ну не снесли - уже хорошо, ссылка же работающая, а то что МММ всю тему изгавнял, так это он делает не впервой, он тут на особом положении жеж

ua6em случайно не знаете что с ммм случилось ?
раньше вроде хороший программист был, а теперь не понятно что, то ли зазвездился, толи работа ужасная, но знаниями вообще почти не делится…

так после этого высказывания на ум ничего, кроме мания величия не приходит

Спрашивали, как проверить RGB на плате, в коде есть проверка, ядро 2.0.14

// Для ядра 2.0.14
#include <Wire.h>
#include <i2cNavKey.h>
#include <Ticker.h>
#include "AD985X.h"
#include <Adafruit_NeoPixel.h>


#ifndef ESP32
#error ESP32 only example, please select appropriate board
#endif

// Настройки пинов и параметров
#define LED_PIN    48      // GPIO пин, к которому подключен светодиод
#define LED_COUNT  1       // У нас только 1 светодиод на борту
int led_case;
int led_delay;

// Создаем объект для управления лентой/светодиодом
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN,  NEO_GRB + NEO_KHZ800);

// ========== Настройка AD9850 ==========
uint8_t AD_RST = 9;
uint8_t AD_FQUDP = 10;
uint8_t AD_DATA = 11;
uint8_t AD_CLK = 13;
AD9850 freqGen(AD_RST, AD_FQUDP, AD_DATA, AD_CLK);

uint32_t rife_freq = 1100000;
uint32_t rife_prev = 0;
uint32_t rife_maxFreq;

// ========== Таймер для NavKey ==========
Ticker tNavkey;
Ticker tLedRGB;

// ========== ШИМ для модулятора (меандр) ==========
const int pwmPin = 15;
const int pwmChannel = 0;   // Канал LEDC (0-15)
volatile int freq = 1000;   // Частота 1 кГц
const int resolution = 10;  // Разрешение 10 бит (0-1023)
volatile int fcounter = 0;
volatile int fcounter_old = 0;
volatile bool fflag = true;  // true - модуляция, false - несущая
volatile bool fmflag = false;

// ========== Настройка пинов I2C ==========
const int SDA_PIN = 1;
const int SCL_PIN = 3;
const int INT_PIN = 4;

// ========== НАСТРОЙКА PDM (старое ядро 2.x) ==========
#include <driver/i2s.h>

#define I2S_BCLK_PIN 17  // PDM CLK
#define I2S_DOUT_PIN 18  // PDM DATA
#define SAMPLE_RATE 48000
#define BUFFER_SIZE 1024

int16_t pcm_buffer[BUFFER_SIZE];

// ========== Объект NavKey ==========
i2cNavKey navkey(0x10);
volatile bool eventFlag = false;

// ========== Прототипы функций ==========
void fill_sine_buffer(int16_t* buffer, int samples, float freq_hz, int sample_rate);
void initPDM();
void tnav();
void IRAM_ATTR navkeyISR();
void help();

// ========== Callbacks NavKey ==========
void UP_Button_Pressed(i2cNavKey* p) {
  Serial.println("ВВЕРХ нажата");
}

void DOWN_Button_Pressed(i2cNavKey* p) {
  Serial.println("ВНИЗ нажата");
}

void LEFT_Button_Pressed(i2cNavKey* p) {
  Serial.println("ВЛЕВО нажата - переключено на модуляцию");
  fflag = true;
}

void RIGHT_Button_Pressed(i2cNavKey* p) {
  Serial.println("ВПРАВО нажата - переключено на несущую");
  fflag = false;
}

void CENTRAL_Button_Pressed(i2cNavKey* p) {
  Serial.println("ЦЕНТР нажата");
}

void CENTRAL_Button_Double(i2cNavKey* p) {
  Serial.println("Двойное нажатие ЦЕНТР!");
}

void Encoder_Rotate(i2cNavKey* p) {
  Serial.printf("Значение энкодера: %d\n", p->readCounterInt());

  if (fflag) {
    // Меняем частоту модуляции (шаг 10 Гц)
    fcounter = p->readCounterInt();
    if (fcounter > fcounter_old) {
      freq += 10;
      if (freq > 20000) freq = 20000;
      fcounter_old = fcounter;
      fmflag = true;
      // В старом ядре меняем частоту через перенастройку канала
      ledcSetup(pwmChannel, freq, resolution);
      ledcWrite(pwmChannel, 512);
    }
    if (fcounter < fcounter_old) {
      freq -= 10;
      if (freq < 10) freq = 10;
      fcounter_old = fcounter;
      fmflag = true;
      ledcSetup(pwmChannel, freq, resolution);
      ledcWrite(pwmChannel, 512);
    }
  } else {
    // Меняем несущую частоту AD9850 (шаг 1000 Гц)
    fcounter = p->readCounterInt();
    if (fcounter > fcounter_old) {
      rife_freq += 1000;
      if (rife_freq > rife_maxFreq && rife_maxFreq > 0) rife_freq = rife_maxFreq;
      rife_prev = rife_freq;
      fcounter_old = fcounter;
      freqGen.setFrequency(rife_freq);
      Serial.printf("Несущая частота: %lu Гц\n", rife_freq);
    }
    if (fcounter < fcounter_old) {
      if (rife_freq >= 1000) rife_freq -= 1000;
      rife_prev = rife_freq;
      fcounter_old = fcounter;
      freqGen.setFrequency(rife_freq);
      Serial.printf("Несущая частота: %lu Гц\n", rife_freq);
    }
  }
}

// ========== Заполнение буфера синусом ==========
void fill_sine_buffer(int16_t* buffer, int samples, float freq_hz, int sample_rate) {
  for (int i = 0; i < samples; i++) {
    float phase = 2.0f * 3.14159265f * freq_hz * i / sample_rate;
    buffer[i] = (int16_t)(32767.0f * sin(phase));
  }
}

// ========== Инициализация PDM для старого ядра ==========
void initPDM() {
  // Конфигурация I2S в режиме PDM
  i2s_config_t i2s_config = {
    .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_PDM),
    .sample_rate = SAMPLE_RATE,
    .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
    .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
    .communication_format = I2S_COMM_FORMAT_I2S,
    .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
    .dma_buf_count = 8,
    .dma_buf_len = 256,
    .use_apll = false,
    .tx_desc_auto_clear = true,
    .fixed_mclk = 0
  };

  // Конфигурация пинов I2S
  i2s_pin_config_t pin_config = {
    .bck_io_num = I2S_PIN_NO_CHANGE,
    .ws_io_num = I2S_BCLK_PIN,
    .data_out_num = I2S_DOUT_PIN,
    .data_in_num = I2S_PIN_NO_CHANGE
  };

  // Установка конфигурации
  i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
  i2s_set_pin(I2S_NUM_0, &pin_config);
  i2s_set_clk(I2S_NUM_0, SAMPLE_RATE, I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_MONO);

  Serial.println("PDM инициализирован (старое ядро)");
}

// ========== Обработчик прерывания NavKey ==========
void IRAM_ATTR navkeyISR() {
  eventFlag = true;
}

void tnav() {
  if (eventFlag) {
    eventFlag = false;
    navkey.updateStatus();
  }
}

void tled(){
led_delay += 100;
if(led_delay >= 1000){
  led_delay = 0;
  led_case += 1;
  }
  switch (led_case) {
    case 1:
      //выполняется, когда led_case равно 1
      strip.setPixelColor(0, strip.Color(255, 0, 0));
      strip.show();
      break;
    case 2:
      //выполняется когда  led_case равно 2
      strip.setPixelColor(0, strip.Color(0, 255, 0));
      strip.show();
      break; 
    case 3:
      //выполняется когда  led_case равно 3
      strip.setPixelColor(0, strip.Color(0, 0, 255));
      strip.show();
      break; 
    case 4:
      //выполняется когда  led_case равно 4
      strip.setPixelColor(0, strip.Color(255, 255, 255));
      strip.show();
      break;
    case 5:
      //выполняется когда  led_case равно 5
      strip.setPixelColor(0, strip.Color(0, 0, 0));
      strip.show();
      break;        
  }
  if(led_case >=5) led_case = 0;
}

// ========== Справка ==========
void help() {
  Serial.println();
  Serial.println("===== УПРАВЛЕНИЕ =====");
  Serial.println("+ :  увеличить несущую на 1 Гц");
  Serial.println("- :  уменьшить несущую на 1 Гц");
  Serial.println("* :  умножить несущую на 10");
  Serial.println("/ :  разделить несущую на 10");
  Serial.println("? :  показать справку");
  Serial.println("R :  AD9850 reset");
  Serial.println("P :  AD9850 power down");
  Serial.println("U :  AD9850 power up");
  Serial.println("=========================");
  Serial.println("Кнопки NavKey:");
  Serial.println("  ВЛЕВО  - энкодер управляет частотой МОДУЛЯЦИИ");
  Serial.println("  ВПРАВО - энкодер управляет НЕСУЩЕЙ частотой");
  Serial.println("=========================");
}

// ========== SETUP ==========
void setup(void) {
  Serial.begin(115200);
  delay(1000);
  Serial.println("\n\n=== ЗАПУСК СИСТЕМЫ ===\n");

  // ========== Инициализация I2C для NavKey ==========
  Wire.begin(SDA_PIN, SCL_PIN);
  pinMode(INT_PIN, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(INT_PIN), navkeyISR, FALLING);

  Serial.println("Инициализация I2C NavKey...");

  navkey.reset();
  navkey.begin(i2cNavKey::INT_DATA | i2cNavKey::WRAP_ENABLE | i2cNavKey::DIRE_RIGHT | i2cNavKey::IPUP_ENABLE);
  navkey.writeCounter((int32_t)0);
  navkey.writeMax((int32_t)256);
  navkey.writeMin((int32_t)-256);
  navkey.writeStep((int32_t)1);
  navkey.writeDoublePushPeriod(50);

  navkey.onUpPush = UP_Button_Pressed;
  navkey.onDownPush = DOWN_Button_Pressed;
  navkey.onRightPush = RIGHT_Button_Pressed;
  navkey.onLeftPush = LEFT_Button_Pressed;
  navkey.onCentralPush = CENTRAL_Button_Pressed;
  navkey.onCentralDoublePush = CENTRAL_Button_Double;
  navkey.onChange = Encoder_Rotate;

  navkey.autoconfigInterrupt();

  Serial.print("ID CODE: 0x");
  Serial.println(navkey.readIDCode(), HEX);

  tNavkey.attach(0.005, tnav);

  // ========== Инициализация ШИМ (меандр) для старого ядра ==========
  ledcSetup(pwmChannel, freq, resolution);
  ledcAttachPin(pwmPin, pwmChannel);
  ledcWrite(pwmChannel, 512);
  Serial.println("PWM (меандр) на пине 15 включен");

  // ========== Инициализация AD9850 ==========
  Serial.println("Инициализация AD9850...");
  freqGen.begin();
  freqGen.powerUp();
  rife_maxFreq = freqGen.getMaxFrequency();
  Serial.printf("Максимальная частота AD9850: %lu Гц\n", rife_maxFreq);
  freqGen.setFrequency(rife_freq);
  Serial.printf("Несущая частота: %lu Гц\n", rife_freq);

  help();

  // ========== Инициализация PDM ==========
  initPDM();

  // Заполняем буфер синусом 1000 Гц
  fill_sine_buffer(pcm_buffer, BUFFER_SIZE, (float)freq, SAMPLE_RATE);
  Serial.println("PDM генерация синуса запущена");

  Serial.println("\n=== СИСТЕМА ГОТОВА ===\n");

  //LED WS2818RGB
  strip.begin();           // Инициализация светодиода
  strip.show();            // Отправка команды (погасить все)
  strip.setBrightness(50); // Устанавливаем яркость (0-255). 50 — комфортно для глаз.
  Serial.begin(115200);
  Serial.println("Скетч запущен. Светодиод на PIN 48.");
  tLedRGB.attach(0.100, tled);
}

// ========== LOOP ==========
void loop() {
  // ========== Обработка команд из Serial ==========
  if (Serial.available() > 0) {
    int c = Serial.read();
    switch (c) {
      case '?':
        help();
        break;
      case 'R':
        freqGen.reset();
        rife_freq = 1100000;
        freqGen.setFrequency(rife_freq);
        Serial.println("AD9850 сброшен");
        break;
      case 'P':
        freqGen.powerDown();
        Serial.println("AD9850 выключен (power down)");
        break;
      case 'U':
        freqGen.powerUp();
        freqGen.setFrequency(rife_freq);
        Serial.println("AD9850 включен (power up)");
        break;
      case '+':
        rife_freq += 1;
        break;
      case '-':
        if (rife_freq > 0) rife_freq -= 1;
        break;
      case '*':
        rife_freq *= 10;
        break;
      case '/':
        rife_freq /= 10;
        break;
    }
    if (rife_freq > rife_maxFreq && rife_maxFreq > 0) rife_freq = rife_maxFreq;
    if (rife_freq < 0) rife_freq = 0;
  }
  // ========== Обновление частоты AD9850 ==========
  if (rife_prev != rife_freq) {
    rife_prev = rife_freq;
    freqGen.setFrequency(rife_freq);
    Serial.printf("Несущая частота: %lu Гц\n", rife_freq);
  }
  // ========== Отправка данных через PDM ==========
  size_t bytes_written;
  i2s_write(I2S_NUM_0, pcm_buffer, BUFFER_SIZE * sizeof(int16_t), &bytes_written, portMAX_DELAY);
  // ========== Обновление буфера при изменении частоты модуляции ==========
  if (fmflag) {
    fmflag = false;
    fill_sine_buffer(pcm_buffer, BUFFER_SIZE, (float)freq, SAMPLE_RATE);
    Serial.printf("Частота модуляции изменена: %d Гц\n", freq);
  }

}

@толстый, это ты спрашивал ?:rofl:

вот ты фома неверующий )))

уговорил, удалю.

это шедевр!

а тебя нигде в интернете не спрашивали, например какой сегодня день недели?

@толстый, ВОЗВРАЩАЙ ПОСТ, ТЫ БЫЛ ПРАВ!

вот сейчас только что ты спросил и что?

что, что, код надо писать, по определению дня!

тут не публикуй, на Озоне, Илья К. видимо будет благодарен.

правилами Озона это запрещено, он не пропустит, тут форум, всё логично, да сегодня 29 апреля 2026 го от рождества Христова, а то спросил, а я оставил без ответа…это строго по правилам русского языка ежели что

Вить, сосредоточься и выдай хоть одно предложение по теме.
Ты Илью то в курс дела поставил?

А вообще, свинство такую простыню не прятать под спойлер. Ладно, бабос, он молодой, ему простительно. А вообще это называется по##измом.

форум уже давно не вываливает весь скетч, отображает в окне, строк 30

Не вываливает, но прокрутка работает. Палец устаёт.