{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Notebook for the design of a simple FIR filter for feasiblity testing\n",
    "\n",
    "from scipy import signal\n",
    "from scipy.fft import fft, fftfreq\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from ipywidgets import interact\n",
    "\n",
    "def simple_fir(b, data):\n",
    "    y=[]\n",
    "    for j in range(0, len(data) - len(b)):\n",
    "        y_i=0\n",
    "        for i, b_i in enumerate(b):\n",
    "            y_i += b_i*data[j+i]\n",
    "        y.append(y_i)\n",
    "    return y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Chirp data generate\n",
    "n=3000 # number of samples to use for the chirp\n",
    "fs=20000 # The sampling rate for the chrip\n",
    "f0=100# the start frequency in Hz for the chirp\n",
    "f1=1000 # the stop frequency of the chirp\n",
    "t1=n/fs # the total length of the chirp in s\n",
    "\n",
    "t_chrip = np.linspace(0, t1, n)\n",
    "# generate a chrip and scale to int16 (1 bit for sign)\n",
    "y_chrip = np.round(signal.chirp(t_chrip, f0=f0, f1=f1, t1=t1, method='linear')*(2**15-1)).astype(int)\n",
    "cutsamps = 45\n",
    "y_chrip = y_chrip[cutsamps:]\n",
    "t_chrip = t_chrip[cutsamps:]\n",
    "\n",
    "# Generate an array were the data is present in an interleaved format with the inverted signal \n",
    "y_chrip_interleaved = np.empty((2*y_chrip.size), dtype=y_chrip.dtype)\n",
    "y_chrip_interleaved[0::2] = y_chrip\n",
    "y_chrip_interleaved[1::2] = -1*y_chrip[::-1]\n",
    "\n",
    "file_str= f\"#define CHIRP_DATA_SAMPLE_RATE {int(fs)}\\n\"\\\n",
    "          \"#define CHIRP_DATA_LEN\"f\" {y_chrip.size}\" \"\\n\"\\\n",
    "          \"#define CHIRP_DATA_INTERLEAVED_LEN\"f\" {y_chrip_interleaved.size}\" \"\\n\"\\\n",
    "          \"#define CHIRP_DATA {\" + \",\".join(y_chrip.astype(str)) +\"}\\n\"\\\n",
    "          \"#define CHIRP_DATA_INTERLEAVED_INVERTED {\" + \",\".join(y_chrip_interleaved.astype(str)) +\"}\" \"\\n\"\n",
    "\n",
    "with open(\"pcm_chirp/include/chirp_data.h\", \"w\") as f:\n",
    "    f.write(file_str)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "ea1dc23834484f6b9cb7db0a2426a67c",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "interactive(children=(IntSlider(value=40, description='numtaps', step=2), IntSlider(value=100, description='f_…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<function __main__.update(numtaps=40, f_cut=100)>"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "9bd858174a2f4aabb1105f16cff87e58",
       "version_major": 2,
       "version_minor": 0
      },
      "image/png": "[encoded data, 164148 characters]",
      "text/html": [
       "\n",
       "            <div style=\"display: inline-block;\">\n",
       "                <div class=\"jupyter-widgets widget-label\" style=\"text-align: center;\">\n",
       "                    Figure\n",
       "                </div>\n",
       "                <img src='data:image/png;base64,[encoded data, 164148 characters]' width=640.0/>\n",
       "            </div>\n",
       "        "
      ],
      "text/plain": [
       "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%matplotlib widget\n",
    "\n",
    "b=signal.firwin(20, 100, fs=fs)\n",
    "y_lfiltered = signal.lfilter(b, [1.0], y_chrip)\n",
    "yf=fft(y_lfiltered)\n",
    "xf = fftfreq(n, t1/n)[:n//2]\n",
    "\n",
    "cols = 1\n",
    "rows = 3\n",
    "\n",
    "fig = plt.figure(1)\n",
    "ax1 = fig.add_subplot(rows, cols, 1)\n",
    "line1, = ax1.plot([0], \".-\", label = \"chrip\")\n",
    "ax2 = fig.add_subplot(rows, cols, 2)\n",
    "line2, = ax2.plot([0], label=\"chrip filtered signal.lfilter\")\n",
    "ax3 = fig.add_subplot(rows, cols, 3)\n",
    "line3, = ax3.plot([0], label=\"own fir implementation\")\n",
    "\n",
    "def update(numtaps = 40, f_cut=100):\n",
    "    # Calculate the filter coefficients for given paramters\n",
    "    b=signal.firwin(numtaps, f_cut, fs=fs)\n",
    "    print(f\"Filter coeffs for {numtaps} tabs and {f_cut}Hz cutoff are:\\n\", b)\n",
    "    \n",
    "    bits=16\n",
    "    if min(b)<0:\n",
    "        bits=bits-1\n",
    "    \n",
    "    print(f\"Filter coeffs converted to Q1.{bits}bit int are :\\n\", \n",
    "          \", \".join(\n",
    "                np.array(np.array(np.round(b*(2**(bits)-1)), dtype=np.int32), dtype=str)\n",
    "            )\n",
    "        )\n",
    "\n",
    "    # plot the chirp\n",
    "    line1.set_data(range(len(y_chrip)), y_chrip)\n",
    "    ax1.set_xlim(0, len(y_chrip))\n",
    "    ax1.set_ylim(min(y_chrip), max(y_chrip))\n",
    "\n",
    "    # Apply the coefficents with scipy function\n",
    "    y_lfiltered = signal.lfilter(b, [1.0], y_chrip)\n",
    "    line2.set_data(range(len(y_lfiltered)), y_lfiltered)\n",
    "    ax2.set_xlim(0, len(y_lfiltered))\n",
    "    ax2.set_ylim(min(y_lfiltered), max(y_lfiltered))\n",
    "\n",
    "    # yf=2.0/n*np.abs(fft(y_chrip[:n//2]))\n",
    "    # xf = fftfreq(n, t1/n)[:n//2]\n",
    "    data = simple_fir(b, y_chrip)\n",
    "    line3.set_data(range(len(data)), data)\n",
    "    ax3.set_xlim(0, len(data))\n",
    "    ax3.set_ylim(min(data), max(data))\n",
    "\n",
    "    fig.canvas.draw_idle()\n",
    "    # save coefficients to file\n",
    "    with open(\"pcm_data_processing/include/coefficients.h\", \"w\") as f:\n",
    "        f.write(\n",
    "            \"#define NUMTAPS \" + str(numtaps) + \"\\n\" +\n",
    "            \"#define COEFFICIENTS {\" + \",\".join(np.array(np.array(np.round(b*(2**(bits)-1)), dtype=np.int32), dtype=str)) +\"}\" \"\\n\"\n",
    "        )\n",
    "\n",
    "plt.tight_layout()\n",
    "interact(update, numtaps=(0, 100,2), f_cut=(100,5000))\n",
    "\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "jupyter",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.5"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
