maanantai, 19. helmikuu 2018

Very simple Python RTL-SDR spectrum analyzer

Python wrapper for librtlsdr: https://github.com/roger-/pyrtlsdr

import matplotlib.pyplot as plt
import matplotlib.pyplot as plts
from rtlsdr import *

sdr = RtlSdr()

ppm = sdr.get_freq_correction()
print 'Frequency correction ' + str(ppm)
tuner_type = sdr.get_tuner_type()
print 'Tuner type ' + str(tuner_type)

sdr.sample_rate = 2.4e6
sdr.center_freq = 392.0125e6
sdr.gain = 7

plts.title('Power spectral density')
plts.xlabel('Frequency (MHz)')
plts.ylabel('Relative power (dB)')
plts.grid(True)
lines, = plts.plot(0, 0)
plts.ion()
fig = plts.figure()

while True:
    samples = sdr.read_samples(256*1024)
    plt.psd(samples, NFFT=512, Fs=sdr.sample_rate/1e6, Fc=sdr.center_freq/1e6)
    line = plt.gca().lines[0]
    lines.set_xdata(line.get_xdata())
    lines.set_ydata(line.get_ydata())
    fig.canvas.draw()

rtlsdr-fft.jpg

 

sunnuntai, 11. helmikuu 2018

Arduino & CC1101 - 1

Ebaystä löytyy muutamalla eurolla TI CC1101 pohjaisia SPI (ISM 433 MHz...) lähetin-vastaanottimia (2-FSK, 4-FSK, GFSK, MSK, ASK/OOK)
https://www.ebay.com/sch/i.html?_from=R40&_sacat=0&_nkw=arduino+cc1101&_sop=15

Datasheet: http://www.ti.com/lit/ds/symlink/cc1101.pdf

Netistä löytyy pari kirjastoa Arduinolle CC1101 ohjaukseen: https://github.com/veonik/arduino-cc1101

Modasin ym. kirjastoa siten että void CC1101::setCCregs(void) metodissa kommentoin sendData(packet); lauseen.

IMG_20180211_142509648.jpg

http://www.electrodragon.com/w/images/a/a7/Cc1101_2_bb.png

CC1101:n laittaminen RX tilaan onnistui lopulta kun resetoi Arduinon muutaman kerran/odotteli vähän aikaa. Jostain syystä piiri jää tuon tuostakin RX CALIBRATE tilaan ....
cc1101-k.jpg

#include <Arduino.h>
#include <cc1101.h>
#include <ccpacket.h>

// Speed      MDMCFG4 MDMCFG3
// 31.25      C0      43        PSK31
// 45.5       C0      D5        RTTY
// 63         C1      45        PSK63
// 441        C4      1D        FSK441
//
// 75         C1      83
// 150        C2      83
// 300        C3      83
// 600        C4      83
// 1200       C5      83
// 2400       C6      83
// 4800       C7      83
// 9600       C8      83
// 19200      C9      83
// 38400      CA      83
// 76800      CB      83
// 153600     CC      83
// 307200     CD      83
//
// 1800       C6      22
// 3600       C7      22
// 7200       C8      22
// 14400      C9      22
// 28800      CA      22
// 57600      CB      22
// 115200     CC      22
// 230400     CD      22

#define SERIAL_SPEED              9600

#define CC1101_RX_DELAY           50

#define CC1101_VAL_FREQ2_433      0x10
#define CC1101_VAL_FREQ1_433      0xA7
#define CC1101_VAL_FREQ0_433      0x10

#define CC1101_VAL_FREQ2_423875   0x10
#define CC1101_VAL_FREQ1_423875   0x4D
#define CC1101_VAL_FREQ0_423875   0x62

#define CC1101_VAL_FREQ2_4200125  0x10
#define CC1101_VAL_FREQ1_4200125  0x27
#define CC1101_VAL_FREQ0_4200125  0x5A

#define CC1101_VAL_FREQ2_413300   0x0F
#define CC1101_VAL_FREQ1_413300   0xE4
#define CC1101_VAL_FREQ0_413300   0x84

