DSP - радиоприёмник на SI4735

Voevoda
Сообщения: 121
Зарегистрирован: 23 июн 2021, 18:33
Позывной: R7KEO
Город: г.Саки
Имя: Владимир
Благодарил (а): 5 раз
Поблагодарили: 21 раз

DSP - радиоприёмник на SI4735

Сообщение Voevoda » 06 сен 2021, 15:21

Прошил сегодня свой ATS 25, шрифты и кнопки симпотнее. Вроде тач отзывчивее или показалось.
Информация на дисплее стала более понятная.
Было.
Было.
Стало.
Стало.

Voevoda
Сообщения: 121
Зарегистрирован: 23 июн 2021, 18:33
Позывной: R7KEO
Город: г.Саки
Имя: Владимир
Благодарил (а): 5 раз
Поблагодарили: 21 раз

DSP - радиоприёмник на SI4735

Сообщение Voevoda » 06 сен 2021, 19:14

Немножко видео снял.
phpBB [video]


Voevoda
Сообщения: 121
Зарегистрирован: 23 июн 2021, 18:33
Позывной: R7KEO
Город: г.Саки
Имя: Владимир
Благодарил (а): 5 раз
Поблагодарили: 21 раз

DSP - радиоприёмник на SI4735

Сообщение Voevoda » 08 сен 2021, 15:46

Копошусь.
В прошивке есть такой кусочек.
Который вы можете под свои станции переписать и вызывать кнопкой Preset
FM_Preset preset[] = {

8930 , "West", // 00 West
9890 , "NPO R1", // 01 NPO R1
9260 , "NPO R2", // 02 NPO R2
9680 , "NPO R3-FM", // 03 NPO R3-FM
9470 , "NPO R4", // 04 NPO R4
9340 , "RIJNMOND", // 05 RIJNMOND
9050 , "SUBLIME", // 06 SUBLIME
9130 , "BNR", // 07 BNR
9520 , "SLAM", // 08 SLAM
9620 , "ZFM", // 09 ZFM
9760 , "DECIBEL", // 10 DECIBEL
10040 , "QMUSIC", // 11 QMUSIC
10150 , "SKYRADIO", // 12 SKYRADIO
10270 , "RADIO 538", // 13 RADIO 538
10320 , "VERONICA", // 14 VERONICA
10380 , "RADIO 10", // 15 RADIO 10
10460 , "100% NL", // 16 100% NL
9220 , "L-FM", // 17 L-FM
10760 , "FEELGOOD" // 18 FEELGOOD Radio

Криворукий
Сообщения: 557
Зарегистрирован: 20 ноя 2019, 19:00
Город: Ленинград
Имя: Андрей
Благодарил (а): 151 раз
Поблагодарили: 164 раза

DSP - радиоприёмник на SI4735

Сообщение Криворукий » 26 сен 2021, 19:17

Voevoda, Open-minded, приветствую и есть вопрос ;)
Какой прошивкой прошивались (ATS-25)? В версии прошивки 3.1 почитал описание (перевод с помощью гугла):

"Я также сделал своего рода подавление неприятного шума при настройке в SSB с шагом 1 кГц. Этот шум вызывает регулятор AGC. Он длится около 350 мс, достигая пика в первые 200 мс. Я отключаю сигнал LF с регулируемым временем, делая два транзистора в цепи LF проводящими. Если время слишком велико, настройка становится трудной. Затем требуется слишком много времени, прежде чем станет слышен результат изменения частоты. 200 мсек кажутся хорошим компромиссом. Это время можно установить в строке 115 скетча V3.1:
#define MIN_ELAPSED_AudMut_TIME 200.
Если здесь введен 0, функция отключена. "

Я так понял ПШИК глушится с помощью двух транзисторов, которые работают на "MUTE". Интересно узнать, насколько комфортнее стала настройка?

Voevoda
Сообщения: 121
Зарегистрирован: 23 июн 2021, 18:33
Позывной: R7KEO
Город: г.Саки
Имя: Владимир
Благодарил (а): 5 раз
Поблагодарили: 21 раз

DSP - радиоприёмник на SI4735

