From 2146a84d4b69e5c2b823cf4417be38767df161b1 Mon Sep 17 00:00:00 2001 From: Paul Zhang Date: Fri, 29 Dec 2023 16:04:09 -0800 Subject: [PATCH] Set up CI for linting (#6) * Lint and format with ESLint and Prettier * Add GitHub Actions lint workflow --- .eslintrc.js | 24 ++ .github/workflows/ci.yaml | 26 ++ babel.config.js | 2 +- docs/DAV/lab-4.md | 67 ++-- docs/DAV/lab-5.md | 22 +- docs/WRAP/module-1.md | 88 ++-- docs/WRAP/module-2.md | 55 +-- docs/WRAP/module-3.md | 74 ++-- docs/WRAP/module-4.md | 67 ++-- docs/pocket-racers/module-0.md | 5 +- docs/pocket-racers/module-1.md | 15 +- docs/pocket-racers/module-2.md | 18 +- docs/pocket-racers/module-3.md | 16 +- docs/pocket-racers/module-4.md | 25 +- package-lock.json | 712 +++++++++++++++++++++++++++++++++ package.json | 7 +- sidebars.js | 2 +- src/css/custom.css | 2 +- 18 files changed, 955 insertions(+), 272 deletions(-) create mode 100644 .eslintrc.js create mode 100644 .github/workflows/ci.yaml diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..b0f5548 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,24 @@ +module.exports = { + env: { + browser: true, + es2021: true, + node: true, + }, + extends: ["eslint:recommended", "plugin:@docusaurus/recommended"], + overrides: [ + { + env: { + node: true, + }, + files: [".eslintrc.{js,cjs}"], + parserOptions: { + sourceType: "script", + }, + }, + ], + parserOptions: { + ecmaVersion: "latest", + sourceType: "module", + }, + rules: {}, +}; diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..4ea2b80 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,26 @@ +name: CI + +on: + push: + branches: + - main + pull_request: + +jobs: + lint: + runs-on: ubuntu-22.04 + + steps: + - name: Checkout the repository + uses: actions/checkout@v3 + + - name: Install Node.js + uses: actions/setup-node@v3 + with: + node-version: "20" + + - name: Install dependencies + run: npm ci + + - name: Lint the project + run: npm run lint diff --git a/babel.config.js b/babel.config.js index e00595d..bfd75db 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,3 +1,3 @@ module.exports = { - presets: [require.resolve('@docusaurus/core/lib/babel/preset')], + presets: [require.resolve("@docusaurus/core/lib/babel/preset")], }; diff --git a/docs/DAV/lab-4.md b/docs/DAV/lab-4.md index 78e352f..c1a0e7c 100644 --- a/docs/DAV/lab-4.md +++ b/docs/DAV/lab-4.md @@ -1,15 +1,16 @@ # Lab 4 + ### Graphic Design Is My Passion -* [1: VGArbage](#1-vgarbage) - * [1.1: The VGA Constants](#11-the-vga-constants) - * [1.2: The Pixel Counters](#12-the-pixel-counters) - * [1.3: hsync and vsynv](#13-hsync-and-vsync) - * [1.4: The Pixel Color](#14-the-pixel-color) - * [1.5: The Top Level](#15-the-top-level) -* [2: I Can't Win](#2-i-cant-win) -* [3: Graphic Design Will Be Your Passion Too](#3-graphic-design-will-be-your-passion-too) -* [?: Extra Credit](#extra-credit) +- [1: VGArbage](#1-vgarbage) + - [1.1: The VGA Constants](#11-the-vga-constants) + - [1.2: The Pixel Counters](#12-the-pixel-counters) + - [1.3: hsync and vsynv](#13-hsync-and-vsync) + - [1.4: The Pixel Color](#14-the-pixel-color) + - [1.5: The Top Level](#15-the-top-level) +- [2: I Can't Win](#2-i-cant-win) +- [3: Graphic Design Will Be Your Passion Too](#3-graphic-design-will-be-your-passion-too) +- [?: Extra Credit](#extra-credit) ## Introduction @@ -23,7 +24,6 @@ Link to Lecture 5 [Verilog Docs and FAQs](https://docs.google.com/document/d/1_8ruatZIb3sZb-3Kk3WOYC8Jzv4HvdwrTPZUGVupdVE/edit) - ## Contact Us You can contact the DAV leads on Discord. @@ -31,8 +31,7 @@ You can contact the DAV leads on Discord. **Claire Huang** (Discord: _zhiyujia_) **Premkumar Giridhar** (Discord: _8bitrobot_) - -## 1 VGArbage +## 1 VGArbage To get started, [we’ve provided a skeleton for you](https://drive.google.com/file/d/1hvoNzdLyxhBUwM9_1KTYdDiDnigi52x9/view?usp=sharing). @@ -40,40 +39,40 @@ You’ll observe that the gist of the VGA is mostly counters and some combinatio Your job now is to fill out the skeleton. We’ve labeled the four parts as **TODO(1), TODO(2), TODO(3), TODO(4)** for your reference. The actual tasks should be fairly straightforward (and they’re outlined in the skeleton!), but we’ll describe them in this lab spec as well for completeness. -### 1.1 The VGA Constants +### 1.1 The VGA Constants Here, you’re presented with 8 constants that you need to find the values for. You can easily find these numbers by Googling _“VGA timing spec”_ or similar. You can also find them in our lecture slides :-) Just keep in mind what each one is conceptually – you’ll need them later! -### 1.2 The Pixel Counters +### 1.2 The Pixel Counters The pixel counters are the brain behind the VGA driver, and the sequential block triggered on the edge of our VGA clock is where we update them. If the reset button is pressed, you need to reset these counters to zero. Otherwise, you should increment the appropriate counter. The logic for counter increments is fairly straightforward – increment the horizontal counter `hc`, and if it gets too high, increment `vc` and set `hc` back to zero. You’ll need to use the parameters you defined earlier to figure out at what value of `hc` you need to move to the next line. Also, keep in mind that `hc` and `vc` are zero-indexed when writing your conditions for incrementing them! If `hc` equals 800 at any point, you did something wrong :-) -### 1.3 `hsync` and `vsync` +### 1.3 `hsync` and `vsync` Here, you’ll combinationally generate the `hsync` and `vsync` signals using the counter values. The parameters we defined earlier will come in handy here. Remember two things when figuring out the assignments: -* `hsync` and `vsync` should be HIGH for most of the time and driven LOW during the specific period within the blanking interval -* the duration of `hsync` and `vsync` is susceptible to off-by-one errors – make sure to double-check your conditions! +- `hsync` and `vsync` should be HIGH for most of the time and driven LOW during the specific period within the blanking interval +- the duration of `hsync` and `vsync` is susceptible to off-by-one errors – make sure to double-check your conditions! -### 1.4 The Pixel Color +### 1.4 The Pixel Color Finally, you’ll use a combinational block to assign the pixel color outputs `red`, `green`, and `blue`. Remember to assign all the colors to 0 during blanking intervals and resets – otherwise, just assign the color values inputted via `input_red`, `input_green`, and `input_blue`. -### 1.5 The Top Level +### 1.5 The Top Level This isn’t labeled in the skeleton because you need to make it yourself, but in addition to filling out the VGA skeleton, you need a top level to drive it. This will include the following tasks: -* Creating and instantiating a 25 MHz clock using a PLL -* Instantiating the VGA module -* Pin planning! +- Creating and instantiating a 25 MHz clock using a PLL +- Instantiating the VGA module +- Pin planning! It’ll be fairly obvious if your module is working as expected, so you _probably_ don’t need to testbench for this one. But if you’re having weird timing issues and can’t figure out why, there’s nothing a testbench can’t help you figure out! -## 2 I Can’t Win +## 2 I Can’t Win In this section, you’ll be implementing ping-pong RAM. If you recall from lecture, ping-pong RAM is a technique where our VGA reads from one memory buffer while our graphics driver writes to the other. This prevents the VGA from having its image change while it’s being read – a very common source of screen-tearing. @@ -81,18 +80,18 @@ To implement this, it might be easier to first create the RAM as two arrays of r For this module, you should take in the following inputs: -* A clock, to allow synchronous changes of the read and write RAM, -* The address to write at, or `addrWrite`. This is dependent on the size of your array. -* Two values for `addrRead_h` and `addrRead_v`, which can be taken from your VGA module (remember the counters `hc` and `vc`?), -* And the data to write, or `dataWrite`. The size of this is dependent on the size of your colors - if your red, green, and blue pixels are 4 bits each, this will be 12 bits. +- A clock, to allow synchronous changes of the read and write RAM, +- The address to write at, or `addrWrite`. This is dependent on the size of your array. +- Two values for `addrRead_h` and `addrRead_v`, which can be taken from your VGA module (remember the counters `hc` and `vc`?), +- And the data to write, or `dataWrite`. The size of this is dependent on the size of your colors - if your red, green, and blue pixels are 4 bits each, this will be 12 bits. Your module should output whatever was at the read address. Now for the actual ping pong part. To switch the two RAMs, you can instantiate a 1 bit `writeEnable` register. Then, when `addrRead_h` and `addrRead_v` both reach zero (a.k.a. the start of the frame), the `writeEnable` register can be flipped. Make sure that the flipping is done sequentially, to keep everything in sync. In the combinational block, the selection of which RAM buffer to read/write can be determined based on `writeEnable`, and this address can be used to read the data out to the VGA module. That means that this ping pong RAM module will need to be instantiated in the top level where you instantiated your VGA module. -Wow, that was a lot. What do you even do with this ping pong RAM? +Wow, that was a lot. What do you even do with this ping pong RAM? -## 3 Graphic Design Will Be Your Passion Too +## 3 Graphic Design Will Be Your Passion Too To encourage best practices, you’ll implement a very basic graphics module too. Don’t worry, you can just hardcode this part for now. This is just to show you a structure you can use for your final capstone project. @@ -102,18 +101,18 @@ In the graphics module, you’ll want to take in the horizontal and vertical pos The module should output the following: -* The color to be sent to the ping pong RAM, -* And the address to read/write from in the ping pong RAM. +- The color to be sent to the ping pong RAM, +- And the address to read/write from in the ping pong RAM. (All of this is combinational, so there’s no clock involved in this one!) -To calculate the address - if the horizontal and vertical position are in the blanking interval, set the address to 0. Otherwise, you can find the address by calculating vertical position * (number of pixels in a row) + horizontal position. +To calculate the address - if the horizontal and vertical position are in the blanking interval, set the address to 0. Otherwise, you can find the address by calculating vertical position \* (number of pixels in a row) + horizontal position. To calculate the color, you can just hard code it to return a certain color if it’s not in the blanking interval. If the horizontal and vertical positions are within the blanking interval, then the color should be all 0’s. Now, it’s a matter of wiring up the inputs and outputs from the modules you created, and now you have a VGA using ping pong RAM! -## ? Extra credit +## ? Extra credit If you want to go above and beyond on this lab, here’s a little exercise that will introduce you to blocking. @@ -125,7 +124,7 @@ Remember that graphics module you created? You could in theory use the vertical However! If we continued just like that, this mushroom would be very, very small. Each square would only be one pixel! What if we want to make this larger? -Well, we can implement a technique called blocking! In the top level, you can assign some wires to be a smaller version of the horizontal position and vertical position. +Well, we can implement a technique called blocking! In the top level, you can assign some wires to be a smaller version of the horizontal position and vertical position. ```verilog // horizontal_position ranges from 0 to 799 diff --git a/docs/DAV/lab-5.md b/docs/DAV/lab-5.md index 9b96dd9..4c08f3f 100644 --- a/docs/DAV/lab-5.md +++ b/docs/DAV/lab-5.md @@ -1,10 +1,10 @@ # Lab 5 -### A Phone Named Michael +### A Phone Named Michael -* [0: In DAV No One Can Hear You Scream](#0-in-dav-no-one-can-hear-you-scream) -* [1: Anyways, Don't Cry](#1-anyways-dont-cry) -* [2: It's So Sample](#2-its-so-sample) +- [0: In DAV No One Can Hear You Scream](#0-in-dav-no-one-can-hear-you-scream) +- [1: Anyways, Don't Cry](#1-anyways-dont-cry) +- [2: It's So Sample](#2-its-so-sample) ## Introduction @@ -21,7 +21,7 @@ You can contact the DAV leads on Discord. **Claire Huang** (Discord: _zhiyujia_) **Premkumar Giridhar** (Discord: _8bitrobot_) -## 0 In DAV No One Can Hear You Scream +## 0 In DAV No One Can Hear You Scream For DAV, we’ll be working with mics that look like this one below. This is an analog microphone. It has two input pins, VCC and GND, and an output pin through which it spits out an _analog_ voltage corresponding to the mic input intensity (a.k.a. the volume). If you want to know more about how microphones work, consult [this article](https://mynewmicrophone.com/how-do-microphones-work-a-helpful-illustrated-guide/) (and perhaps ChatGPT for a summary). @@ -31,16 +31,16 @@ But wait! You might be thinking, _aren’t we learning about digital design?_ Yo So anyways, onto the ADC we go! -## 1 Anyways, Don’t Cry +## 1 Anyways, Don’t Cry In order to use the ADC on our FPGAS, we can just use an IP! It’s called the **ADC Controller for DE-series Boards**. In the IP settings, you’ll want to specify these: -* DE-Series Board: **DE10-Lite** -* ADC Clock Frequency: **10.0 MHz** (this should be filled in already) -* Number of channels: **1** -* System Clock Frequency: **50** +- DE-Series Board: **DE10-Lite** +- ADC Clock Frequency: **10.0 MHz** (this should be filled in already) +- Number of channels: **1** +- System Clock Frequency: **50** The files will be generated for you, and they’re all you need to get started with your ADC. However, you need to manually add the `.qip` file to your project - and after that, you can find the template within the QIP with the same name as your ADC instantiation. The ADC comes with eight channels, but we’ll only be using one of them (CH0). @@ -50,7 +50,7 @@ To set up your microphone, you’ll want to use your breadboard. (If you need a Then, you’ll want to wire up the VCC pin on the microphone to **VCC5** (the 5-volt power pin) on the board, the GND pin on the microphone to **GND**, and the OUT pin to **ADC_IN0**. Note that the little labels on the board are _incorrect_ for some pins, so you should use the screenshot above as your source of where the pins are. -## 2 It’s So Sample +## 2 It’s So Sample To get a feel for how your microphone works, let’s test the waters a little bit! Your job is to get the output of your microphone onto the LEDs of your board. The ADC wants a clock (to sample) and a reset button, and it will output the microphone intensity to `CH0`. Then, display the magnitude on your LEDs. You can do that by using the output of the ADC outstream to right-shift `10'b1000000000` by some amount; due to sign-extension, this will cause light up more LEDs when the mic input is louder! (If the magnitude of the mic output is too large, all of the LEDs will always be lit up, so you may want to scale and/or shift your ADC output value by some experimentally derived constant.) diff --git a/docs/WRAP/module-1.md b/docs/WRAP/module-1.md index af2a266..72967a5 100644 --- a/docs/WRAP/module-1.md +++ b/docs/WRAP/module-1.md @@ -1,17 +1,16 @@ -# Module 1 -### Introduction to Amplifiers and LTspice +# Module 1 +### Introduction to Amplifiers and LTspice ![alt_text](images/image2.png "image_tooltip") - **Lecture Notes:** [Lecture 1 Notes](https://drive.google.com/file/d/1UlqseA_aiCYNR1isKwwh8ZNgZEOqVJPT/view?usp=sharing) **Motivation:** -In this module, we will cover the basics of using LTspice to verify our circuit designs. We will verify parameters such as gain, input impedance and output impedance using different types of analysis including transient and AC analysis. Throughout this process, we will also review the content covered in the lecture 1 notes by creating a Class A amplifier from a given spec and deriving component values to meet the performance requirements using BJT amplifier basics. We will then briefly touch on another type of amplifier structure and its pros and cons. +In this module, we will cover the basics of using LTspice to verify our circuit designs. We will verify parameters such as gain, input impedance and output impedance using different types of analysis including transient and AC analysis. Throughout this process, we will also review the content covered in the lecture 1 notes by creating a Class A amplifier from a given spec and deriving component values to meet the performance requirements using BJT amplifier basics. We will then briefly touch on another type of amplifier structure and its pros and cons. **Prerequisites:** @@ -39,26 +38,23 @@ Time to get set up! Please install LTSpice from Analog Devices: https://www.anal A prior WRAP lead and WRAP creator, David Baum, recorded a [fantastic video](https://www.youtube.com/watch?v=OwtuRsOh_rc) that will give you a quick rundown of how to use LTSpice. You can find similar such resources on the internet or come to the lab for any questions about using this software. - ## Part 1: Common Emitter (Class A Amplifier) -We will start off by using what we have learned in lecture to try creating an amplifier with the following specifications: +We will start off by using what we have learned in lecture to try creating an amplifier with the following specifications: Collector current Ic = 1mA Gain = -40 (16 dB) (At least -40) -Collector-emitter voltage Vce = 2.5V +Collector-emitter voltage Vce = 2.5V Supply voltage Vcc = 5V Use the MMBTH10 transistor (this is the transistor we will be using later in the project as well) - ![alt_text](images/image4.png "image_tooltip") - -To verify our design we will be using LTspice, a widely used circuit simulation tool. LTspice allows us to select different components and place them together in a network, or netlist to create a system. +To verify our design we will be using LTspice, a widely used circuit simulation tool. LTspice allows us to select different components and place them together in a network, or netlist to create a system. For devices like transistors and diodes which can have vastly different performances and specifications, LTspice allows us to input specific parameters that characterize the performance of the device. The transistor we use is not provided for LTspice, so we will have to import its parameters. To make sure LTSpice knows what numbers to use to model its behavior you will need to add a Spice directive, with the following text: @@ -66,71 +62,64 @@ For devices like transistors and diodes which can have vastly different performa .model MMBTH10 npn - + IS=69.28e-18 XTI=3 EG=1.11 VAF=100 + + IS=69.28e-18 XTI=3 EG=1.11 VAF=100 - + BF=308.6 NE=1.197 ISE=69.28e-18 IKF=22.83e-3 + + BF=308.6 NE=1.197 ISE=69.28e-18 IKF=22.83e-3 - + XTB=1.5 BR=1.11 NC=2 IKR=0 + + XTB=1.5 BR=1.11 NC=2 IKR=0 - + RC=4 CJC=1.042e-12 MJC=0.2468 VJC=0.75 + + RC=4 CJC=1.042e-12 MJC=0.2468 VJC=0.75 - + FC=0.5 CJE=1.52e-12 MJE=0.3223 VJE=0.75 + + FC=0.5 CJE=1.52e-12 MJE=0.3223 VJE=0.75 - + TR=1.558e-9 TF=135.8e-12 ITF=0.27 VTF=10 + + TR=1.558e-9 TF=135.8e-12 ITF=0.27 VTF=10 + XTF=30 RB=10 **** - Please copy and paste this exactly (only what is within the asterisks, not including them). -Once LTspice has installed, open it and create ‘New Schematic’. To add the transistor model above, please right click in the middle of the screen click ‘Draft’ -> ‘SPICE Directive’. Alternatively, you may press ‘S’ to access the SPICE Directive Menu. Copy and paste the above code into the text box, and click ‘OK’. Then left-click to place it where you want. - -We’ve now instructed LTspice how our device can be modeled - but we do not yet know how to construct it. To add the component after creating the directive, navigate to ‘Edit’ and click on ‘Component’ (alternatively, F2) then add component npn. Ctrl+right click and change ‘Value’ to npn to MMBTH10, or alternatively, right-click on the “npn” text under Q1 and change it to “MMBTH10”. +Once LTspice has installed, open it and create ‘New Schematic’. To add the transistor model above, please right click in the middle of the screen click ‘Draft’ -> ‘SPICE Directive’. Alternatively, you may press ‘S’ to access the SPICE Directive Menu. Copy and paste the above code into the text box, and click ‘OK’. Then left-click to place it where you want. +We’ve now instructed LTspice how our device can be modeled - but we do not yet know how to construct it. To add the component after creating the directive, navigate to ‘Edit’ and click on ‘Component’ (alternatively, F2) then add component npn. Ctrl+right click and change ‘Value’ to npn to MMBTH10, or alternatively, right-click on the “npn” text under Q1 and change it to “MMBTH10”. ![alt_text](images/image5.png "image_tooltip") - - ![alt_text](images/image3.png "image_tooltip") - Your npn transistor should now look like the above. **Checkpoint 1: DC Biasing** -Alright, with that done we can now set up a stable DC bias (that is, set the desired collector current). Recall from Lecture 1 that in order to properly bias the common emitter amplifier, we need to add a resistor at the emitter, Re. Recall that the collector current will end up being Ve/Re (emitter voltage divided by emitter resistor) and that we have Vcc=5V to play with. +Alright, with that done we can now set up a stable DC bias (that is, set the desired collector current). Recall from Lecture 1 that in order to properly bias the common emitter amplifier, we need to add a resistor at the emitter, Re. Recall that the collector current will end up being Ve/Re (emitter voltage divided by emitter resistor) and that we have Vcc=5V to play with. -Note that because we want a fixed collector current of 1 mA, If we make Re too large, since IC ~ IE, then we will have too large of a voltage drop from emitter to ground, leading to the transistor being in the saturation region (recall that we want the collector voltage to be larger than the base voltage to operate in the linear region and our base voltage to be around one forward voltage drop larger than our emitter, hence a larger emitter voltage requires a larger base and therefore collector voltage, but our collector voltage cannot exceed 5 V at which point IC ~ 0 A which we do not want). And if Re is too small, we do not have good bias point stability against beta and temperature variations. Try playing around with values to see how changing Re affects bias. +Note that because we want a fixed collector current of 1 mA, If we make Re too large, since IC ~ IE, then we will have too large of a voltage drop from emitter to ground, leading to the transistor being in the saturation region (recall that we want the collector voltage to be larger than the base voltage to operate in the linear region and our base voltage to be around one forward voltage drop larger than our emitter, hence a larger emitter voltage requires a larger base and therefore collector voltage, but our collector voltage cannot exceed 5 V at which point IC ~ 0 A which we do not want). And if Re is too small, we do not have good bias point stability against beta and temperature variations. Try playing around with values to see how changing Re affects bias. -We also need to select the proper Rc value. We know the gain must be -40, and gain is given by -gm*Rc. Since we know the desired collector current, we can compute gm and determine the proper value of Rc. With Rc known, we can figure out what voltage we need across Re in order to set Vce=2.5V (one of the specs). From there, we can find the proper value of Re. +We also need to select the proper Rc value. We know the gain must be -40, and gain is given by -gm\*Rc. Since we know the desired collector current, we can compute gm and determine the proper value of Rc. With Rc known, we can figure out what voltage we need across Re in order to set Vce=2.5V (one of the specs). From there, we can find the proper value of Re. -Lastly, we set R1 and R2, the base voltage divider resistors, in order to obtain the proper voltage at the base. Since we know what the voltage at the emitter should be from the previous step, we can calculate what the base voltage should be. That is, the base voltage is the emitter voltage plus Vbe, the voltage from base to emitter). +Lastly, we set R1 and R2, the base voltage divider resistors, in order to obtain the proper voltage at the base. Since we know what the voltage at the emitter should be from the previous step, we can calculate what the base voltage should be. That is, the base voltage is the emitter voltage plus Vbe, the voltage from base to emitter). By the end of this step, you should be able to report the values -* R1 -* R2 -* Rc -* Re -* Ve, the voltage at the emitter -* Vc, the voltage at the collector -* Vb, the voltage at the base +- R1 +- R2 +- Rc +- Re +- Ve, the voltage at the emitter +- Vc, the voltage at the collector +- Vb, the voltage at the base **Checkpoint 2: Measuring Small-Signal Gain** -Once you have your DC bias set up, it’s time to attach an AC source signal and measure the output voltage. Use a large resistor as the load of the amplifier (100k works well). Take a moment to think about why we want R_L to be this large - how does a smaller load affect our gain? Also, be sure to include the AC coupling capacitors on both the input and output, as well as the bypass capacitor at the emitter (what capacitance should you use?). +Once you have your DC bias set up, it’s time to attach an AC source signal and measure the output voltage. Use a large resistor as the load of the amplifier (100k works well). Take a moment to think about why we want R_L to be this large - how does a smaller load affect our gain? Also, be sure to include the AC coupling capacitors on both the input and output, as well as the bypass capacitor at the emitter (what capacitance should you use?). Use an input frequency of 10 kHz and an input amplitude of 1mV (again, think about the idea of ‘small signal’ compared to the bias point at the base). Since the gain is -40, the output should be 180° out of phase (with respect to the input) and 40 times larger. Verify that with a transient simulation. Try removing the bypass capacitor at the emitter. What happens to the gain (at the risk of being repetitive, think about why)? By the end of this step, you should have: - - -* A functional CE amplifier with bypassed emitter degeneration -* Comfort with DC and transient analysis in LTSpice +- A functional CE amplifier with bypassed emitter degeneration +- Comfort with DC and transient analysis in LTSpice **Checkpoint 3: Input and Output Impedance** @@ -138,23 +127,16 @@ Now, let’s measure the input and output impedance of the amplifier at 10 kHz. By the end of this step, you should have: - - -* The input impedance at 10kHz (and the impedance over frequency) -* The output impedance at 10kHz (and the impedance over frequency) - +- The input impedance at 10kHz (and the impedance over frequency) +- The output impedance at 10kHz (and the impedance over frequency) ## Part 2: Common Base Amplifier - ![alt_text](images/image1.png "image_tooltip") +Above is the circuit of another type of amplifier known as common base; note that unlike the common emitter configuration shown above, it does NOT invert our signal. -Above is the circuit of another type of amplifier known as common base; note that unlike the common emitter configuration shown above, it does NOT invert our signal. - - - -* Use the small signal model of npn transistor to prove the gain of this amplifier is Av= gm*Rc -* Conceptually explain why the gain of this amplifier is positive while for the common emitter the gain is negative (you can verbally explain it once you come to us for checking your assignment). Hint: consider small voltage changes at the emitter and how those changes manifest themselves at the other terminals of the BJT. You may also approach this question from a semiconductor physics perspective - but it is much easier to consider larger scale phenomena such as voltage and current. -* What do you think is one disadvantage of this amplifier over the common emitter configuration? Hint: Consider the attributes of the common-emitter stage shown above - its gain, phase, input and output impedance, etc. -* As motivation for the next part of WRAP, start to think about why we wanted a large load impedance when we made our Class A amplifier in LTspice. If possible, try adding another RL to the VOUT of the diagram below and see how that affects the gain and if this effect of “loading” the output with an impedance is universal. \ No newline at end of file +- Use the small signal model of npn transistor to prove the gain of this amplifier is Av= gm\*Rc +- Conceptually explain why the gain of this amplifier is positive while for the common emitter the gain is negative (you can verbally explain it once you come to us for checking your assignment). Hint: consider small voltage changes at the emitter and how those changes manifest themselves at the other terminals of the BJT. You may also approach this question from a semiconductor physics perspective - but it is much easier to consider larger scale phenomena such as voltage and current. +- What do you think is one disadvantage of this amplifier over the common emitter configuration? Hint: Consider the attributes of the common-emitter stage shown above - its gain, phase, input and output impedance, etc. +- As motivation for the next part of WRAP, start to think about why we wanted a large load impedance when we made our Class A amplifier in LTspice. If possible, try adding another RL to the VOUT of the diagram below and see how that affects the gain and if this effect of “loading” the output with an impedance is universal. diff --git a/docs/WRAP/module-2.md b/docs/WRAP/module-2.md index cbd23a9..f01ee66 100644 --- a/docs/WRAP/module-2.md +++ b/docs/WRAP/module-2.md @@ -1,10 +1,9 @@ # Module 2 -### Return of the Amplifiers! (With a twist) +### Return of the Amplifiers! (With a twist) ![alt_text](images/image6.png "image_tooltip") - **Lecture Notes:** [Lecture 2 Notes](https://drive.google.com/file/d/1dELZCNGZFk3gMKIeW0V8cDILK0TgxSMv/view?usp=sharing) @@ -13,9 +12,7 @@ Alright, hopefully everyone is feeling good with some snazzy common emitter amplifiers under their belts. You should be pretty comfortable working in LTSpice and will only continue to get more used to it throughout this assignment. -We discussed some of the impedance related shortcomings that a CE amplifier has at the end of the first lecture, and introduced the common collector amplifier as our solution. For the first part of this assignment, we revisit that lecture to design a common collector amplifier. Afterwards, we use them in a Colpitts oscillator, as we discussed in lecture 2. - - +We discussed some of the impedance related shortcomings that a CE amplifier has at the end of the first lecture, and introduced the common collector amplifier as our solution. For the first part of this assignment, we revisit that lecture to design a common collector amplifier. Afterwards, we use them in a Colpitts oscillator, as we discussed in lecture 2. **Prerequisites:** @@ -39,7 +36,6 @@ Oscillator Design LTspice - ## Part 1: Common Collector Amplifier We’re going to start this assignment by designing an isolated common collector amplifier. The specs we want you to meet are: @@ -62,21 +58,16 @@ We’re going all the way in one shot here, based on what you learned from modul You have a fair bit more freedom with design choices here. This is intentional, since as we progress through the project you will often need to define a lot of specs on your own based on the requirements of your system. Here are a few good guidelines to get you started: +- Try placing the emitter voltage Ve at roughly Vcc/2. Doing so enables the amplifier to have a larger output swing (i.e. the maximum output amplitude before the amplifier stops working). +- Start with the output impedance equation given in the slides. You know the source resistance (50Ω), you know beta (somewhere around 100), you don’t know anything else. But you can make some engineering approximations. For example, if you do things right, R1 and R2 should be much larger than Rs, so you can ignore R1 and R2. Try to see how else you can simplify the expression (remember what we discussed in the first lecture, the factor of beta is quite large and should guide the approximations you make). +- Once your output impedance is correct, the gain should follow naturally (to within some tolerance). Try to understand why. It might be useful to retrace the approximations you made with the actual values you now have. See how accurate they are and which ones you should/should not make in the future. +- Pick R1 and R2 such that the current flowing through them is significantly less than the collector current. +Please note that of the three following criteria, matching the first two are the most important and should be the main takeaways of the assignment. It is perfectly acceptable to not meet the third requirement, provided that the first two are met - although it is important to understand why the third requirement is there in the first place and why it is something we do not consider as strongly as the first two. -* Try placing the emitter voltage Ve at roughly Vcc/2. Doing so enables the amplifier to have a larger output swing (i.e. the maximum output amplitude before the amplifier stops working). -* Start with the output impedance equation given in the slides. You know the source resistance (50Ω), you know beta (somewhere around 100), you don’t know anything else. But you can make some engineering approximations. For example, if you do things right, R1 and R2 should be much larger than Rs, so you can ignore R1 and R2. Try to see how else you can simplify the expression (remember what we discussed in the first lecture, the factor of beta is quite large and should guide the approximations you make). -* Once your output impedance is correct, the gain should follow naturally (to within some tolerance). Try to understand why. It might be useful to retrace the approximations you made with the actual values you now have. See how accurate they are and which ones you should/should not make in the future. -* Pick R1 and R2 such that the current flowing through them is significantly less than the collector current. - -Please note that of the three following criteria, matching the first two are the most important and should be the main takeaways of the assignment. It is perfectly acceptable to not meet the third requirement, provided that the first two are met - although it is important to understand why the third requirement is there in the first place and why it is something we do not consider as strongly as the first two. - - - -* Correct output impedance of around 50 Ohms -* Correct gain of around 0.5 -* Currents through the base biasing resistors should have as small a DC current relative to the DC current going through the BJT collector. - +- Correct output impedance of around 50 Ohms +- Correct gain of around 0.5 +- Currents through the base biasing resistors should have as small a DC current relative to the DC current going through the BJT collector. ## Part 2: Collpitts Oscillators @@ -88,19 +79,17 @@ Our desired output frequency is 27MHz. Let’s say that to generate the 27MHz si So, we split this process into two steps. We upconvert to some intermediary frequency X, which we then upconvert again to 27MHz (more on the details of upconversion in lecture 3). For now, suffice to say that if we want roughly equal fractional bandwidth for both filters to make their design easier, then X = sqrt(27) = ~5 MHz (again, we like nice round numbers). -Thus, we need local oscillators that provide us two frequencies - one to go from 1MHz to 5MHz and another to go from 5MHz to 27MHz. For this assignment, we will design a 4MHz Colpitts oscillator and a 22MHz Colpitts oscillator. These can be used for both the upconversion in the transmitter and the downconversion in the receiver. +Thus, we need local oscillators that provide us two frequencies - one to go from 1MHz to 5MHz and another to go from 5MHz to 27MHz. For this assignment, we will design a 4MHz Colpitts oscillator and a 22MHz Colpitts oscillator. These can be used for both the upconversion in the transmitter and the downconversion in the receiver. **Checkpoint 2: The (First) Colpitts Oscillator** We’ll start with a Colpitts oscillator that outputs a 4MHz sine wave. Using the topology shown in lecture 2, design an oscillator that fulfills the following requirements: - - -* Outputs a sine wave at 4 MHz -* Vcc = 5V -* Uses an inductor in the range 500nH to 1uH. Try searching for inductors within this range and look at the datasheet to see what the Q factor is. Most data sheets have plots of Q factor over frequency. (make sure to calculate the appropriate series resistance using the equation from the slides and add it to your schematic. It may be easier to visualize if you add an additional resistor rather than add it as a property of the inductor.) -* Output amplitude of 1V (This will be important once we get to mixers) -* All harmonics of the fundamental should be at least 20dB below the fundamental. Here, the fundamental refers to the 4MHz component of the output. Harmonics are multiples of the 4MHz frequency. To check this, perform an FFT operation on the output voltage (you can do this in LTSpice during the transient simulation), and measure the signal level in dB of the fundamental and the harmonics. A harmonic that is 20dB below the fundamental is ten times lower in amplitude than the fundamental. Decibels come up frequently in communications (and most engineering related things), so it’s best to get used to them now! +- Outputs a sine wave at 4 MHz +- Vcc = 5V +- Uses an inductor in the range 500nH to 1uH. Try searching for inductors within this range and look at the datasheet to see what the Q factor is. Most data sheets have plots of Q factor over frequency. (make sure to calculate the appropriate series resistance using the equation from the slides and add it to your schematic. It may be easier to visualize if you add an additional resistor rather than add it as a property of the inductor.) +- Output amplitude of 1V (This will be important once we get to mixers) +- All harmonics of the fundamental should be at least 20dB below the fundamental. Here, the fundamental refers to the 4MHz component of the output. Harmonics are multiples of the 4MHz frequency. To check this, perform an FFT operation on the output voltage (you can do this in LTSpice during the transient simulation), and measure the signal level in dB of the fundamental and the harmonics. A harmonic that is 20dB below the fundamental is ten times lower in amplitude than the fundamental. Decibels come up frequently in communications (and most engineering related things), so it’s best to get used to them now! To open up the FFT of a signal in LTSpice, plot it as you normally would. Once you have the plot open, right-click on that window and you should see View -> FFT. You can then add cursors exactly as you would to a time-domain plot. @@ -108,13 +97,11 @@ When performing the FFT of your output signal, make sure to capture a very large Again, this design is very open to engineering choices. What bias current should you choose? What inductor and capacitor values should you choose for your LC tank? Here’s some tips: - - -* Choose an inductor value first, the exact value isn’t too critical. Just make sure it lies in the given range. Compute the series resistance and include it in your schematic -* Start by choosing the two LC tank capacitors to be equal. Once you have an inductor value, you can easily find the capacitors using the equation for oscillation frequency. -* Find out what gm you need given your LC tank values. Knowing gm gives you what collector current you need. Make sure to choose a gm roughly 2 times bigger than the minimum required for oscillation. You may need to adjust the collector current later to get the output amplitude you need. -* Try sticking the emitter voltage at roughly 2.5V to maximize output swing. -* Compute the reactance of C2 and make sure RE is much bigger than that reactance. Doing so ensures that RE will not load the LC tank too much. This hopefully should not conflict with the above step. +- Choose an inductor value first, the exact value isn’t too critical. Just make sure it lies in the given range. Compute the series resistance and include it in your schematic +- Start by choosing the two LC tank capacitors to be equal. Once you have an inductor value, you can easily find the capacitors using the equation for oscillation frequency. +- Find out what gm you need given your LC tank values. Knowing gm gives you what collector current you need. Make sure to choose a gm roughly 2 times bigger than the minimum required for oscillation. You may need to adjust the collector current later to get the output amplitude you need. +- Try sticking the emitter voltage at roughly 2.5V to maximize output swing. +- Compute the reactance of C2 and make sure RE is much bigger than that reactance. Doing so ensures that RE will not load the LC tank too much. This hopefully should not conflict with the above step. Once you have completed your design, measure the time domain output and the frequency domain output. diff --git a/docs/WRAP/module-3.md b/docs/WRAP/module-3.md index 9281f78..078c73c 100644 --- a/docs/WRAP/module-3.md +++ b/docs/WRAP/module-3.md @@ -1,4 +1,5 @@ # Module 3 + ### Mix n Match! **Lecture Notes:** @@ -7,15 +8,13 @@ **Motivation:** -We’ve thus far covered ways of amplifying signals and generating frequencies - but is there a way to generate frequencies given other frequencies? From last time, we saw that using feedback, we can create systems whose output oscillates at a designed frequency. One common use of generating known, stable frequencies is in use of the Local Oscillator or LO of a mixer, whose operation is covered in the Lecture 3 notes. - -This is also why we wanted to ensure that our signal generated by our Colpitts Oscillator had a high enough power level - our LO needs to be large enough in power that it can sustain a voltage drop of 0.6 to 0.7 V - enough to maintain forward operation of the diodes in the diode ring mixer. +We’ve thus far covered ways of amplifying signals and generating frequencies - but is there a way to generate frequencies given other frequencies? From last time, we saw that using feedback, we can create systems whose output oscillates at a designed frequency. One common use of generating known, stable frequencies is in use of the Local Oscillator or LO of a mixer, whose operation is covered in the Lecture 3 notes. - +This is also why we wanted to ensure that our signal generated by our Colpitts Oscillator had a high enough power level - our LO needs to be large enough in power that it can sustain a voltage drop of 0.6 to 0.7 V - enough to maintain forward operation of the diodes in the diode ring mixer. **Prerequisites:** -Lecture 1, 2 and 3 alongside assignment 1 and 2. +Lecture 1, 2 and 3 alongside assignment 1 and 2. Class A amplifiers/Common-emitter and common-base @@ -39,59 +38,49 @@ Thus far, we’ve designed a few important system components, including amplifie In this assignment, your mission, should you choose to accept it, is to design a few diode ring mixers that can perform frequency upconversion from 1MHz to 27MHz. We will be using these devices to convert the ~1MHz output from the microcontroller DAC to a frequency we can transmit at. As discussed before, we will be doing this in two steps - from 1MHz to 5Mhz and from 5MHz to 27MHz. - ## Part 1: Diode Ring Mixer First, we’ll create a diode ring mixer and use it as an upconverter. Based on the schematic shown in the lecture, create a mixer simulation in LTSPICE. Note that the schematic assumes the input to the mixer is the RF signal. That is true for a downconverter. Here, we will be making an upconverter where the IF port is the input. The circuit is exactly the same, only what was previously called the RF port is now the IF port and vice versa (i.e., you will input your IF signal at what we were calling the RF port and measure the RF output at what had been labeled the IF port). This is important, so please be sure you understand it - the output of our mixer is at the ‘bottom’ of the circuit diagram (at the port labeled IF) and the inputs are for the LO frequency and the input signal (at the port labeled RF). These are not interchangeable, and depending on whether you want to do upconversion or downconversion using the LO frequency, you will need to treat different ports as the input and output ports. +- For the diodes, we’ll use the MMBD101 Schottky diode ([datasheet](https://www.onsemi.com/pub/Collateral/MBD101-D.PDF)). This diode is designed for UHF circuits (ultra high frequency, 300MHz-3GHz) and easily does the trick for our application. + - In theory, any type of diode could be used for this application. However, there are multiple reasons why Schottky diodes are used. First, Schottky diodes have a lower forward voltage than standard PN junction diodes, meaning that the mixer requires less LO power to function. Second, Schottky diodes tend to switch on and off faster than PN junction diodes and have lower junction capacitance (higher capacitance effectively increases the conversion loss of the mixer). + - Use the following SPICE model (the same way you used the MMBTH10 npn transistor model in the previous assignments) -* For the diodes, we’ll use the MMBD101 Schottky diode ([datasheet](https://www.onsemi.com/pub/Collateral/MBD101-D.PDF)). This diode is designed for UHF circuits (ultra high frequency, 300MHz-3GHz) and easily does the trick for our application. - * In theory, any type of diode could be used for this application. However, there are multiple reasons why Schottky diodes are used. First, Schottky diodes have a lower forward voltage than standard PN junction diodes, meaning that the mixer requires less LO power to function. Second, Schottky diodes tend to switch on and off faster than PN junction diodes and have lower junction capacitance (higher capacitance effectively increases the conversion loss of the mixer). - * Use the following SPICE model (the same way you used the MMBTH10 npn transistor model in the previous assignments) - - .model MMBD101 d - Is=1e-7 Rs=2.51244 N=1.71158 Tt=0 - Cjo=9.20838e-13 Vj=1.5 M=0.2 - Fc=0.5 Bv=1000 Ibv=0.0001 - Kf=0 Af=1 Xti=4 Eg=0.63401 - - - + .model MMBD101 d + Is=1e-7 Rs=2.51244 N=1.71158 Tt=0 + Cjo=9.20838e-13 Vj=1.5 M=0.2 + Fc=0.5 Bv=1000 Ibv=0.0001 + Kf=0 Af=1 Xti=4 Eg=0.63401 -* For the LO, use a 4MHz voltage source with a 50Ω source resistance. Give the LO a 0.5V amplitude (we’ll vary this later). -* For the IF input, use a 1MHz voltage source with a 50Ω source resistance and 1mV amplitude (we’ll vary this later too). -* Use a 50Ω resistor as the load at the RF port. The signal at the RF port should consist of the sum and difference frequencies: 5MHz and 3MHz. We will filter out the 3MHz later. -* To determine the inductance of your transformer coils, try to make their impedance about 10x your load resistance - this is a good rule of thumb for designing components when you want reactive elements to dominate the response (eg - decoupling capacitors should have at least ~10x smaller impedance than what they are bypassing). Also make sure the turns ratio for each transformer is 1:1. - * Remember to stick to reasonable inductor values. For transformers, reasonable inductances range from nanohenries to ~15uH. +- For the LO, use a 4MHz voltage source with a 50Ω source resistance. Give the LO a 0.5V amplitude (we’ll vary this later). +- For the IF input, use a 1MHz voltage source with a 50Ω source resistance and 1mV amplitude (we’ll vary this later too). +- Use a 50Ω resistor as the load at the RF port. The signal at the RF port should consist of the sum and difference frequencies: 5MHz and 3MHz. We will filter out the 3MHz later. +- To determine the inductance of your transformer coils, try to make their impedance about 10x your load resistance - this is a good rule of thumb for designing components when you want reactive elements to dominate the response (eg - decoupling capacitors should have at least ~10x smaller impedance than what they are bypassing). Also make sure the turns ratio for each transformer is 1:1. + - Remember to stick to reasonable inductor values. For transformers, reasonable inductances range from nanohenries to ~15uH. To make sure things are working properly, look at the following: - - -* If you plot the FFT of the RF resistor voltage, you should see the sum and difference frequencies, plus a bunch of harmonics. -* The voltage across the RF voltage source should be roughly 1mV amplitude plus some fuzz (the fuzz is due to the IF and LO signals leaking into the RF port). The IF voltage source is 1mV amplitude with a 50Ω source resistance, and the voltage across the voltage source is 1mV amplitude -- Can you guess what the resistance is looking into the IF & RF ports? (Hint: this is a transformer…) +- If you plot the FFT of the RF resistor voltage, you should see the sum and difference frequencies, plus a bunch of harmonics. +- The voltage across the RF voltage source should be roughly 1mV amplitude plus some fuzz (the fuzz is due to the IF and LO signals leaking into the RF port). The IF voltage source is 1mV amplitude with a 50Ω source resistance, and the voltage across the voltage source is 1mV amplitude -- Can you guess what the resistance is looking into the IF & RF ports? (Hint: this is a transformer…) **Checkpoint 1: The Mixer** - - -* Verify that the RF output contains the sum and difference frequencies by using the FFT method introduced in Assignment 2. Save a screenshot of the spectrum. -* Verify that there is essentially zero leakage from the LO port to the RF port, and the IF port to the RF port. You will need to perform the FFT of the voltage at the port in question and check the magnitude of the test port’s frequency - so you might put a cursor at 1MHz, on the FFT of your RF output to see the IF to RF leakage. Similarly, for the LO leakage, you would put the cursor at 4Mhz on the FFT of the RF output FFT. -* Determine the conversion loss of the mixer. Conversion loss is defined here as the ratio of output power at the RF port at 5MHz to the input power at the IF port at 1MHz. This calculation should be performed in decibels (Conversion Loss (dB) = 20log10(V_RF) - 20log10(V_IF) ) - * You can determine RF and IF voltage in dB easily by looking at the FFT of each signal. By default, the FFT will be plotted in dB scale. The difference between the two in dB is the conversion loss. Note: make sure to only look at the frequency of interest (5MHz) at the RF port. - * If this was a downconversion mixer, the conversion loss would be defined as the ratio between the IF port power and the RF port power (i.e., your input would be at an intermediate frequency and your output would be at the radio frequency). - * Fun fact: the smallest possible loss for a diode ring mixer is 3.9dB. That means your answer should be greater than 3.9dB. -* Try changing one of the LO transformer secondary winding inductances by 1%. What happens to the LO isolation? -* Try changing one of the RF transformer secondary winding inductances by 1%. What happens to the IF isolation? Now try changing the inductance by 50%. What happens to the IF isolation? -* Try varying the LO amplitude to 0.2V and 1V. What happens to the conversion loss? - * It turns out that an LO amplitude of roughly 0.7V (or 7dBm, which means a voltage source of 1.4V) is close to optimal for diode ring mixers. Many commercial ring mixers will specify a LO drive of 7dBm. +- Verify that the RF output contains the sum and difference frequencies by using the FFT method introduced in Assignment 2. Save a screenshot of the spectrum. +- Verify that there is essentially zero leakage from the LO port to the RF port, and the IF port to the RF port. You will need to perform the FFT of the voltage at the port in question and check the magnitude of the test port’s frequency - so you might put a cursor at 1MHz, on the FFT of your RF output to see the IF to RF leakage. Similarly, for the LO leakage, you would put the cursor at 4Mhz on the FFT of the RF output FFT. +- Determine the conversion loss of the mixer. Conversion loss is defined here as the ratio of output power at the RF port at 5MHz to the input power at the IF port at 1MHz. This calculation should be performed in decibels (Conversion Loss (dB) = 20log10(V_RF) - 20log10(V_IF) ) + - You can determine RF and IF voltage in dB easily by looking at the FFT of each signal. By default, the FFT will be plotted in dB scale. The difference between the two in dB is the conversion loss. Note: make sure to only look at the frequency of interest (5MHz) at the RF port. + - If this was a downconversion mixer, the conversion loss would be defined as the ratio between the IF port power and the RF port power (i.e., your input would be at an intermediate frequency and your output would be at the radio frequency). + - Fun fact: the smallest possible loss for a diode ring mixer is 3.9dB. That means your answer should be greater than 3.9dB. +- Try changing one of the LO transformer secondary winding inductances by 1%. What happens to the LO isolation? +- Try changing one of the RF transformer secondary winding inductances by 1%. What happens to the IF isolation? Now try changing the inductance by 50%. What happens to the IF isolation? +- Try varying the LO amplitude to 0.2V and 1V. What happens to the conversion loss? + - It turns out that an LO amplitude of roughly 0.7V (or 7dBm, which means a voltage source of 1.4V) is close to optimal for diode ring mixers. Many commercial ring mixers will specify a LO drive of 7dBm. Now that you designed one mixer to upconvert from 1MHz to 5MHz, you can design the other three as well - one to upconvert from 5MHz to 27MHz and two to downconvert, from 27MHz to 5MHz and from 5MHz to 1MHz. Do not try to connect the output of one mixer to the input of another - with so many unfiltered harmonics you will get near gibberish at the output. To design the other mixers, you will need to create new voltage sources at the appropriate frequencies (you can use the same amplitudes as above). The schematics will likely be the same, with some changes to the values of inductors used in the transformers. You should repeat the measurements for leakage and conversion loss. - ## Part 2: Driving LO Port with an Oscillator Next, we’ll see how we can use an oscillator to drive the LO port of the mixer. Pull out the oscillators you designed from module 2! @@ -112,16 +101,15 @@ When choosing your bias resistors, remember that the input impedance for this bu **Checkpoint 2: The Mixer + Oscillator** -With the buffer designed, hook up your oscillator, buffer and mixer together. The IF should still be driven by a perfect voltage source with a 50Ω internal resistance. With this configuration, find the conversion loss, LO isolation, and IF isolation. +With the buffer designed, hook up your oscillator, buffer and mixer together. The IF should still be driven by a perfect voltage source with a 50Ω internal resistance. With this configuration, find the conversion loss, LO isolation, and IF isolation. Again, make sure you can repeat this for all four mixers - with the two oscillators used for upconversion or downconversion. You should be able to use the same buffer for all schematics. When down converting, drive the RF port with a perfect voltage source with a 50Ω internal resistance, as you did for checkpoint 1. By now you should have four functional ring mixers, being driven by Colpitts oscillators at the LO port, that make the appropriate frequency conversions (i.e, we will look at input and output FFTs). - ## Part 3: Filters -Filters can be tedious to design by hand, especially to certain specifications. Thus, we are going to use an online tool to make them. In this project, we will apply filters mainly at 1 MHz, 5MHz and 27MHz, right after the Mixer Modules, as mixing introduces harmonics and other frequencies. For this part, use the tool below to create bandpass filters at these two frequencies, and put them into LTSpice. Feel free to play around with the Filter Type, Order, and Topology. Note that the higher order, the better the results, but also the more parts you will need to solder. Also, the tighter the passband, the better. However, the higher the frequency, the larger the passband will typically be. +Filters can be tedious to design by hand, especially to certain specifications. Thus, we are going to use an online tool to make them. In this project, we will apply filters mainly at 1 MHz, 5MHz and 27MHz, right after the Mixer Modules, as mixing introduces harmonics and other frequencies. For this part, use the tool below to create bandpass filters at these two frequencies, and put them into LTSpice. Feel free to play around with the Filter Type, Order, and Topology. Note that the higher order, the better the results, but also the more parts you will need to solder. Also, the tighter the passband, the better. However, the higher the frequency, the larger the passband will typically be. [RF Tools | LC Filter Design Tool (rf-tools.com)](https://rf-tools.com/lc-filter/) diff --git a/docs/WRAP/module-4.md b/docs/WRAP/module-4.md index ffe64b1..0f36993 100644 --- a/docs/WRAP/module-4.md +++ b/docs/WRAP/module-4.md @@ -1,4 +1,5 @@ # Module 4 + ### Designing the System! **Lecture Notes:** @@ -9,13 +10,11 @@ We’ve thus far covered ways of amplifying signals and generating frequencies - but is there a way to generate frequencies given other frequencies? From last time, we saw that using feedback, we can create systems whose output oscillates at a designed frequency. One common use of generating known, stable frequencies is in use of the Local Oscillator or LO of a mixer, whose operation is covered in the Lecture 3 notes. -This is also why we wanted to ensure that our signal generated by our Colpitts Oscillator had a high enough power level - our LO needs to be large enough in power that it can sustain a voltage drop of 0.6 to 0.7 V - enough to maintain forward operation of the diodes in the diode ring mixer. - - +This is also why we wanted to ensure that our signal generated by our Colpitts Oscillator had a high enough power level - our LO needs to be large enough in power that it can sustain a voltage drop of 0.6 to 0.7 V - enough to maintain forward operation of the diodes in the diode ring mixer. **Prerequisites:** -Lecture 1, 2 and 3. alongside assignment 1, 2 and 3. +Lecture 1, 2 and 3. alongside assignment 1, 2 and 3. Signals and Systems @@ -47,63 +46,53 @@ Smith Chart **Setup:** -We have finally designed all necessary components. All you have to do is put it together! This assignment introduces you to some techniques which will help you a lot during your milestone design. - +We have finally designed all necessary components. All you have to do is put it together! This assignment introduces you to some techniques which will help you a lot during your milestone design. ## Part 1: T-Attenuator -To ensure maximum power transfer, your impedance between modules should be matched! Your filters have an input and output impedance of 50 and the antenna is also 50. All these modules need to be matched. +To ensure maximum power transfer, your impedance between modules should be matched! Your filters have an input and output impedance of 50 and the antenna is also 50. All these modules need to be matched. It is best to design your modules such that they already match impedances, but oftentimes, that can be difficult such as in mixers. In this part, you will be matching your first mixer (1MHz to 5 MHZ) to the first stage buffer: - - -* Using transient analysis, measure the input impedance of your mixer at its IF port. To do so, connect a voltage source (1MHz sine wave with 1V amplitude) to the port and measure the peak current. Dividing the peak voltage of 1V by the peak current will give you the real part of the impedance. The phase difference between the current and voltage gives the imaginary part of the impedance but we don’t have to worry about that for now. Make sure your 4MHz oscillator is also connected to the LO port. You can model the filter at the RF port by either using the filter from assignment 3 terminated by 50 ohms (recommended) or simply connecting a 50 ohm resistor to the RF. -* Measure the output impedance of the first stage buffer using AC analysis as before. -* Use [Matching T Attenuator Calculator (chemandy.com)](https://chemandy.com/calculators/matching-t-attenuator-calculator.htm) to match the buffer to the mixer. Once you have inserted the T attenuator between the buffer and the mixer, plot the FFT at the output of the buffer. Go back to the online tool and play around with the attenuation factor until you find the smallest value which gives at least -35dB difference between the 1MHz peak and the rest of the peaks on the FFT. +- Using transient analysis, measure the input impedance of your mixer at its IF port. To do so, connect a voltage source (1MHz sine wave with 1V amplitude) to the port and measure the peak current. Dividing the peak voltage of 1V by the peak current will give you the real part of the impedance. The phase difference between the current and voltage gives the imaginary part of the impedance but we don’t have to worry about that for now. Make sure your 4MHz oscillator is also connected to the LO port. You can model the filter at the RF port by either using the filter from assignment 3 terminated by 50 ohms (recommended) or simply connecting a 50 ohm resistor to the RF. +- Measure the output impedance of the first stage buffer using AC analysis as before. +- Use [Matching T Attenuator Calculator (chemandy.com)](https://chemandy.com/calculators/matching-t-attenuator-calculator.htm) to match the buffer to the mixer. Once you have inserted the T attenuator between the buffer and the mixer, plot the FFT at the output of the buffer. Go back to the online tool and play around with the attenuation factor until you find the smallest value which gives at least -35dB difference between the 1MHz peak and the rest of the peaks on the FFT. **Checkpoint 1:** Show the voltage at the output of the buffer and its frequency spectrum. -Show the voltage and FFT at the RF port of the mixer with the 50 ohm load connected. - +Show the voltage and FFT at the RF port of the mixer with the 50 ohm load connected. ## Part 2: Impedance Matching with Lumped Elements (L - Networks) -At the final stage for the transmitter, we want to amplify the 27.185MHz signal and feed it into a 50 ohm antenna. The low impedance that the antenna presents significantly reduces the gain of your amplifier. Therefore, we have to add a network before the antenna so that looking into it, we see a higher impedance that is equal to the output impedance of the amplifier. We won’t ask you to use the smith chart (even though you should know how to use it as an RF engineer). For this part of the assignment you are not allowed to use a buffer. +At the final stage for the transmitter, we want to amplify the 27.185MHz signal and feed it into a 50 ohm antenna. The low impedance that the antenna presents significantly reduces the gain of your amplifier. Therefore, we have to add a network before the antenna so that looking into it, we see a higher impedance that is equal to the output impedance of the amplifier. We won’t ask you to use the smith chart (even though you should know how to use it as an RF engineer). For this part of the assignment you are not allowed to use a buffer. - - -* Create a sinusoidal voltage source with 1mV amplitude and 27.185MHz frequency. -* Design an amplifier stage with a gain of 500 so that the output with no loads connected is 500mV amplitude. This is not a trivial stage. You will probably have to cascade two common emitter amplifiers to achieve this gain. -* Measure the output impedance of this stage using AC analysis technique. -* Now connect your amplifier to a 50 ohm resistor (antenna) and measure the peak to peak voltage. Don’t forget the decoupling capacitor (100nF is a good choice for this stage). -* Next, go to [RF Impedance Matching Calculator](https://www.analog.com/en/design-center/interactive-design-tools/rf-impedance-matching-calculator.html) to create an impedance transformer. For the characteristic impedance box, enter the output impedance of your amplifier stage. The website generates two networks for you. Choose the one with reasonable values and add it in between your amplifier and antenna. Run the simulation again and measure the peak to peak voltage. You should notice an improvement in your output level. +- Create a sinusoidal voltage source with 1mV amplitude and 27.185MHz frequency. +- Design an amplifier stage with a gain of 500 so that the output with no loads connected is 500mV amplitude. This is not a trivial stage. You will probably have to cascade two common emitter amplifiers to achieve this gain. +- Measure the output impedance of this stage using AC analysis technique. +- Now connect your amplifier to a 50 ohm resistor (antenna) and measure the peak to peak voltage. Don’t forget the decoupling capacitor (100nF is a good choice for this stage). +- Next, go to [RF Impedance Matching Calculator](https://www.analog.com/en/design-center/interactive-design-tools/rf-impedance-matching-calculator.html) to create an impedance transformer. For the characteristic impedance box, enter the output impedance of your amplifier stage. The website generates two networks for you. Choose the one with reasonable values and add it in between your amplifier and antenna. Run the simulation again and measure the peak to peak voltage. You should notice an improvement in your output level. **Checkpoint 2:** -Show the output voltage plots at the antenna with and without the impedance matching network. - +Show the output voltage plots at the antenna with and without the impedance matching network. ## Part 3: Common Emitter with LC Resonator -We will finish this assignment with the last trick of the trade we learned in fall. - +We will finish this assignment with the last trick of the trade we learned in fall. ![alt_text](images/image8.png "image_tooltip") - Choose a capacitor value which gives you a Qs of at least 3 at 27Mhz (remember Rs is the antenna impedance which is 50). This capacitor should be in the order of pF. Next, calculate an inductor value which has the same reactance as the capacitor at 27Mhz. -Replace the collector resistor of your amplifier with the inductor and place the capacitor between the output and the antenna (see the picture below). This capacitor acts as a decoupling capacitor as well. +Replace the collector resistor of your amplifier with the inductor and place the capacitor between the output and the antenna (see the picture below). This capacitor acts as a decoupling capacitor as well. -Run the transient simulation and measure the output voltage at the antenna. +Run the transient simulation and measure the output voltage at the antenna. **Checkpoint 3: ** -Show the output voltage plot at the antenna along with its FFT. - +Show the output voltage plot at the antenna along with its FFT. ## Part 4: Putting it all together @@ -111,7 +100,7 @@ You are now familiar with the fundamental hardware blocks of an RF communication Amplifier, buffer, oscillator, mixer, filter, attenuator, LC-network -As our fall quarter milestone, you will design a transmitter and a receiver in LTspice. Feel free to use the architecture discussed in the lecture. However, as designers, you have complete control over how you design your hardware as long as you meet the specifications. For example, you can try another oscillator design, but you have to prove it works both theoretically and in simulation. +As our fall quarter milestone, you will design a transmitter and a receiver in LTspice. Feel free to use the architecture discussed in the lecture. However, as designers, you have complete control over how you design your hardware as long as you meet the specifications. For example, you can try another oscillator design, but you have to prove it works both theoretically and in simulation. Summary of Specifications: @@ -125,7 +114,7 @@ Frequencies must be within 27.01-27.36 MHz (Pass band) Transmitted Power: 5mW -First, let’s derive our specifications. The first two are given specifications. Don’t worry, you don’t have to calculate anything for this part, but we do encourage you to go through this to understand the justification behind our specs. +First, let’s derive our specifications. The first two are given specifications. Don’t worry, you don’t have to calculate anything for this part, but we do encourage you to go through this to understand the justification behind our specs. Target Frequency: @@ -133,7 +122,7 @@ The FCC allocates certain frequencies for different purposes/groups. As civilian Transmitted Power: -A received power of about 1uW is acceptable. With this, we can calculate the needed power for transmission over 100m using the Friis Transmission Equation. +A received power of about 1uW is acceptable. With this, we can calculate the needed power for transmission over 100m using the Friis Transmission Equation. ![alt_text](images/image7.png "image_tooltip") @@ -145,15 +134,15 @@ Gr = Gain of Transmitted Antenna in dBi = 2.15 dBi Gt = Gain of Received Antenna in dBi = 2.15 dBi - = Wavelength = 11.11 m @27MHz += Wavelength = 11.11 m @27MHz d = distance = 100m -Solving the Friis Equation with the given quantities, the transmitted power is -22.8dB or ~5mW. +Solving the Friis Equation with the given quantities, the transmitted power is -22.8dB or ~5mW. -Transmitter: +Transmitter: -Input: the input to the transmitter comes from STM32 microcontroller. Model the input signal as a 1MHz sinusoid with 1.65V amplitude and a DC offset of 1.65V (this should create a sine wave that oscillates between 0 and 3.3V which is the operating range of the microcontroller output). You can assume the output impedance of the microcontroller to be 15Kohm. +Input: the input to the transmitter comes from STM32 microcontroller. Model the input signal as a 1MHz sinusoid with 1.65V amplitude and a DC offset of 1.65V (this should create a sine wave that oscillates between 0 and 3.3V which is the operating range of the microcontroller output). You can assume the output impedance of the microcontroller to be 15Kohm. Output: Transmitted power = 5mW which corresponds to a peak to peak voltage of 1V on a 50 ohm antenna. Your signal should be a sine wave at 27.185MHz. @@ -161,4 +150,4 @@ Receiver: Input: the received power is 1uW which corresponds to a peak to peak voltage of 20mV on a 50 ohm antenna. For simplicity, assume the input is at 27.185Mhz. -Output: The final signal will be fed into another STM32. This signal should be a 1MHz sinusoid centered at 1.65V and an amplitude as close to 1.65V as possible (3.3V peak to peak). The input impedance of the microcontroller is 1Kohm. +Output: The final signal will be fed into another STM32. This signal should be a 1MHz sinusoid centered at 1.65V and an amplitude as close to 1.65V as possible (3.3V peak to peak). The input impedance of the microcontroller is 1Kohm. diff --git a/docs/pocket-racers/module-0.md b/docs/pocket-racers/module-0.md index 01240f9..7b29e6f 100644 --- a/docs/pocket-racers/module-0.md +++ b/docs/pocket-racers/module-0.md @@ -1,6 +1,5 @@ # Module 0 - ### Intro to OpenCV - [Overview](#overview) @@ -11,12 +10,10 @@ In this module, we will learn about OpenCV, the open-source library we will be using for Image Processing. For those without a Raspberry Pi, the module will walk you through how to install Python and OpenCV on your computer. For those with a Raspberry Pi, the module will also describe how to connect and send commands to your Pi from your computer, and how to prepare the Pi for image processing with OpenCV and a Raspberry Pi camera. - ## Lecture Slides {#lecture-slides} [Click here for lecture slides](https://docs.google.com/presentation/d/1mjegQI3MeFt7cMF37BtC6IsHotNk8r-EcDkOALqlRpY/edit?usp=drive_link) - ## Helpful Tips/FAQ {#helpful-tips-faq} -[Click here for FAQ sheet](https://docs.google.com/document/u/0/d/1lUnK5WOirf125nsWOR8H8y9OeY6WMU5Oy9NtQBtFl_8/edit) \ No newline at end of file +[Click here for FAQ sheet](https://docs.google.com/document/u/0/d/1lUnK5WOirf125nsWOR8H8y9OeY6WMU5Oy9NtQBtFl_8/edit) diff --git a/docs/pocket-racers/module-1.md b/docs/pocket-racers/module-1.md index bb1d13d..2b0e312 100644 --- a/docs/pocket-racers/module-1.md +++ b/docs/pocket-racers/module-1.md @@ -1,4 +1,5 @@ # Module 1 + ### Downscaling // Grayscaling, HSV Conversion // Thresholding and Adaptive Thresholding - [Overview](#overview) @@ -9,22 +10,18 @@ ## Overview {#overview} - Our first image processing module will go over how a computer sees images, how image processing works mathematically, and how we can make images easier for the computer to read and analyze. This module mostly focuses on techniques that simplify the image through color and contrast adjustments. We will learn the benefit of techniques such as downscaling, grayscaling, thresholding and adaptive thresholding. - ## Lecture Slides {#lecture-slides} [Click here for lecture slides](https://docs.google.com/presentation/d/16VabwJj7FgEXsF_ooGWiYEC7AshbvK_XKuDeHOT2990/edit?usp=drive_link) - ## Objectives {#objectives} -By the end of Module 1 in the skeleton code, you should have a thresholded grayscale image that looks similar to this: +By the end of Module 1 in the skeleton code, you should have a thresholded grayscale image that looks similar to this: ![grayscale image](images/image1.png) - ## Skeleton Code {#skeleton-code} [Modules 1-3: Dice Detection](https://colab.research.google.com/drive/1enqrfz7Y4wEG6Qgae1qbllJe3fynSznn?usp=sharing) @@ -33,14 +30,12 @@ Note that for Modules 1-3, we will be using the same Jupyter notebook for coding In the Module 1 section of the notebook, you will be walked through loading an image with OpenCV, displaying that image, converting that image to different color spaces, and applying thresholds across that image. - ## Helpful Tips/FAQ {#helpful-tips-faq} [Click here for FAQ sheet](https://docs.google.com/document/u/0/d/1lUnK5WOirf125nsWOR8H8y9OeY6WMU5Oy9NtQBtFl_8/edit) - ## Checkoff Questions {#checkoff-questions} -* What are the advantages of using HSV vs Grayscale? -* Why does your HSV converted image look weird? -* What is the benefit of increasing the Gaussian kernel size when adaptive thresholding? \ No newline at end of file +- What are the advantages of using HSV vs Grayscale? +- Why does your HSV converted image look weird? +- What is the benefit of increasing the Gaussian kernel size when adaptive thresholding? diff --git a/docs/pocket-racers/module-2.md b/docs/pocket-racers/module-2.md index 1337428..ecf4edf 100644 --- a/docs/pocket-racers/module-2.md +++ b/docs/pocket-racers/module-2.md @@ -1,4 +1,5 @@ # Module 2 + ### Box Blur, Gaussian Blur, etc. // Erosion and Dilation - [Overview](#overview) @@ -8,25 +9,20 @@ - [Helpful Tips and FAQ](#helpful-tips-faq) - [Checkoff Questions](#checkoff-questions) - ## Overview {#overview} In the second image processing module, we will introduce various methods on improving the quality of images, at least from a computer’s viewpoint. By performing techniques like blurring, erosion, and dilation, we can prepare an image for a blob detection algorithm. After going over the basic conceptual background for these techniques, we will apply them to an image of white dice to remove visual artifacts (or noise). - ## Lecture Slides {#lecture-slides} [Click here for lecture slides](https://docs.google.com/presentation/d/16VabwJj7FgEXsF_ooGWiYEC7AshbvK_XKuDeHOT2990/edit?usp=drive_link) - - ## Objectives {#objectives} -By the end of Module 2 in the skeleton code, you will have filtered out artifacts in an image, going from this to this +By the end of Module 2 in the skeleton code, you will have filtered out artifacts in an image, going from this to this ![dice](images/image2.png) - ## Skeleton Code {#skeleton-code} [Modules 1-3: Dice Detection](https://colab.research.google.com/drive/1enqrfz7Y4wEG6Qgae1qbllJe3fynSznn?usp=sharing) @@ -35,16 +31,12 @@ Note that for Modules 1-3, we will be using the same Jupyter notebook for coding In the Module 2 section of the notebook, you are given more of a free hand in exploring different image processing techniques to improve the usability of an image. By trying blurring, erosion, and dilation in different combinations, you can explore all the different ways to get to an image that will be ready for blob detection in Module 3. - ## Helpful Tips/FAQ {#helpful-tips-faq} [Click here for FAQ sheet](https://docs.google.com/document/u/0/d/1lUnK5WOirf125nsWOR8H8y9OeY6WMU5Oy9NtQBtFl_8/edit) - ## Checkoff Questions {#checkoff-questions} - - -* After eroding and dilating, circular blobs become less circular. Why might this be the case? -* To preserve the size of the image, everytime you erode you must dilate and everytime you dilate, you must erode. How do you know when to do which first? -* Why is blurring helpful? When is it appropriate to blur the image? \ No newline at end of file +- After eroding and dilating, circular blobs become less circular. Why might this be the case? +- To preserve the size of the image, everytime you erode you must dilate and everytime you dilate, you must erode. How do you know when to do which first? +- Why is blurring helpful? When is it appropriate to blur the image? diff --git a/docs/pocket-racers/module-3.md b/docs/pocket-racers/module-3.md index 23230de..969d3f8 100644 --- a/docs/pocket-racers/module-3.md +++ b/docs/pocket-racers/module-3.md @@ -1,4 +1,5 @@ # Module 3 + ### Masks and Blob Detection - [Overview](#overview) @@ -8,18 +9,15 @@ - [Helpful Links/FAQ](#helpful-tips-faq) - [Checkoff Questions](#checkoff-questions) - ## Overview {#overview} In Module 1, we learned how we can use thresholds to have OpenCV “pick out” certain parts of an image based on its pixels’ grayscale values. In general terms, this is creating a mask, which is a purely black and white image used to pick out desired features. In this module, we will learn different ways to create these masks, specifically using HSV values to filter out desired parts of our image. The second part of this module will make use of OpenCV’s blob detection feature, which allows us to count the number of blobs on the mask. We will also learn OpenCV’s Simple Blob Detector parameters, which allow us to filter blobs based on a variety of attributes like circularity, color, size, etc. - ## Lecture Slides {#lecture-slides} -[Click here for lecture slides](https://docs.google.com/presentation/d/1XfI1txHgtaMa7_NAAd37OG5br-U1x2tV51z1D6oa2p8/edit?usp=drive_link) - +[Click here for lecture slides](https://docs.google.com/presentation/d/1XfI1txHgtaMa7_NAAd37OG5br-U1x2tV51z1D6oa2p8/edit?usp=drive_link) ## Objectives {#objectives} @@ -39,14 +37,12 @@ Note that for Modules 1-3, we will be using the same Jupyter notebook for coding In the Module 3 section of the notebook, you will begin with a new image, that of two colored dice. After using some different techniques, you will arrive at a thresholded image of the dice, called a mask. Finally, after implementation of OpenCV’s simple blob detector, you have a pipeline that takes in an image of a dice and spits out the number of dots, and which pixels they are located at in the image. - ## Helpful Tips/FAQ {#helpful-tips-faq} -[Click here for FAQ sheet](https://docs.google.com/document/u/0/d/1lUnK5WOirf125nsWOR8H8y9OeY6WMU5Oy9NtQBtFl_8/edit) - +[Click here for FAQ sheet](https://docs.google.com/document/u/0/d/1lUnK5WOirf125nsWOR8H8y9OeY6WMU5Oy9NtQBtFl_8/edit) ## Checkoff Questions {#checkoff-questions} -* Imagine that a dice was thresholded poorly, and the shadow the dice cast was part of the resulting mask. If your blob detector is counting this shadow, how might you fix this? -* What bitwise function would you use to perform masking? (applying the mask to the original image) -* Why was adaptive thresholding not necessary for HSV filtering? (i.e., why were we able to set static values for the hue) \ No newline at end of file +- Imagine that a dice was thresholded poorly, and the shadow the dice cast was part of the resulting mask. If your blob detector is counting this shadow, how might you fix this? +- What bitwise function would you use to perform masking? (applying the mask to the original image) +- Why was adaptive thresholding not necessary for HSV filtering? (i.e., why were we able to set static values for the hue) diff --git a/docs/pocket-racers/module-4.md b/docs/pocket-racers/module-4.md index 22453d8..addd237 100644 --- a/docs/pocket-racers/module-4.md +++ b/docs/pocket-racers/module-4.md @@ -1,6 +1,5 @@ # Module 4 - ### All About Contours // Reading Arrows - [Overview](#overview) @@ -10,8 +9,7 @@ - [Helpful Tips/FAQ](#skeleton-code) - [Checkoff Questions](#checkoff-questions) - -## Overview {#overview} +## Overview {#overview} To continue expanding on what we have done so far, we will introduce contours, OpenCV’s even more flexible shape detection method. There is a brief conceptual overview of what contours are in the lecture slides, but the real meat of this module is the skeleton code. You will be walked through how we can use certain characteristics of a contour, like convexity, moment of inertia, center of mass, and more, to distinguish one from the other. The goal will be to preprocess an image containing a symbolic instruction, like a stop sign or an arrow, and utilize OpenCV’s contour methods to recognize that symbol as stop, forward, right, or left. @@ -19,38 +17,31 @@ To continue expanding on what we have done so far, we will introduce contours, O ## Lecture Slides {#lecture-slides} -[Click here for lecture slides](https://docs.google.com/presentation/d/18HkCl3PE8X0LkocppHsm0W58tI0TzuiOxXtO3bjuQWg/edit?usp=drive_link) - - -## +[Click here for lecture slides](https://docs.google.com/presentation/d/18HkCl3PE8X0LkocppHsm0W58tI0TzuiOxXtO3bjuQWg/edit?usp=drive_link) +## ## Objectives {#objectives} By the end of Module 4, you will have used a variety of OpenCV’s contour methods to implement a lengthy function to classify an image as a written instruction. - ## Skeleton Code {#skeleton-code} [Module 4: Contours](https://colab.research.google.com/drive/1q5mRnvqbVB1puqR1HxueBTcW1wSKTNmq?usp=sharing) -In this Jupyter notebook, you start with some unprocessed .jpg images of a stop sign and some arranged arrows. Using what you learned from Modules 1-3, and a new floodfill function, you can write a function that isolates the black shape by itself. +In this Jupyter notebook, you start with some unprocessed .jpg images of a stop sign and some arranged arrows. Using what you learned from Modules 1-3, and a new floodfill function, you can write a function that isolates the black shape by itself. Then, you will write a larger function consisting of conditional statements that distinguish between a contour’s features, like its centroid, convexity, area, and more. These will enable you to tell the difference between stop, forward, right, and left, and we have also provided a function to help you visualize how your classification scheme is working. - ## Helpful Tips/FAQ {#helpful-tips-faq} -[Click here for FAQ sheet](https://docs.google.com/document/u/0/d/1lUnK5WOirf125nsWOR8H8y9OeY6WMU5Oy9NtQBtFl_8/edit) - +[Click here for FAQ sheet](https://docs.google.com/document/u/0/d/1lUnK5WOirf125nsWOR8H8y9OeY6WMU5Oy9NtQBtFl_8/edit) ## Checkoff Questions {#checkoff-questions} - - -* How would you find the direction your car should travel if, in addition to the signs we already have, we also had a backwards arrow sign? -* What would the hierarchy list look like for a bullseye with three concentric circles? Assume the background is distinct from the bullseye’s outermost circle and there is no “noise” in the image. +- How would you find the direction your car should travel if, in addition to the signs we already have, we also had a backwards arrow sign? +- What would the hierarchy list look like for a bullseye with three concentric circles? Assume the background is distinct from the bullseye’s outermost circle and there is no “noise” in the image. ![drawing](images/image6.png) -* Why must we invert **our** image of the arrows before using OpenCV’s contour functions? (why do we want a black background instead of a white one?) \ No newline at end of file +- Why must we invert **our** image of the arrows before using OpenCV’s contour functions? (why do we want a black background instead of a white one?) diff --git a/package-lock.json b/package-lock.json index f8e4edc..7bd76d0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,15 +17,27 @@ "react-dom": "^18.2.0" }, "devDependencies": { + "@docusaurus/eslint-plugin": "^3.0.1", "@docusaurus/module-type-aliases": "3.0.1", "@docusaurus/types": "^3.0.1", "@tsconfig/docusaurus": "^2.0.2", + "eslint": "^8.56.0", + "prettier": "^3.1.1", "typescript": "^5.3.3" }, "engines": { "node": ">=18.0" } }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "devOptional": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/@algolia/autocomplete-core": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.9.3.tgz", @@ -2264,6 +2276,22 @@ "node": ">=18.0" } }, + "node_modules/@docusaurus/eslint-plugin": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/eslint-plugin/-/eslint-plugin-3.0.1.tgz", + "integrity": "sha512-6t32uK6MQwm4G3di2tiAq6vHclLt6qyBqXW9rPI1scwJV+PJUxZTob4Ivf7UYH3jeOLH9YJM9L9QIhnhmabQmQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/utils": "^5.62.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "eslint": ">=6" + } + }, "node_modules/@docusaurus/logger": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.0.1.tgz", @@ -2752,6 +2780,111 @@ "node": ">=18.0" } }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "devOptional": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "devOptional": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "devOptional": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "devOptional": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "devOptional": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "devOptional": true + }, + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "devOptional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", + "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "devOptional": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/@hapi/hoek": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", @@ -2765,6 +2898,39 @@ "@hapi/hoek": "^9.0.0" } }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "devOptional": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "devOptional": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "devOptional": true + }, "node_modules/@jest/schemas": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", @@ -3589,6 +3755,12 @@ "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==" }, + "node_modules/@types/semver": { + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", + "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", + "dev": true + }, "node_modules/@types/send": { "version": "0.17.4", "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", @@ -3650,6 +3822,106 @@ "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==" }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@ungap/structured-clone": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", @@ -5391,6 +5663,12 @@ "node": ">=4.0.0" } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "devOptional": true + }, "node_modules/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", @@ -5587,6 +5865,18 @@ "node": ">=6" } }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "devOptional": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/dom-converter": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", @@ -5803,6 +6093,61 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/eslint": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", + "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "devOptional": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.56.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -5815,6 +6160,203 @@ "node": ">=8.0.0" } }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "devOptional": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "devOptional": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "devOptional": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "devOptional": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "devOptional": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "devOptional": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "devOptional": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "devOptional": true + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "devOptional": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "devOptional": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "devOptional": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "devOptional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "devOptional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "devOptional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "devOptional": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", @@ -5827,6 +6369,27 @@ "node": ">=4" } }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "devOptional": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "devOptional": true, + "engines": { + "node": ">=4.0" + } + }, "node_modules/esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", @@ -6138,6 +6701,12 @@ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "devOptional": true + }, "node_modules/fast-url-parser": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", @@ -6188,6 +6757,18 @@ "node": ">=0.4.0" } }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "devOptional": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, "node_modules/file-loader": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", @@ -6339,6 +6920,26 @@ "flat": "cli.js" } }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "devOptional": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "devOptional": true + }, "node_modules/follow-redirects": { "version": "1.15.3", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", @@ -6779,6 +7380,12 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "devOptional": true + }, "node_modules/gray-matter": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", @@ -7911,6 +8518,12 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "devOptional": true + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -7988,6 +8601,19 @@ "node": ">=6" } }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "devOptional": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/lilconfig": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", @@ -8051,6 +8677,12 @@ "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==" }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "devOptional": true + }, "node_modules/lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", @@ -10366,6 +10998,12 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "devOptional": true + }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -10580,6 +11218,23 @@ "opener": "bin/opener-bin.js" } }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "devOptional": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/p-cancelable": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", @@ -11521,6 +12176,30 @@ "postcss": "^8.2.15" } }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "devOptional": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.1.tgz", + "integrity": "sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/pretty-error": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", @@ -13569,6 +14248,39 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "devOptional": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-fest": { "version": "2.19.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", diff --git a/package.json b/package.json index d9f1316..158b317 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,9 @@ "serve": "docusaurus serve", "write-translations": "docusaurus write-translations", "write-heading-ids": "docusaurus write-heading-ids", - "typecheck": "tsc" + "typecheck": "tsc", + "format": "prettier --write .", + "lint": "prettier --check . && eslint ." }, "dependencies": { "@docusaurus/core": "3.0.1", @@ -24,9 +26,12 @@ "react-dom": "^18.2.0" }, "devDependencies": { + "@docusaurus/eslint-plugin": "^3.0.1", "@docusaurus/module-type-aliases": "3.0.1", "@docusaurus/types": "^3.0.1", "@tsconfig/docusaurus": "^2.0.2", + "eslint": "^8.56.0", + "prettier": "^3.1.1", "typescript": "^5.3.3" }, "browserslist": { diff --git a/sidebars.js b/sidebars.js index 6920585..56a509f 100644 --- a/sidebars.js +++ b/sidebars.js @@ -14,7 +14,7 @@ /** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ const sidebars = { // By default, Docusaurus generates a sidebar from the docs folder structure - docsSidebar: [{type: 'autogenerated', dirName: '.'}], + docsSidebar: [{ type: "autogenerated", dirName: "." }], // But you can create a sidebar manually /* diff --git a/src/css/custom.css b/src/css/custom.css index ac1d744..c3c6993 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -18,7 +18,7 @@ } /* For readability concerns, you should choose a lighter palette in dark mode. */ -[data-theme='dark'] { +[data-theme="dark"] { --ifm-color-primary: #25c2a0; --ifm-color-primary-dark: #21af90; --ifm-color-primary-darker: #1fa588;