#define CC1101_PKTLEN_VALUE       0xFF
// Fixed packet length, FIFO for RX/TX, CRC calculation off, data whitening off
#define CC1101_PKTCTROL0_VALUE    0x00
#define CC1101_PKTCTRL1_VALUE     0x04
#define CC1101_ADDR_VALUE         0x00
#define CC1101_CHANNR_VALUE       0x05
// 9600 bps. Digital channel bandwidth filter: 58 kHz
#define CC1101_MDMCFG4_VALUE      0xC9
#define CC1101_MDMCFG3_VALUE      0x83
// Enable digital DC blocking filter, ASK modulation, disable Manchester encoding, no preamble/sync
#define CC1101_MDMCFG2_VALUE      B00110000
// Disable FEC
#define CC1101_MDMCFG1_VALUE      B00100010
#define CC1101_MDMCFG0_VALUE      0xF8
// Modem deviation +- kHz
#define CC1101_DEVIATN_25         B01000000 // 25.4 kHz
#define CC1101_DEVIATN_20         B00110101 // 20.63 kHz
#define CC1101_DEVIATN_15_8       B00110010 // 15.87 kHz
#define CC1101_DEVIATN_12_7       B00110000 // 12.7 kHz
#define CC1101_DEVIATN_10         B00100101 // 10.3 kHz
#define CC1101_DEVIATN_7_9        B00100010 // 7.9 kHz
#define CC1101_DEVIATN_7_1        B00100001 // 7.1 kHz
#define CC1101_DEVIATN_6_3        B00100000 // 6.3 kHz

CC1101 radio;

volatile bool packetWaiting = false;

void messageReceived() {
  packetWaiting = true;
}

void setup() {
  Serial.begin(SERIAL_SPEED);
  radio.init();
  setFreq(CC1101_VAL_FREQ2_433, CC1101_VAL_FREQ2_433, CC1101_VAL_FREQ2_433);
  // disable addr chk
  radio.writeReg(CC1101_PKTCTRL1, CC1101_PKTCTRL1_VALUE);
 
  radio.writeReg(CC1101_PKTLEN, CC1101_PKTLEN_VALUE);
  radio.writeReg(CC1101_PKTCTRL0, CC1101_PKTCTROL0_VALUE);
  radio.writeReg(CC1101_ADDR, CC1101_ADDR_VALUE);
  radio.writeReg(CC1101_CHANNR, CC1101_CHANNR_VALUE);
  radio.writeReg(CC1101_MDMCFG4, CC1101_MDMCFG4_VALUE);
  radio.writeReg(CC1101_MDMCFG3, CC1101_MDMCFG3_VALUE);
  radio.writeReg(CC1101_MDMCFG2, CC1101_MDMCFG2_VALUE);
  radio.writeReg(CC1101_MDMCFG1, CC1101_MDMCFG1_VALUE);
  radio.writeReg(CC1101_MDMCFG0, CC1101_MDMCFG0_VALUE);
  radio.writeReg(CC1101_DEVIATN, CC1101_DEVIATN_25);

  CCPACKET packet;
  packet.length = 0;
  radio.setRxState();

  uint16_t t = 0;
  uint8_t marcState = radio.readStatusReg(CC1101_MARCSTATE) & 0x1F;
  Serial.println(marcState);
  while (marcState != 0x0D)
  {
    marcState = radio.readStatusReg(CC1101_MARCSTATE) & 0x1F;
  }
    
  Serial.print(F("CC1101 partnum "));
  Serial.println(radio.readStatusReg(CC1101_PARTNUM));
  Serial.print(F("CC1101 version "));
  Serial.println(radio.readStatusReg(CC1101_VERSION));
  Serial.print(F("CC1101 marcstate "));
  Serial.println(radio.readStatusReg(CC1101_MARCSTATE) & 0x1F);

  Serial.println(F("CC1101 initialized"));

  attachInterrupt(digitalPinToInterrupt(CC1101_GDO0), messageReceived, FALLING);
}

// http://www.ti.com/lit/an/swra114d/swra114d.pdf
int rssi(char raw) {
  uint8_t rssi_dec;
  uint8_t rssi_offset = 74;
  rssi_dec = (uint8_t) raw;
  if (rssi_dec >= 128)
    return ((int)( rssi_dec - 256) / 2) - rssi_offset;
  else
    return (rssi_dec / 2) - rssi_offset;
}

int lqi(char raw) {
  return 0x3F - raw;
}

void loop() {
  //Serial.println(radio.readStatusReg(CC1101_MARCSTATE) & 0x1F);
  if (packetWaiting) {
    detachInterrupt(CC1101_GDO0);
    packetWaiting = false;
    CCPACKET packet;
    if (radio.receiveData(&packet) > 0) {
      Serial.println(F("Received packet"));
      Serial.print(F("lqi: "));
      Serial.println(lqi(packet.lqi));
      Serial.print(F("rssi: "));
      Serial.print(rssi(packet.rssi));
      Serial.println(F(" dBm"));
 
      if (packet.length > 0) {
        Serial.print(F("packet: len "));
        Serial.println(packet.length);
        Serial.println(F("data: "));
        for (int i = 0; i < packet.length; i++) { Serial.print(packet.data[i], HEX); }
        Serial.println();
        //Serial.println((const char *) packet.data);
      }
    }
    attachInterrupt(digitalPinToInterrupt(CC1101_GDO0), messageReceived, FALLING);
  }
}