Сообщение Voevoda » 26 сен 2021, 21:54

Криворукий писал(а):
26 сен 2021, 19:17
Я так понял ПШИК глушится с помощью двух транзисторов, которые работают на "MUTE". Интересно узнать, насколько комфортнее стала настройка?
Дело в том, что на старой прошивке я его и не слушал толком.
И пользуюсь только на новой.
Как по мне, вполне комфортно слушать.
Были бы вы где рядом, дал бы покрутить.

Криворукий
Сообщения: 557
Зарегистрирован: 20 ноя 2019, 19:00
Город: Ленинград
Имя: Андрей
Благодарил (а): 151 раз
Поблагодарили: 164 раза

DSP - радиоприёмник на SI4735

Сообщение Криворукий » 26 сен 2021, 23:28

Voevoda, благодарю!
Купил я дисплей 2.8 и esp32. Были мысли не собирать ту часть схемы с двумя транзисторами, которая отвечает за MUTE. Пересмотрел видео после перепрошивки приёмника и вроде как не особо "пшикает" при настройке в SSB режиме, т.е. в принципе это работает и можно покрутить это значение.

Прошил ESP и подключил дисплей - прошивка запустилась.
ats_diy.jpg

Open-minded
Сообщения: 47
Зарегистрирован: 19 июл 2021, 09:17
Позывной: UA6WSH
Город: Махачкала
Имя: Назим
Благодарил (а): 44 раза
Поблагодарили: 16 раз

DSP - радиоприёмник на SI4735

Сообщение Open-minded » 02 окт 2021, 11:39

У меня прошивка крайняя на данный момент 3.1. Транзисторы отвечающие за MUTE стоят, как без них не знаю т.к впаял их сразу при сборке. Участок кода с бразильскими станциями перебил на местные, также подкорректировал чуток стартовые частоты для каждого диапазона. Модуль усилителя ЗЧ сменил. Установил магнитную антенну индуктивностью в районе 310uH. Входные цепи КВ выполнил как на прикреплённом изображении. Думаю об усилителе для работы с телескопической антенной, к работе на 30 метровый кусок провода за окном претензий нет.
sch_sfgN10xXUJ.jpg

Криворукий
Сообщения: 557
Зарегистрирован: 20 ноя 2019, 19:00
Город: Ленинград
Имя: Андрей
Благодарил (а): 151 раз
Поблагодарили: 164 раза

DSP - радиоприёмник на SI4735

Сообщение Криворукий » 07 окт 2021, 22:39

Собрал макет приёмника.
Нарисовал плату (как обычно без общей шины под ЧПУ):
ats3.jpg
После того как спаял выяснилось, что энкодер подключил вместо RX2 и TX2, к TX и RX.
Пришлось исправлять в программе и энкодер заработал.
Не понравилось, что по умолчанию в прошивке в выборе диапазона, на вещательных прописана полоса фильтра 2 кГц, а в радиолюбительских - 2.2 кГц. Не понял почему так сделано, но нужно будет подправить.
Вид готовой платы:
ats1.jpg
Макет в работе:
ats2.jpg
Работает хорошо, прошивка 3.1 ;)

N0D
Сообщения: 13
Зарегистрирован: 21 окт 2019, 23:06
Позывной: UA3YMC
Город: Брянск
Поблагодарили: 3 раза

DSP - радиоприёмник на SI4735

Сообщение N0D » 11 окт 2021, 10:55

Коллеги, а не кто не пытался подружить SI4735(SI4732) с Raspberry Pi ?
Я вот пытаюсь и пока безуспешно.
Идея сделать удаленный интернет приемник, т.е. с подключением через интернет через браузер. Ход моих мыслей был такой, раз приемник имеет управление i2c и цифровой выход звука i2s, а у малины 3.3в логика тут уже сама судьба намекает их подружить.
Железо: Raspberry Pi zero и переходная плата с SI4732.
В качестве ПО собирался использовать python скрипт который нашел на github. Все спаял, и тут вылезла засада, для запуска данного скрипта требуется модуль ядра(звук i2s) о котором есть упоминание в самом скрипте, и которое я заметил не сразу. Я попытался его скомпилировать, но безуспешно. Навыков программирования не хватает.
Пытался использовать другой модуль ядра i2s, но тоже безрезультатно.
Я уже было отчаялся, но тут нашел описание как можно использовать код написанный для arduino в raspberry pi, и что как раз этот код для управления SI4732. К сожалению это описание очень скудное, из разряда попробовал-что-то-получилось и без какой либо конкретики. Но даже так я решил попробовать и кое что таки получилось.
Установил framework, добавил библиотеку SI4735 от pu2clr, и модифицировав примеры получил следующее:

Код: Выделить всё

#include <SI4735.h>
#include <stdio.h>
#include <Bridge.h>
#include <Console.h>

#define RESET_PIN 12

#define AM_FUNCTION 1
#define FM_FUNCTION 0

#define SI473X_ANALOG_AUDIO 0b00000101          // Analog Audio Inputs
#define SI473X_DIGITAL_AUDIO1 0b00001011        // Digital audio output (DCLK, LOUT/DFS, ROUT/DIO)
#define SI473X_DIGITAL_AUDIO2 0b10110000        // Digital audio outputs (DCLK, DFS, DIO)
#define SI473X_ANALOG_DIGITAL_AUDIO 0b10110101  // Analog and digital audio outputs (LOUT/ROUT and DCLK, DFS,DIO)
#define XOSCEN_CRYSTAL 1                        // Use crystal oscillator
#define XOSCEN_RCLK 0                           // Use external RCLK (crystal oscillator disabled).

uint16_t currentFrequency;
uint16_t previousFrequency;
uint8_t bandwidthIdx = 0;
const char *bandwidth[] = {"6", "4", "3", "2", "1", "1.8", "2.5"};

SI4735 rx;

void setup()
{
  digitalWrite(RESET_PIN, HIGH);
  Bridge.begin();
  Console.begin();
  Console.print("AM and FM station tuning test.\n");
  showHelp();


  // Look for the Si47XX I2C bus address
  int16_t si4735Addr = rx.getDeviceI2CAddress(RESET_PIN);
  if ( si4735Addr == 0 ) {
    Console.print("Si473X not found!\n");
    // Serial.flush();
    while (1);
  } else {
    Console.print("Si473X found!\n");
  }


  delay(500);

  //rx.setup(RESET_PIN, FM_FUNCTION);
  rx.setRefClock(32768);
  rx.setRefClockPrescaler(1);
  rx.setup(RESET_PIN, -1, 1, SI473X_DIGITAL_AUDIO2, XOSCEN_RCLK);
  // Starts defaul radio function and band (FM; from 84 to 108 MHz; 103.9 MHz; step 100kHz)
  rx.setFM(8400, 10800, 10650, 10);
  rx.setSeekFmLimits(6400, 10800);
  rx.setSeekFmSpacing(5);
  delay(500);
  currentFrequency = previousFrequency = rx.getFrequency();
  rx.setVolume(45);
  showStatus();
}

void showHelp()
{

  Console.print("\nType F to FM; A to MW; 1 to All Band (100kHz to 30MHz)");
  Console.print("\nType U to increase and D to decrease the frequency");
  Console.print("\nType S or s to seek station Up or Down");
  Console.print("\nType + or - to volume Up or Down");
  Console.print("\nType 0 to show current status");
  Console.print("\nType B to change Bandwidth filter");
  Console.print("\nType 4 to 8 (4 to step 1; 5 to step 5kHz; 6 to 10kHz; 7 to 100kHz; 8 to 1000kHz)");
  Console.print("\nType ? to this help.");
  Console.print("\n==================================================\n");
  delay(1000);
}

// Show current frequency
void showStatus()
{
  // rx.getStatus();
  previousFrequency = currentFrequency = rx.getFrequency();
  rx.getCurrentReceivedSignalQuality();
  Console.print("\nYou are tuned on ");
  if (rx.isCurrentTuneFM())
  {
    Console.print((currentFrequency / 100.0));
    Console.print("MHz ");
    Console.print((rx.getCurrentPilot()) ? "STEREO" : "MONO");
  }
  else
  {
    Console.print(currentFrequency);
    Console.print("kHz ");
  }
  Console.print(" [SNR:");
  Console.print(rx.getCurrentSNR());
  Console.print("dB");

  Console.print(" Signal:");
  Console.print(rx.getCurrentRSSI());
  Console.print("dBuV]");
}