void setFreq(uint8_t f2, uint8_t f1, uint8_t f0) {
  radio.writeReg(CC1101_FREQ2, f2);
  radio.writeReg(CC1101_FREQ1, f1);
  radio.writeReg(CC1101_FREQ0, f0);
}

CC1101 piirin ohjelmointi on aika kryptistä ja työlästä. TI:n SmartRF ohjelmalla (kehityskortin mukana, maksullinen) rekisteriarvojen määrittäminen olisi simppeliä. Perus toimintataajuuden rekisteriarvot voi määrittää vaikka näin:

#include <math.h>

#define clk_frq 26.0
#define carrier_freq 433.0

double frequencyInMHz = carrier_freq;

  double secondByteOverflow = fmod(frequencyInMHz, clk_frq);
  double firstByteValue = (double)((frequencyInMHz - secondByteOverflow) / clk_frq);

  double thirdByteOverflow = fmod((secondByteOverflow * 255), clk_frq);
  double secondByteValue = (double)(((secondByteOverflow * 255) - thirdByteOverflow) / clk_frq);

  double excessOverflow = fmod((thirdByteOverflow * 255), clk_frq);
  double thirdByteValue = (double)(((thirdByteOverflow * 255) - excessOverflow) / clk_frq);

  Serial.print("FREQ2: ");
  Serial.println((byte) firstByteValue, HEX);
  Serial.print("FREQ1: ");
  Serial.println((byte) secondByteValue, HEX);
  Serial.print("FREQ0: ");
  Serial.println((byte) thirdByteValue, HEX);
 

C# - CC1101 rekisteriarvot: bps ja taajuus

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace cc1101
{
    public partial class formCC101 : Form
    {
        const double CC1101_CLK_FREQ = 26;

        public formCC101()
        {
            InitializeComponent();
        }

        private void txtCF_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar) &&
                (e.KeyChar != '.'))
            {
                e.Handled = true;
            }

            // only allow one decimal point
            if ((e.KeyChar == '.') && ((sender as TextBox).Text.IndexOf('.') > -1))
            {
                e.Handled = true;
            }
        }

        private void buttonCalcCF_Click(object sender, EventArgs e)
        {
            labelF2.Text = "FREQ2: ";
            labelF1.Text = "FREQ1: ";
            labelF0.Text = "FREQ0: ";
            labelMDMCFG4.Text = "MDMCFG4: ";
            labelMDMCFG3.Text = "MDMCFG3: ";
            labelBPS.Text = "";


            double frequencyInMHz = Double.Parse(txtCF.Text.Replace(".", ","));

            double secondByteOverflow = frequencyInMHz % CC1101_CLK_FREQ;
            double firstByteValue = (double)((frequencyInMHz - secondByteOverflow) / CC1101_CLK_FREQ);

            double thirdByteOverflow = (secondByteOverflow * 255) % CC1101_CLK_FREQ;
            double secondByteValue = (double)(((secondByteOverflow * 255) - thirdByteOverflow) / CC1101_CLK_FREQ);

            double excessOverflow = (thirdByteOverflow * 255) % CC1101_CLK_FREQ;
            double thirdByteValue = (double)(((thirdByteOverflow * 255) - excessOverflow) / CC1101_CLK_FREQ);

            labelF2.Text = labelF2.Text + ((byte)firstByteValue).ToString("X");
            labelF1.Text = labelF1.Text + ((byte)secondByteValue).ToString("X");
            labelF0.Text = labelF0.Text + ((byte)thirdByteValue).ToString("X");

            double clockFrequencyMHz = CC1101_CLK_FREQ;
            double baudRate = Double.Parse(txtBPS.Text.Replace(".", ","));

            double baudRateExponent = 0;
            double baudRateMantissa = 0;
            for (int tempExponent = 0; tempExponent < 16; tempExponent++)
            {
                int tempMantissa = (int)((baudRate * Math.Pow(2, 28) / (Math.Pow(2, tempExponent) * (clockFrequencyMHz * 1000000.0)) - 256) + .5);
                if (tempMantissa < 256)
                {
                    baudRateExponent = tempExponent;
                    baudRateMantissa = tempMantissa;
                    break;
                }
            }

            baudRate = (1000000.0 * clockFrequencyMHz * (256 + baudRateMantissa) * Math.Pow(2, baudRateExponent) / Math.Pow(2, 28));
            baudRate = Math.Round(baudRate, 4);

            byte mdmcfg4 = Convert.ToByte( "10001100", 2 );
            labelMDMCFG4.Text = labelMDMCFG4.Text + ((byte)((mdmcfg4 & 0xf0) | (int)baudRateExponent)).ToString("X");
            labelMDMCFG3.Text = labelMDMCFG3.Text + ((byte)baudRateMantissa).ToString("X");
            labelBPS.Text = baudRate.ToString();

        }

        private void textBPS_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar) &&
                (e.KeyChar != '.'))
            {
                e.Handled = true;
            }

            // only allow one decimal point
            if ((e.KeyChar == '.') && ((sender as TextBox).Text.IndexOf('.') > -1))
            {
                e.Handled = true;
            }
        }

    }
}