void showFrequency( uint16_t freq ) {

  if (rx.isCurrentTuneFM())
  {
    Console.print(freq / 100.0);
    Console.print("MHz ");
  }
  else
  {
    Console.print(freq);
    Console.print("kHz");
  }

}


// Main
void loop()
{
  while (!Console);
  if (Console.available() > 0)
  {
    char key = Console.read();
    switch (key)
    {
      case '+':
        rx.volumeUp();
        break;
      case '-':
        rx.volumeDown();
        break;
      case 'a':
      case 'A':
        rx.setAM(520, 1750, 810, 10);
        rx.setSeekAmLimits(520, 1750);
        rx.setSeekAmSpacing(10); // spacing 10kHz
        break;
      case 'f':
      case 'F':
        rx.setFM(8600, 10800, 10390, 50);
        rx.setSeekAmRssiThreshold(0);
        rx.setSeekAmSrnThreshold(10);
        break;
      case '1':
        rx.setAM(100, 30000, 7200, 5);
        rx.setSeekAmLimits(100, 30000);   // Range for seeking.
        rx.setSeekAmSpacing(1); // spacing 1kHz
        Console.print("\nALL - LW/MW/SW");
        break;
      case 'U':
      case 'u':
        rx.frequencyUp();
        break;
      case 'D':
      case 'd':
        rx.frequencyDown();
        break;
      case 'b':
      case 'B':
        if (rx.isCurrentTuneFM())
        {
          Console.print("\nNot valid for FM");
        }
        else
        {
          if (bandwidthIdx > 6)
            bandwidthIdx = 0;
          rx.setBandwidth(bandwidthIdx, 1);
          Console.print("Filter - Bandwidth: ");
          Console.print(bandwidth[bandwidthIdx]);
          Console.print(" kHz");
          bandwidthIdx++;
        }
        break;
      case 'S':
        rx.seekStationProgress(showFrequency, 1);
        // rx.seekStationUp();
        break;
      case 's':
        rx.seekStationProgress(showFrequency, 0);
        // rx.seekStationDown();
        break;
      case '0':
        showStatus();
        break;
      case '4':
        rx.setFrequencyStep(1);
        Console.print("\nStep 1");
        break;
      case '5':
        rx.setFrequencyStep(5);
        Console.print("\nStep 5");
        break;
      case '6':
        rx.setFrequencyStep(10);
        Console.print("\nStep 10");
        break;
      case '7':
        rx.setFrequencyStep(100);
        Console.print("\nStep 100");
        break;
      case '8':
        rx.setFrequencyStep(1000);
        Console.print("\nStep 1000");
        break;
      case '?':
        showHelp();
        break;
      default:
        break;
    }
  }
  delay(100);
  currentFrequency = rx.getCurrentFrequency();
  if (currentFrequency != previousFrequency)
  {
    previousFrequency = currentFrequency;
    showStatus();
    delay(300);
  }
}
Данный код не доведен до ума, проблемы следующие:
Так как для цифрового звука i2s нужно внешнее тактирование чипа приемника, часового кварца на плате нет, его функции заменяет GPIO 4 малины, для запуска тактирования используются комманды:
# gpio -g mode 4 clock
# gpio -g clock 4 32768
Как это сделать непосредственно из программы я пока не понял.
После запуска программы можно получить управление чипом приемника. Он определяется, сканирует и находит станцию FM, но получить звук я тоже пока не могу.

Нет ли на этом форуме людей которым данная тема была бы интересна и кто мог бы помочь с доведением ее до ума?

N0D
Сообщения: 13
Зарегистрирован: 21 окт 2019, 23:06
Позывной: UA3YMC
Город: Брянск
Поблагодарили: 3 раза

DSP - радиоприёмник на SI4735

Сообщение N0D » 14 окт 2021, 13:28

Может кому пригодится:
Завел этот python скрипт
Нужно:
поставить звук i2s https://github.com/RobleLab/snd-i2s_rpi (Installing as a DKMS module)
загрузить модуль: sudo modprobe snd-i2s_rpi rpi_platform_generation=0
проверить: aplay -L (должна появится зв. карта sndrpii2scard)
установить: https://github.com/quick2wire/quick2wire-python-api
нужно будет доставить:
sudo apt-get install -y python3-setuptools
sudo apt-get install -y python3-pip
установить библиотеку alsa для python: sudo -H pip3 install pyalsaaudio
если скрипт будет ругаться на отсутствие /dev/i2c-0 сделать симлинк с /dev/i2s-1 (sudo ln -s /dev/i2c-1 /dev/i2c-0)
запустить скрипт: python3 sipiradio.py
Сам скрипт немного поправил:
Spoiler

Код: Выделить всё

#!/usr/bin/python3
import quick2wire.i2c as i2c
import time
import RPi.GPIO as GPIO
import alsaaudio
import threading
import logging
import sys
import subprocess
import shlex


#Work in progress library for Si473x for Raspberry Pi by Jonathan Thorpe <jt@jonthorpe.net>
#SiPiRadio
#
#Wiring:
# RPi                      Si473x Module
# i2s SDA                  i2c SDIO
# i2s SCL                  i2c SCLK
#
# GPIO 15                  RESET
# GPIO 4                   RCLK
#
# PCM_CLK                  DCLK
# PCM_FS                   DFS
# PCM_IN                   DOUT
#
# GPIO 4 must be set to clock mode at the appropriate rate.
# Can't find a way to do this in Python yet - use the command line:
#   gpio -g mode 4 clock
#   gpio -g clock 4 34406
#

cmd = shlex.split("gpio -g mode 4 clock")
subprocess.call(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
cmd = shlex.split("gpio -g clock 4 34406")
subprocess.call(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)

# Before running this program, you need to load the my_loader.c kernel module from here:
# https://www.raspberrypi.org/forums/viewtopic.php?f=44&t=91237
# 
# Before compiling this module, ensure daifmt is set in clock and frame slave mode (Si47xx operates in slave only mode):
# .daifmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS
#
#
# TODO (essentially implement more of the programmer's guide):
#   1. Support AM/SW/LW
#   2. Get Status information
#   3. FM RDS information
#   4. Make sure I'm using ALSA properly - seems a bit hacky
#
# Acknowledgments:
#    https://github.com/rickeywang/Si4737_i2c was useful for seeing how to program this device over i2c

logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)

# ===========================================================================
# Si473x I2C / I2S Class
# ===========================================================================