kkk.jpg

torstai, 8. helmikuu 2018

Find max Y value from matplotlib.pyplot

import matplotlib.pyplot as plt
import numpy as np

file = open('tesffile.txt', 'w')
dt = 0.01
t = np.arange(0, 10, dt)
nse = np.random.randn(len(t))
r = np.exp(-t/0.05)

cnse = np.convolve(nse, r)*dt
cnse = cnse[:len(t)]
s = 0.1*np.sin(2*np.pi*t) + cnse

plt.psd(s, 64, 1/dt)
plt.title('Plot')
plt.xlabel('X')
plt.ylabel('Y')
plt.grid(True)

ax = plt.gca()
line = ax.lines[0]

ydata = line.get_ydata()
xdata = line.get_xdata()

ymax = -999999
imax = -1
i = 0
while i < len(ydata):
    if ydata[i] > ymax:
        ymax = ydata[i]
        imax = i
    print(xdata[i], ydata[i])
    s = str(xdata[i])
    s += ' '
    s += str(ydata[i])
    s += '\r\n'
    file.write(s)
    i += 1

print
print xdata[imax], ymax
file.close()
plt.show()

perjantai, 2. helmikuu 2018

SDR# TETRA decoder plugin

https://www.rtl-sdr.com/tetra-decoder-plugin-for-sdr-now-available/

Sain tuon pluginin toimimaan, herjasi SDR#:ssa kun klikkasi TETRA demodulaattorin päälle:
IF samplerate to low change modulation type to WFM or set parameter minoutputsample value = 48000
Tuohon auttoi se että kytkin RTL-SDR tikun toiseen USB porttiin ja klikkasin SDRSharpissa play:n päälle ja sen jälkeen TETRA demodulaattori alkoi toimimaan.

Windows 10 64-bit, SDRSharp 1.0.0.1637, .NET Framework 4.6.1, MSYS2 64-bit (http://www.msys2.org/), VC 2015 runtime

sdr# plugin magic line:
<add key="Tetra" value="SDRSharp.Tetra.TetraPlugin,SDRSharp.Tetra"/>

Install:
---------
1) Copy ddl's to sdr# directory
2) Add magic line to Plugins.xml
3) Download and install M-SYS2 from https://sourceforge.net/projects/msys2/
4) Copy contents of msys_root to your M-SYS2 installation directory
5) Open M-SYS2 shell and execute "pacman -S socat"

Use:
---------
1) Open M-SYS2 shell and execute command "startrx"
2) Run sdr#

The best result is achieved in WFM mode. To run the plugin in NFM
MinOutputSamplerate must be set equal to or greater than 48000.

confs.jpg

strx.jpg

 

sdrsharp-tetra.jpg

Windows 10 Fall Creators Update:ssa on .NET Framework 4.7 Windows komponenttina. TETRA demodulator voi herjata:
err2.jpgerr1.jpg

Virheen voi kuitata Continue painikeella (SDR# ja TETRA demodulator toimii edelleen). Quit sulkee SDR# ohjelman.
 

sunnuntai, 14. tammikuu 2018

Mobile traffic lights radiomodem at 430.3 MHz - 2

http://www.berghaus-verkehrstechnik.com/home/

lllllll.jpg

AM demodulated signal in audacity
https://vocaroo.com/i/s01SjrOGEOMx
auda-am.jpg

Plot spectrum

auda-fm-plot.jpg