class SiPiRadio():
  #GPIO pin for issuing the device reset
  GPIO_RESET=15

  #Si473x i2c address
  #I2C_ADDRESS=0x63
  I2C_ADDRESS=0x11

  #The i2s Device as found from ALSA (my_loader.ko)
  #AUDIO_IN_DEV="hw:CARD=sndrpisimplecar,DEV=0"
  AUDIO_IN_DEV="hw:CARD=sndrpii2scard,DEV=0"
  #Default device to send audio out of
  AUDIO_OUT_DEV="hw:CARD=b1,DEV=0"

  #Audio sample rate
  AUDIO_SAMPLE_RATE=48000
  AUDIO_CHANNELS=2
  AUDIO_BITS_SAMPLE=16

  pcm_audio_in=None
  pcm_audio_out=None

  REFCLK_FREQ=34406
  REFCLK_PRESCALE=1

  #Constants
  SI4735_CMD_POWER_UP=0x01
  SI4735_CMD_GET_REV=0x10
  SI4735_CMD_POWER_DOWN=0x11
  SI4735_CMD_SET_PROPERTY=0x12
  SI4735_CMD_GET_PROPERTY=0x13
  SI4735_CMD_FM_TUNE_FREQ=0x20, 0x00
  SI4735_CMD_FM_TUNE_STATUS=0x22
  SI4735_CMD_GET_INT_STATUS=0x14

  #Define Si4735 Output modes
  SI4735_OUT_RDS=0x00  # RDS only
  SI4735_OUT_ANALOG=0x05
  SI4735_OUT_DIGITAL1=0x0B # DCLK, LOUT/DFS, ROUT/DIO
  SI4735_OUT_DIGITAL2=0xB0 # DCLK, DFS, DIO
  SI4735_OUT_BOTH=(SI4735_OUT_ANALOG | SI4735_OUT_DIGITAL2)

  #Statuses
  SI4735_STATUS_CTS=0x80
  SI4735_STATUS_ERR=0x40
  SI4735_STATUS_STCINT=0x01

  #Properties
  SI4735_PROP_REFCLK_FREQ=0x00, 0x02, 0x01
  SI4735_PROP_REFCLK_PRESCALE=0x00, 0x02, 0x02
  SI4735_PROP_DIGITAL_OUTPUT_SAMPLE_RATE=0x00, 0x01, 0x04
  SI4735_PROP_DIGITAL_OUTPUT_FORMAT=0x00, 0x01, 0x02
  SI4735_PROP_RX_VOLUME=0x40, 0x00

  #Flags
  SI4735_DIGITAL_I2S=0x01, 0x00

  SI4735_FLG_INTACK=0x01

  #Modes
  SI4735_MODE_LW=0
  SI4735_MODE_AM=1
  SI4735_MODE_SW=2
  SI4735_MODE_FM=3
  mode=SI4735_MODE_FM

  record_stop = threading.Event()
  record_thread = None

  def byteHigh(self, val):
    return val >> 8

  def byteLow(self, val):
    return val & 0xFF

  def sendCommand(self, cmd, *args):
    with i2c.I2CMaster() as bus:
      if (isinstance(cmd, int)):
        bytesToSend=(cmd,) + args
      else:
        bytesToSend=cmd + args

      logging.debug("Command: " + " ".join('0x%02x' % i for i in bytesToSend))
      bus.transaction(i2c.writing_bytes(self.I2C_ADDRESS, *bytesToSend))

  def getStatus(self):
    with i2c.I2CMaster() as bus:
        return bus.transaction(i2c.reading(self.I2C_ADDRESS, 1))[0][0]

  def ctsWait(self):
    status = 0
    while not status & self.SI4735_STATUS_CTS:
      status = self.getStatus()
      logging.debug("Returned status is: {0:#04x}".format(status))

  def intWait(self, interruptType):
    status = 0

    while not status & interruptType:
      self.sendCommand(self.SI4735_CMD_GET_INT_STATUS, 0x00)
      time.sleep(0.125)
      status = self.getStatus()
      if (not status & interruptType):
        logging.debug('Still waiting. Got status {0:#04x}'.format(status))

  def sendWait(self, cmd, *args):
    self.sendCommand(cmd, *args)
    self.ctsWait()

  def setProperty(self, property, *args):
    self.sendWait((self.SI4735_CMD_SET_PROPERTY,)+property+args)

  def setupCaptureDevice(self):
    logging.debug('Setting up capture device')
    self.pcm_audio_in = alsaaudio.PCM(type=alsaaudio.PCM_CAPTURE, mode=alsaaudio.PCM_NORMAL, device=self.AUDIO_IN_DEV, rate=self.AUDIO_SAMPLE_RATE, channels=self.AUDIO_CHANNELS, format=alsaaudio.PCM_FORMAT_S16_LE, periodsize=160)
# to old alsa
#    self.pcm_audio_in = alsaaudio.PCM(alsaaudio.PCM_CAPTURE, alsaaudio.PCM_NORMAL, self.AUDIO_IN_DEV)
#    self.pcm_audio_in.setchannels(self.AUDIO_CHANNELS)
#    self.pcm_audio_in.setrate(self.AUDIO_SAMPLE_RATE)
#    self.pcm_audio_in.setformat(alsaaudio.PCM_FORMAT_S16_LE)

  def setupPlaybackDevice(self):
    logging.debug('Setting up playback device')
    self.pcm_audio_out = alsaaudio.PCM(type=alsaaudio.PCM_PLAYBACK, mode=alsaaudio.PCM_NONBLOCK, device=self.AUDIO_OUT_DEV, rate=self.AUDIO_SAMPLE_RATE, channels=self.AUDIO_CHANNELS, format=alsaaudio.PCM_FORMAT_S16_LE)
# to old alsa
#    self.pcm_audio_out = alsaaudio.PCM(alsaaudio.PCM_PLAYBACK, alsaaudio.PCM_NONBLOCK)
#    self.pcm_audio_out.setchannels(self.AUDIO_CHANNELS)
#    self.pcm_audio_out.setrate(self.AUDIO_SAMPLE_RATE)
#    self.pcm_audio_out.setformat(alsaaudio.PCM_FORMAT_S16_LE)
    logging.debug('Done setting up playback device')

  def captureAudio(self, arg, stop_event):
#   self.pcm_audio_in.setperiodsize(160)

   while(not self.record_stop.is_set()):
      l, data = self.pcm_audio_in.read()
      if l:
        #logging.debug("Sending output audio...")
        self.pcm_audio_out.write(data)

  def powerUp(self):
    logging.debug('Powering up si473x')
    GPIO.output(self.GPIO_RESET, False)
    time.sleep(0.01)
    GPIO.output(self.GPIO_RESET, True)
    time.sleep(0.01)

    self.sendWait(self.SI4735_CMD_POWER_UP, 0x00, self.SI4735_OUT_BOTH)

    #Configure REFCLK
    self.setProperty(self.SI4735_PROP_REFCLK_FREQ,
                     self.byteHigh(self.REFCLK_FREQ),
                     self.byteLow(self.REFCLK_FREQ))

    self.setProperty(self.SI4735_PROP_REFCLK_PRESCALE,
                     self.byteHigh(self.REFCLK_PRESCALE),
                     self.byteLow(self.REFCLK_PRESCALE))

    self.record_thread.start()

    self.setProperty(self.SI4735_PROP_DIGITAL_OUTPUT_SAMPLE_RATE,
                     self.byteHigh(self.AUDIO_SAMPLE_RATE),
                     self.byteLow(self.AUDIO_SAMPLE_RATE))

    self.setProperty(self.SI4735_PROP_DIGITAL_OUTPUT_FORMAT, *self.SI4735_DIGITAL_I2S)

  def setFrequency(self, freq):
    if(self.mode == self.SI4735_MODE_FM):
      logging.debug('Setting frequency to {0} ({1:#04x} {2:#04x})'.format(freq, self.byteHigh(freq), self.byteLow(freq)))
      self.sendWait(self.SI4735_CMD_FM_TUNE_FREQ, self.byteHigh(freq), self.byteLow(freq), 0x00, 0x00)

    logging.debug('Frequency set, just waiting for tuning to complete')
    self.intWait(self.SI4735_STATUS_STCINT)

    if(self.mode == self.SI4735_MODE_FM):
      self.sendCommand(self.SI4735_CMD_FM_TUNE_STATUS, self.SI4735_FLG_INTACK)

  def setVolume(self, vol):
    logging.debug('Setting volume to {0:#04x}'.format(vol))
    self.setProperty(self.SI4735_PROP_RX_VOLUME, vol)

  def init(self):    
    self.setupCaptureDevice()
    self.setupPlaybackDevice()

  def __init__(self):
    self.record_thread = threading.Thread(target=self.captureAudio, args=(1, self.record_stop))

radio = SiPiRadio()
GPIO.setmode(GPIO.BOARD)
GPIO.setup(radio.GPIO_RESET, GPIO.OUT)

radio.init()
radio.powerUp()
radio.setVolume(0x63)
radio.setFrequency(10650)

logging.debug("Execution Complete")

print("q=quit")
cmd = ""
while True:
   cmd = input("Command: ")
   if(cmd=="q"):
      break
   
radio.record_stop.set()

GPIO.cleanup()

Результат: Скрипт работает, микросхема приемника управляется, отвечает на команды. Но звука по i2s нет. Теоретически будет работать с аналоговым выходом.

Ответить

Вернуться в «Микроконтроллеры и программирование»