From 65e72c962cba2af9f3422694465850936d74c5a2 Mon Sep 17 00:00:00 2001 From: Kevin Thomas Date: Sat, 17 Oct 2026 15:35:24 -0400 Subject: [PATCH] Restore original legacy source files from Embedded-Hacking-main to match course markdown and PDFs --- 0x0001_hello-world/0x0001_hello-world.c | 41 +--- .../0x0005_intro-to-variables.c | 43 +--- .../0x0008_uninitialized-variables-a.c | 45 +--- .../0x0008_uninitialized-variables-b.c | 83 ++----- .../0x0008_uninitialized-variables-c.c | 90 ++------ .../0x0008_uninitialized-variables-d.c | 136 +++-------- .../0x0008_uninitialized-variables-e.c | 42 +--- .../0x0008_uninitialized-variables.c | 67 +----- .../0x000b_integer-data-type.c | 143 ++++-------- .../0x000e_floating-point-data-type.c | 42 +--- .../0x0011_double-floating-point-data-type.c | 42 +--- .../0x0014_static-variables.c | 95 ++------ 0x0017_constants/0x0017_constants.c | 81 +------ 0x0017_constants/lcd_1602.c | 72 ++---- 0x001a_operators/0x001a_operators.c | 140 ++---------- 0x001a_operators/dht11.c | 125 +++------- .../0x001d_static-conditionals.c | 119 +++------- 0x001d_static-conditionals/servo.c | 60 ++--- .../0x0020_dynamic-conditionals.c | 127 +++------- 0x0020_dynamic-conditionals/servo.c | 60 ++--- 0x0023_structures/0x0023_structures.c | 159 +++---------- 0x0023_structures/ir.c | 102 +++------ 0x0026_functions/0x0026_functions.c | 216 ++++++------------ 0x0026_functions/ir.c | 102 +++------ .../0x0001_hello-world/0x0001_hello-world.c | 41 +--- .../0x0001_hello-world/0x0001_hello-world.c | 41 +--- .../0x0001_hello-world/0x0001_hello-world.c | 41 +--- .../0x0005_intro-to-variables.c | 43 +--- .../0x0008_uninitialized-variables-a.c | 45 +--- .../0x0008_uninitialized-variables-b.c | 83 ++----- .../0x0008_uninitialized-variables-c.c | 90 ++------ .../0x0008_uninitialized-variables-d.c | 136 +++-------- .../0x0008_uninitialized-variables-e.c | 42 +--- .../0x0008_uninitialized-variables.c | 67 +----- .../0x000b_integer-data-type.c | 143 ++++-------- .../0x000e_floating-point-data-type.c | 42 +--- .../0x0011_double-floating-point-data-type.c | 42 +--- .../0x0014_static-variables.c | 95 ++------ WEEK07/0x0017_constants/0x0017_constants.c | 81 +------ WEEK07/0x0017_constants/lcd_1602.c | 72 ++---- WEEK09/0x001a_operators/0x001a_operators.c | 140 ++---------- WEEK09/0x001a_operators/dht11.c | 125 +++------- .../0x001d_static-conditionals.c | 119 +++------- WEEK10/0x001d_static-conditionals/servo.c | 60 ++--- .../0x0020_dynamic-conditionals.c | 127 +++------- WEEK10/0x0020_dynamic-conditionals/servo.c | 60 ++--- WEEK11/0x0023_structures/0x0023_structures.c | 159 +++---------- WEEK11/0x0023_structures/ir.c | 102 +++------ WEEK11/0x0026_functions/0x0026_functions.c | 216 ++++++------------ WEEK11/0x0026_functions/ir.c | 102 +++------ 50 files changed, 970 insertions(+), 3576 deletions(-) diff --git a/0x0001_hello-world/0x0001_hello-world.c b/0x0001_hello-world/0x0001_hello-world.c index 7f7b062..096aba7 100644 --- a/0x0001_hello-world/0x0001_hello-world.c +++ b/0x0001_hello-world/0x0001_hello-world.c @@ -1,46 +1,9 @@ -/** - * @file 0x0001_hello-world.c - * @brief Hello World: print a greeting over UART in an infinite loop - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Demonstrates the minimal "hello, world" program on the Raspberry Pi Pico 2. - * Initializes stdio over UART and prints a greeting in an infinite loop. - * - * Wiring: - * No external wiring required (USB serial). - */ - #include #include "pico/stdlib.h" int main(void) { stdio_init_all(); - while (true) { + + while (true) printf("hello, world\r\n"); - } } diff --git a/0x0005_intro-to-variables/0x0005_intro-to-variables.c b/0x0005_intro-to-variables/0x0005_intro-to-variables.c index 29f6b2d..7b2b3ae 100644 --- a/0x0005_intro-to-variables/0x0005_intro-to-variables.c +++ b/0x0005_intro-to-variables/0x0005_intro-to-variables.c @@ -1,48 +1,13 @@ -/** - * @file 0x0005_intro-to-variables.c - * @brief Introduction to variables: declare, assign, and print a uint8_t - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Demonstrates declaring, initializing, and reassigning a uint8_t variable. - * Prints the variable value over UART in an infinite loop. - * - * Wiring: - * No external wiring required (USB serial). - */ - #include #include "pico/stdlib.h" int main(void) { uint8_t age = 42; + age = 43; + stdio_init_all(); - while (true) { + + while (true) printf("age: %d\r\n", age); - } } diff --git a/0x0008_uninitialized-variables-a/0x0008_uninitialized-variables-a.c b/0x0008_uninitialized-variables-a/0x0008_uninitialized-variables-a.c index 9d2ddb3..656a992 100644 --- a/0x0008_uninitialized-variables-a/0x0008_uninitialized-variables-a.c +++ b/0x0008_uninitialized-variables-a/0x0008_uninitialized-variables-a.c @@ -1,52 +1,17 @@ -/** - * @file 0x0008_uninitialized-variables-a.c - * @brief Blink LED using SDK gpio functions (no UART) - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Blinks an LED on GPIO16 using the standard Pico SDK gpio_init / gpio_put - * functions. No UART output; pure GPIO blink demonstration. - * - * Wiring: - * GPIO16 -> LED anode (with current-limiting resistor to GND) - */ - #include #include "pico/stdlib.h" -/** @brief GPIO pin number for the LED */ -#define LED_PIN 16 +#define LED_PIN 16 -int main(void) { +int main(void) +{ gpio_init(LED_PIN); gpio_set_dir(LED_PIN, GPIO_OUT); + while (true) { gpio_put(LED_PIN, 1); sleep_ms(500); + gpio_put(LED_PIN, 0); sleep_ms(500); } diff --git a/0x0008_uninitialized-variables-b/0x0008_uninitialized-variables-b.c b/0x0008_uninitialized-variables-b/0x0008_uninitialized-variables-b.c index b42c544..365d7eb 100644 --- a/0x0008_uninitialized-variables-b/0x0008_uninitialized-variables-b.c +++ b/0x0008_uninitialized-variables-b/0x0008_uninitialized-variables-b.c @@ -1,80 +1,27 @@ -/** - * @file 0x0008_uninitialized-variables-b.c - * @brief Blink LED using gpioc coprocessor bit-level functions - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Blinks an LED on GPIO16 using the RP2350 gpioc coprocessor bit-level - * functions (gpioc_bit_oe_put / gpioc_bit_out_put) instead of the standard - * gpio_init / gpio_put SDK calls. - * - * Wiring: - * GPIO16 -> LED anode (with current-limiting resistor to GND) - */ - #include #include "pico/stdlib.h" -/** @brief GPIO pin number for the LED */ -#define LED_PIN 16 +#define LED_PIN 16 -/** - * @brief Initialize GPIO16 for output using coprocessor bit functions - * - * @details Configures the pad for SIO, sets direction to input first, - * clears the output, selects SIO function, then enables output. - * - * @retval None - */ -static void gpio_coprocessor_init(void) { +int main(void) +{ + // gpio_init(LED_PIN); gpio_set_dir(LED_PIN, GPIO_IN); gpio_put(LED_PIN, 0); gpio_set_function(LED_PIN, GPIO_FUNC_SIO); + + // gpio_set_dir(LED_PIN, GPIO_OUT); gpioc_bit_oe_put(LED_PIN, GPIO_OUT); -} -/** - * @brief Blink LED using coprocessor bit output functions - * - * @details Toggles the LED on and off with 500ms delays using - * gpioc_bit_out_put and sleep_us. - * - * @retval None - */ -static void blink_cycle(void) { - gpioc_bit_out_put(LED_PIN, 1); - sleep_us(500 * 1000ull); - gpioc_bit_out_put(LED_PIN, 0); - sleep_us(500 * 1000ull); -} - -int main(void) { - gpio_coprocessor_init(); while (true) { - blink_cycle(); + // gpio_put(LED_PIN, 1); + gpioc_bit_out_put(LED_PIN, 1); + // sleep_ms(500); + sleep_us(500 * 1000ull); + + // gpio_put(LED_PIN, 0); + gpioc_bit_out_put(LED_PIN, 0); + // sleep_ms(500); + sleep_us(500 * 1000ull); } } diff --git a/0x0008_uninitialized-variables-c/0x0008_uninitialized-variables-c.c b/0x0008_uninitialized-variables-c/0x0008_uninitialized-variables-c.c index 40771de..5136c35 100644 --- a/0x0008_uninitialized-variables-c/0x0008_uninitialized-variables-c.c +++ b/0x0008_uninitialized-variables-c/0x0008_uninitialized-variables-c.c @@ -1,85 +1,35 @@ -/** - * @file 0x0008_uninitialized-variables-c.c - * @brief Blink LED using direct register-level pad and IO bank configuration - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Blinks an LED on GPIO16 using direct register writes to PADS_BANK0 and - * IO_BANK0 for pad configuration, plus gpioc coprocessor bit-level functions - * for output enable and data. Demonstrates the register-level equivalent of - * gpio_init / gpio_set_function. - * - * Wiring: - * GPIO16 -> LED anode (with current-limiting resistor to GND) - */ - #include #include "pico/stdlib.h" -/** @brief GPIO pin number for the LED */ -#define LED_PIN 16 +#define LED_PIN 16 -/** - * @brief Configure pad and IO bank registers for GPIO16 as SIO output - * - * @details Sets PADS_BANK0 IE/OD bits, assigns FUNCSEL to SIO in IO_BANK0, - * clears the ISO bit, and enables output via the coprocessor. - * - * @retval None - */ -static void configure_pad_and_iobank(void) { +int main(void) +{ + // gpio_init(LED_PIN); + /// gpio_set_dir(LED_PIN, GPIO_IN); gpioc_bit_oe_put(LED_PIN, GPIO_OUT); + /// gpio_put(LED_PIN, 0); gpioc_bit_out_put(LED_PIN, 0); + /// gpio_set_function(LED_PIN, GPIO_FUNC_SIO); hw_write_masked(&pads_bank0_hw->io[LED_PIN], PADS_BANK0_GPIO0_IE_BITS, - PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS); + PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS + ); io_bank0_hw->io[LED_PIN].ctrl = GPIO_FUNC_SIO << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB; hw_clear_bits(&pads_bank0_hw->io[LED_PIN], PADS_BANK0_GPIO0_ISO_BITS); + + // gpio_set_dir(LED_PIN, GPIO_OUT); gpioc_bit_oe_put(LED_PIN, GPIO_OUT); -} -/** - * @brief Blink LED using coprocessor bit output functions - * - * @details Toggles the LED on and off with 500ms delays using - * gpioc_bit_out_put and sleep_us. - * - * @retval None - */ -static void blink_cycle(void) { - gpioc_bit_out_put(LED_PIN, 1); - sleep_us(500 * 1000ull); - gpioc_bit_out_put(LED_PIN, 0); - sleep_us(500 * 1000ull); -} - -int main(void) { - configure_pad_and_iobank(); while (true) { - blink_cycle(); + // gpio_put(LED_PIN, 1); + gpioc_bit_out_put(LED_PIN, 1); + // sleep_ms(500); + sleep_us(500 * 1000ull); + + // gpio_put(LED_PIN, 0); + gpioc_bit_out_put(LED_PIN, 0); + // sleep_ms(500); + sleep_us(500 * 1000ull); } } diff --git a/0x0008_uninitialized-variables-d/0x0008_uninitialized-variables-d.c b/0x0008_uninitialized-variables-d/0x0008_uninitialized-variables-d.c index b834115..457ed9a 100644 --- a/0x0008_uninitialized-variables-d/0x0008_uninitialized-variables-d.c +++ b/0x0008_uninitialized-variables-d/0x0008_uninitialized-variables-d.c @@ -1,70 +1,23 @@ -/** - * @file 0x0008_uninitialized-variables-d.c - * @brief Blink LED using pico_default_asm_volatile coprocessor instructions - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Blinks an LED on GPIO16 using pico_default_asm_volatile to emit mcrr - * coprocessor instructions for GPIO output enable and data, plus inline - * assembly for pad configuration (hw_write_masked, IO_BANK0 FUNCSEL, - * hw_clear_bits equivalents). - * - * Wiring: - * GPIO16 -> LED anode (with current-limiting resistor to GND) - */ - #include #include "pico/stdlib.h" -/** @brief GPIO pin number for the LED */ -#define LED_PIN 16 +#define LED_PIN 16 -/** - * @brief Enable output and set initial coprocessor OE/OUT via mcrr - * - * @details Issues two mcrr p0 instructions: one to enable output direction, - * one to set the initial output state. - * - * @retval None - */ -static void asm_set_oe_and_out(void) { +int main(void) +{ + // gpio_init(LED_PIN); + /// gpio_set_dir(LED_PIN, GPIO_IN); + //// gpioc_bit_oe_put(LED_PIN, GPIO_OUT); pico_default_asm_volatile ("mcrr p0, #4, %0, %1, c4" : : "r" (LED_PIN), "r" (GPIO_OUT)); + /// gpio_put(LED_PIN, 0); + //// gpioc_bit_out_put(LED_PIN, 0); pico_default_asm_volatile ("mcrr p0, #4, %0, %1, c4" : : "r" (LED_PIN), "r" (GPIO_OUT)); -} - -/** - * @brief Configure PADS_BANK0 IE/OD bits via inline assembly hw_xor_bits - * - * @details Performs a read-modify-write on the pad register to set IE - * and clear OD, replicating hw_write_masked behavior. - * - * @retval None - */ -static void asm_configure_pad(void) { + /// gpio_set_function(LED_PIN, GPIO_FUNC_SIO); + //// hw_write_masked(&pads_bank0_hw->io[LED_PIN], + //// PADS_BANK0_GPIO0_IE_BITS, + //// PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS + //// ); + //// hw_xor_bits(addr, (*addr ^ values) & write_mask); pico_default_asm_volatile ( "ldr r2, [%0]\n" // load current pad register "eor r2, r2, %1\n" // xor with IE bit @@ -77,17 +30,8 @@ static void asm_configure_pad(void) { "r" (PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS) : "r2", "memory" ); -} -/** - * @brief Set IO_BANK0 FUNCSEL to SIO via inline assembly store - * - * @details Writes the SIO function select value directly to the - * IO_BANK0 GPIO control register. - * - * @retval None - */ -static void asm_set_funcsel(void) { + /// io_bank0_hw->io[LED_PIN].ctrl = GPIO_FUNC_SIO << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB; pico_default_asm_volatile ( "str %1, [%0]\n" : @@ -95,50 +39,32 @@ static void asm_set_funcsel(void) { "r" (GPIO_FUNC_SIO << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB) : "memory" ); -} - -/** - * @brief Clear ISO bits in PADS_BANK0 via inline assembly - * - * @details Performs a read-modify-write to clear the pad isolation - * bit, un-isolating the pad for normal operation. - * - * @retval None - */ -static void asm_clear_iso(void) { + /// hw_clear_bits(&pads_bank0_hw->io[LED_PIN], PADS_BANK0_GPIO0_ISO_BITS); pico_default_asm_volatile ( "ldr r2, [%0]\n" // load current register value "bic r2, r2, %1\n" // clear the ISO bits (bit clear) - "str r2, [%0]\n" // write back + "str r2, [%0]\n" // write back : : "r" (&pads_bank0_hw->io[LED_PIN]), "r" (PADS_BANK0_GPIO0_ISO_BITS) : "r2", "memory" ); -} -/** - * @brief Blink LED using coprocessor mcrr output instructions - * - * @details Toggles the LED on and off with 500ms delays using - * pico_default_asm_volatile mcrr instructions. - * - * @retval None - */ -static void asm_blink_cycle(void) { - pico_default_asm_volatile ("mcrr p0, #4, %0, %1, c0" : : "r" (LED_PIN), "r" (1)); - sleep_us(500 * 1000ull); - pico_default_asm_volatile ("mcrr p0, #4, %0, %1, c0" : : "r" (LED_PIN), "r" (0)); - sleep_us(500 * 1000ull); -} - -int main(void) { - asm_set_oe_and_out(); - asm_configure_pad(); - asm_set_funcsel(); - asm_clear_iso(); + // gpio_set_dir(LED_PIN, GPIO_OUT); + /// gpioc_bit_oe_put(LED_PIN, GPIO_OUT); pico_default_asm_volatile ("mcrr p0, #4, %0, %1, c4" : : "r" (LED_PIN), "r" (GPIO_OUT)); + while (true) { - asm_blink_cycle(); + // gpio_put(LED_PIN, 1); + /// gpioc_bit_out_put(LED_PIN, 1); + pico_default_asm_volatile ("mcrr p0, #4, %0, %1, c0" : : "r" (LED_PIN), "r" (1)); + /// sleep_ms(500); + sleep_us(500 * 1000ull); + + // gpio_put(LED_PIN, 0); + /// gpioc_bit_out_put(LED_PIN, 0); + pico_default_asm_volatile ("mcrr p0, #4, %0, %1, c0" : : "r" (LED_PIN), "r" (0)); + /// sleep_ms(500); + sleep_us(500 * 1000ull); } } diff --git a/0x0008_uninitialized-variables-e/0x0008_uninitialized-variables-e.c b/0x0008_uninitialized-variables-e/0x0008_uninitialized-variables-e.c index ac572c8..5dba746 100644 --- a/0x0008_uninitialized-variables-e/0x0008_uninitialized-variables-e.c +++ b/0x0008_uninitialized-variables-e/0x0008_uninitialized-variables-e.c @@ -1,43 +1,5 @@ -/** - * @file 0x0008_uninitialized-variables-e.c - * @brief Blink LED using pure inline ARM assembly with direct register addresses - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Blinks an LED on GPIO16 using pure inline ARM assembly. No SDK calls, no - * includes. Configures PADS_BANK0, IO_BANK0, and GPIO coprocessor via direct - * register addresses and mcrr instructions, with a busy-wait delay loop. - * - * Wiring: - * GPIO16 -> LED anode (with current-limiting resistor to GND) - */ - -int main(void) { - __asm__ volatile ( +int main(void) { + __asm__ volatile ( // gpio_init(LED_PIN); /// gpio_set_dir(LED_PIN, GPIO_IN); //// gpioc_bit_oe_put(LED_PIN, GPIO_OUT); diff --git a/0x0008_uninitialized-variables/0x0008_uninitialized-variables.c b/0x0008_uninitialized-variables/0x0008_uninitialized-variables.c index 8e9dc42..0c94677 100644 --- a/0x0008_uninitialized-variables/0x0008_uninitialized-variables.c +++ b/0x0008_uninitialized-variables/0x0008_uninitialized-variables.c @@ -1,68 +1,23 @@ -/** - * @file 0x0008_uninitialized-variables.c - * @brief Uninitialized variables: demonstrate undefined behavior with printf - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Demonstrates the danger of uninitialized variables. Prints the value of an - * uninitialized uint8_t over UART while blinking an LED on GPIO16. - * - * Wiring: - * GPIO16 -> LED anode (with current-limiting resistor to GND) - */ - #include #include "pico/stdlib.h" -/** @brief GPIO pin number for the LED */ -#define LED_PIN 16 - -/** - * @brief Toggle LED and print uninitialized variable value - * - * @details Blinks the LED on and off with a 500ms delay between each - * transition and prints the age variable each cycle. - * - * @param age value to print (uninitialized in this demo) - */ -static void blink_and_print(uint8_t age) { - printf("age: %d\r\n", age); - gpio_put(LED_PIN, 1); - sleep_ms(500); - gpio_put(LED_PIN, 0); - sleep_ms(500); -} +#define LED_PIN 16 int main(void) { uint8_t age; + stdio_init_all(); + gpio_init(LED_PIN); gpio_set_dir(LED_PIN, GPIO_OUT); + while (true) { - blink_and_print(age); + printf("age: %d\r\n", age); + + gpio_put(LED_PIN, 1); + sleep_ms(500); + + gpio_put(LED_PIN, 0); + sleep_ms(500); } } diff --git a/0x000b_integer-data-type/0x000b_integer-data-type.c b/0x000b_integer-data-type/0x000b_integer-data-type.c index c923449..6a0d6ab 100644 --- a/0x000b_integer-data-type/0x000b_integer-data-type.c +++ b/0x000b_integer-data-type/0x000b_integer-data-type.c @@ -1,59 +1,17 @@ -/** - * @file 0x000b_integer-data-type.c - * @brief Integer data types: cycle LEDs on GPIO16-18 with asm, print int values - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Demonstrates uint8_t and int8_t integer data types. Initializes GPIO16-18 - * via inline assembly (PADS_BANK0, IO_BANK0, coprocessor OE), then cycles - * LEDs using coprocessor mcrr instructions while printing integer values. - * - * Wiring: - * GPIO16 -> LED1 anode (with current-limiting resistor to GND) - * GPIO17 -> LED2 anode (with current-limiting resistor to GND) - * GPIO18 -> LED3 anode (with current-limiting resistor to GND) - */ +#include +#include "pico/stdlib.h" -#include -#include "pico/stdlib.h" +int main(void) { + uint8_t age = 43; + int8_t range = -42; -/** - * @brief Initialize GPIO16-18 as SIO outputs via inline assembly loop - * - * @details Configures PADS_BANK0 (clear OD+ISO, set IE), IO_BANK0 - * (FUNCSEL=5 SIO), and coprocessor OE for pins 16-18. - * - * @retval None - */ -static void asm_init_gpio_range(void) { - __asm volatile ( + stdio_init_all(); + + __asm volatile ( "ldr r3, =0x40038000\n" // address of PADS_BANK0_BASE "ldr r2, =0x40028004\n" // address of IO_BANK0 GPIO0.ctrl "movs r0, #16\n" // GPIO16 (start pin) + "init_loop:\n" // loop start "lsls r1, r0, #2\n" // pin * 4 (pad offset) "adds r4, r3, r1\n" // PADS base + offset @@ -61,72 +19,49 @@ static void asm_init_gpio_range(void) { "bic r5, r5, #0x180\n" // clear OD+ISO "orr r5, r5, #0x40\n" // set IE "str r5, [r4]\n" // store updated config + "lsls r1, r0, #3\n" // pin * 8 (ctrl offset) "adds r4, r2, r1\n" // IO_BANK0 base + offset "ldr r5, [r4]\n" // load current config "bic r5, r5, #0x1f\n" // clear FUNCSEL bits [4:0] "orr r5, r5, #5\n" // set FUNCSEL = 5 (SIO) "str r5, [r4]\n" // store updated config + "mov r4, r0\n" // pin "movs r5, #1\n" // bit 1; used for OUT/OE writes "mcrr p0, #4, r4, r5, c4\n" // gpioc_bit_oe_put(pin,1) "adds r0, r0, #1\n" // increment pin "cmp r0, #20\n" // stop after pin 18 "blt init_loop\n" // loop until r0 == 20 - ); -} + ); -/** - * @brief Blink a single pin using coprocessor mcrr instructions - * - * @details Turns the specified pin on for 500ms, then off for 500ms - * using inline asm mcrr coprocessor output instructions. - * - * @param pin GPIO pin number to blink - * @retval None - */ -static void asm_blink_pin(uint8_t pin) { - __asm volatile ( - "mov r4, %0\n" - "movs r5, #0x01\n" - "mcrr p0, #4, r4, r5, c0\n" - : : "r"(pin) : "r4", "r5" - ); - sleep_ms(500); - __asm volatile ( - "mov r4, %0\n" - "movs r5, #0\n" - "mcrr p0, #4, r4, r5, c0\n" - : : "r"(pin) : "r4", "r5" - ); - sleep_ms(500); -} + uint8_t pin = 16; -/** - * @brief Blink LED, advance pin, and print age/range - * - * @details Blinks the current pin, wraps pin 16-18, - * and prints both integer variables. - * - * @param pin pointer to the current GPIO pin number - * @param age unsigned 8-bit age value - * @param range signed 8-bit range value - * @retval None - */ -static void blink_and_print(uint8_t *pin, uint8_t age, int8_t range) { - asm_blink_pin(*pin); - *pin = (*pin > 18) ? 16 : *pin + 1; - printf("age: %d\r\n", age); - printf("range: %d\r\n", range); -} + while (1) { + __asm volatile ( + "mov r4, %0\n" // pin + "movs r5, #0x01\n" // bit 1; used for OUT/OE writes + "mcrr p0, #4, r4, r5, c0\n" // gpioc_bit_out_put(16, 1) + : + : "r"(pin) + : "r4","r5" + ); + sleep_ms(500); -int main(void) { - uint8_t age = 43; - int8_t range = -42; - stdio_init_all(); - asm_init_gpio_range(); - uint8_t pin = 16; - while (1) { - blink_and_print(&pin, age, range); - } + __asm volatile ( + "mov r4, %0\n" // pin + "movs r5, #0\n" // bit 0; used for OUT/OE writes + "mcrr p0, #4, r4, r5, c0\n" // gpioc_bit_out_put(16, 0) + : + : "r"(pin) + : "r4","r5" + ); + sleep_ms(500); + + pin++; + if (pin > 18) pin = 16; + + printf("age: %d\r\n", age); + printf("range: %d\r\n", range); + } } diff --git a/0x000e_floating-point-data-type/0x000e_floating-point-data-type.c b/0x000e_floating-point-data-type/0x000e_floating-point-data-type.c index f0a3bac..fb3d382 100644 --- a/0x000e_floating-point-data-type/0x000e_floating-point-data-type.c +++ b/0x000e_floating-point-data-type/0x000e_floating-point-data-type.c @@ -1,47 +1,11 @@ -/** - * @file 0x000e_floating-point-data-type.c - * @brief Floating-point data type: print a float value over UART - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Demonstrates the float data type on the Raspberry Pi Pico 2. Initializes - * a float variable and prints its value over UART in an infinite loop. - * - * Wiring: - * No external wiring required (USB serial). - */ - #include #include "pico/stdlib.h" int main(void) { float fav_num = 42.5; + stdio_init_all(); - while (true) { + + while (true) printf("fav_num: %f\r\n", fav_num); - } } diff --git a/0x0011_double-floating-point-data-type/0x0011_double-floating-point-data-type.c b/0x0011_double-floating-point-data-type/0x0011_double-floating-point-data-type.c index 753f51d..d4f3d11 100644 --- a/0x0011_double-floating-point-data-type/0x0011_double-floating-point-data-type.c +++ b/0x0011_double-floating-point-data-type/0x0011_double-floating-point-data-type.c @@ -1,47 +1,11 @@ -/** - * @file 0x0011_double-floating-point-data-type.c - * @brief Double floating-point data type: print a double value over UART - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Demonstrates the double data type on the Raspberry Pi Pico 2. Initializes - * a double variable and prints its value over UART in an infinite loop. - * - * Wiring: - * No external wiring required (USB serial). - */ - #include #include "pico/stdlib.h" int main(void) { double fav_num = 42.52525; + stdio_init_all(); - while (true) { + + while (true) printf("fav_num: %lf\r\n", fav_num); - } } diff --git a/0x0014_static-variables/0x0014_static-variables.c b/0x0014_static-variables/0x0014_static-variables.c index ff5fd32..bb34259 100644 --- a/0x0014_static-variables/0x0014_static-variables.c +++ b/0x0014_static-variables/0x0014_static-variables.c @@ -1,90 +1,31 @@ -/** - * @file 0x0014_static-variables.c - * @brief Static variables: compare regular vs static local variable persistence - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Demonstrates the difference between regular and static local variables. - * A regular variable resets to 42 each iteration while a static variable - * persists and increments across loop iterations. Also reads a button on - * GPIO15 and mirrors its state to an LED on GPIO16. - * - * Wiring: - * GPIO15 -> Button (with pull-up, active low) - * GPIO16 -> LED anode (with current-limiting resistor to GND) - */ - #include #include "pico/stdlib.h" -/** @brief GPIO pin number for the button input */ -#define BUTTON_GPIO 15 -/** @brief GPIO pin number for the LED output */ -#define LED_GPIO 16 +int main(void) { + stdio_init_all(); + + const uint BUTTON_GPIO = 15; + const uint LED_GPIO = 16; + bool pressed = 0; -/** - * @brief Initialize button and LED GPIO pins - * - * @details Configures the button pin as input with pull-up and the - * LED pin as output. - * - * @retval None - */ -static void init_gpio(void) { gpio_init(BUTTON_GPIO); gpio_set_dir(BUTTON_GPIO, GPIO_IN); gpio_pull_up(BUTTON_GPIO); + gpio_init(LED_GPIO); gpio_set_dir(LED_GPIO, GPIO_OUT); -} -/** - * @brief Print and increment regular vs static variables, update LED - * - * @details Prints both variable values, increments them, reads the - * button state and drives the LED accordingly. - * - * @retval None - */ -static void demo_static_variable(void) { - uint8_t regular_fav_num = 42; - static uint8_t static_fav_num = 42; - printf("regular_fav_num: %d\r\n", regular_fav_num); - printf("static_fav_num: %d\r\n", static_fav_num); - regular_fav_num++; - static_fav_num++; - bool pressed = gpio_get(BUTTON_GPIO); - gpio_put(LED_GPIO, pressed ? 0 : 1); -} - -int main(void) { - stdio_init_all(); - init_gpio(); while (true) { - demo_static_variable(); + uint8_t regular_fav_num = 42; + static uint8_t static_fav_num = 42; + + printf("regular_fav_num: %d\r\n", regular_fav_num); + printf("static_fav_num: %d\r\n", static_fav_num); + + regular_fav_num++; + static_fav_num++; + + pressed = gpio_get(BUTTON_GPIO); + gpio_put(LED_GPIO, pressed ? 0 : 1); } } diff --git a/0x0017_constants/0x0017_constants.c b/0x0017_constants/0x0017_constants.c index f3b5182..b762ca1 100644 --- a/0x0017_constants/0x0017_constants.c +++ b/0x0017_constants/0x0017_constants.c @@ -1,98 +1,33 @@ -/** - * @file 0x0017_constants.c - * @brief Constants: demonstrate #define and const with LCD1602 I2C display - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Demonstrates #define macro constants and const-qualified variables. - * Initializes an LCD1602 display over I2C and prints constant values - * over UART in an infinite loop. - * - * Wiring: - * GPIO2 (SDA) -> LCD1602 PCF8574 SDA - * GPIO3 (SCL) -> LCD1602 PCF8574 SCL - * 3V3 -> LCD1602 VCC - * GND -> LCD1602 GND - */ - #include #include #include "pico/stdlib.h" #include "hardware/i2c.h" #include "lcd_1602.h" -/** @brief Macro constant for favorite number */ -#define FAV_NUM 42 -/** @brief I2C peripheral instance */ -#define I2C_PORT i2c1 -/** @brief GPIO pin for I2C SDA */ +#define FAV_NUM 42 + +#define I2C_PORT i2c1 #define I2C_SDA_PIN 2 -/** @brief GPIO pin for I2C SCL */ #define I2C_SCL_PIN 3 -/** @brief Const-qualified favorite number */ const int OTHER_FAV_NUM = 1337; -/** - * @brief Initialize I2C bus and LCD1602 display - * - * @details Configures I2C1 at 100kHz on GPIO2/3, initializes the - * LCD via PCF8574 at address 0x27, and writes two lines. - * - * @retval None - */ -static void init_i2c_and_lcd(void) { +int main(void) { + stdio_init_all(); + i2c_init(I2C_PORT, 100000); gpio_set_function(I2C_SDA_PIN, GPIO_FUNC_I2C); gpio_set_function(I2C_SCL_PIN, GPIO_FUNC_I2C); gpio_pull_up(I2C_SDA_PIN); gpio_pull_up(I2C_SCL_PIN); - lcd_i2c_init(I2C_PORT, 0x27, 4, 0x08); -} -/** - * @brief Write greeting text to the LCD display - * - * @details Sets cursor to line 0 and writes "Reverse", then sets - * cursor to line 1 and writes "Engineering". - * - * @retval None - */ -static void write_lcd_greeting(void) { + lcd_i2c_init(I2C_PORT, 0x27, 4, 0x08); + lcd_set_cursor(0, 0); lcd_puts("Reverse"); lcd_set_cursor(1, 0); lcd_puts("Engineering"); -} -int main(void) { - stdio_init_all(); - init_i2c_and_lcd(); - write_lcd_greeting(); while (true) { printf("FAV_NUM: %d\r\n", FAV_NUM); printf("OTHER_FAV_NUM: %d\r\n", OTHER_FAV_NUM); diff --git a/0x0017_constants/lcd_1602.c b/0x0017_constants/lcd_1602.c index 80054cc..7425cf1 100644 --- a/0x0017_constants/lcd_1602.c +++ b/0x0017_constants/lcd_1602.c @@ -31,37 +31,21 @@ #include #include -/** @brief I2C instance pointer for the LCD */ static i2c_inst_t *lcd_i2c = NULL; -/** @brief I2C address of the PCF8574 backpack */ static uint8_t lcd_addr = 0x27; -/** @brief Bit shift for 4-bit nibble position */ static int lcd_nibble_shift = 4; -/** @brief PCF8574 bit mask controlling the backlight */ static uint8_t lcd_backlight_mask = 0x08; -/** @brief PCF8574 bit mask for Register Select */ +/* PCF8574 -> LCD control pins */ #define PIN_RS 0x01 -/** @brief PCF8574 bit mask for Read/Write */ #define PIN_RW 0x02 -/** @brief PCF8574 bit mask for Enable */ #define PIN_EN 0x04 -/** - * @brief Write one raw byte to the PCF8574 expander over I2C - * - * @param data Output byte to send to the expander - */ static void pcf_write_byte(uint8_t data) { if (!lcd_i2c) return; i2c_write_blocking(lcd_i2c, lcd_addr, &data, 1, false); } -/** - * @brief Toggle EN to latch a nibble into the LCD controller - * - * @param data Current control/data bus byte (with RS and backlight already set) - */ static void pcf_pulse_enable(uint8_t data) { pcf_write_byte(data | PIN_EN); sleep_us(1); @@ -69,12 +53,6 @@ static void pcf_pulse_enable(uint8_t data) { sleep_us(50); } -/** - * @brief Write one 4-bit nibble to the LCD - * - * @param nibble Lower 4 bits to write - * @param mode 0 for command, non-zero for character data - */ static void lcd_write4(uint8_t nibble, uint8_t mode) { uint8_t data = (nibble & 0x0F) << lcd_nibble_shift; data |= mode ? PIN_RS : 0; @@ -82,37 +60,18 @@ static void lcd_write4(uint8_t nibble, uint8_t mode) { pcf_pulse_enable(data); } -/** - * @brief Send one full 8-bit command/data value as two nibbles - * - * @param value Byte to send to the LCD - * @param mode 0 for command, non-zero for character data - */ static void lcd_send(uint8_t value, uint8_t mode) { lcd_write4((value >> 4) & 0x0F, mode); lcd_write4(value & 0x0F, mode); } -/** - * @brief Store LCD driver configuration in module-level state - * - * @param i2c Pointer to the I2C instance - * @param pcf_addr 7-bit PCF8574 address - * @param nibble_shift Bit shift for 4-bit nibbles - * @param backlight_mask Backlight control bit mask - */ -static void lcd_store_config(i2c_inst_t *i2c, uint8_t pcf_addr, - int nibble_shift, uint8_t backlight_mask) { +void lcd_i2c_init(i2c_inst_t *i2c, uint8_t pcf_addr, int nibble_shift, uint8_t backlight_mask) { lcd_i2c = i2c; lcd_addr = pcf_addr; lcd_nibble_shift = nibble_shift; lcd_backlight_mask = backlight_mask; -} -/** - * @brief Execute the HD44780 4-bit mode power-on reset sequence - */ -static void lcd_hd44780_reset(void) { + // Follow init sequence for HD44780 in 4-bit mode lcd_write4(0x03, 0); sleep_ms(5); lcd_write4(0x03, 0); @@ -121,26 +80,19 @@ static void lcd_hd44780_reset(void) { sleep_us(150); lcd_write4(0x02, 0); sleep_us(150); -} -/** - * @brief Send post-reset configuration commands to the HD44780 - * - * Sets 4-bit mode with 2 display lines, turns the display on with - * cursor hidden, clears the screen, and selects left-to-right entry mode. - */ -static void lcd_hd44780_configure(void) { + // Function set: 4-bit, 2 lines lcd_send(0x28, 0); + + // Display on, cursor off lcd_send(0x0C, 0); + + // Clear lcd_send(0x01, 0); sleep_ms(2); - lcd_send(0x06, 0); -} -void lcd_i2c_init(i2c_inst_t *i2c, uint8_t pcf_addr, int nibble_shift, uint8_t backlight_mask) { - lcd_store_config(i2c, pcf_addr, nibble_shift, backlight_mask); - lcd_hd44780_reset(); - lcd_hd44780_configure(); + // Entry mode set + lcd_send(0x06, 0); } void lcd_clear(void) { @@ -150,11 +102,13 @@ void lcd_clear(void) { void lcd_set_cursor(int line, int position) { const uint8_t row_offsets[] = {0x00, 0x40}; + if (line > 1) line = 1; lcd_send(0x80 | (position + row_offsets[line]), 0); } void lcd_puts(const char *s) { - while (*s) + while (*s) { lcd_send((uint8_t)*s++, 1); + } } diff --git a/0x001a_operators/0x001a_operators.c b/0x001a_operators/0x001a_operators.c index 1eecc97..d9ddccf 100644 --- a/0x001a_operators/0x001a_operators.c +++ b/0x001a_operators/0x001a_operators.c @@ -1,126 +1,36 @@ -/** - * @file 0x001a_operators.c - * @brief Operators: demonstrate C operators with DHT11 temperature sensor - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Demonstrates arithmetic, increment, relational, logical, bitwise, and - * assignment operators in C. Also reads humidity and temperature from a - * DHT11 sensor on GPIO4. - * - * Wiring: - * GPIO4 -> DHT11 data pin (with 10k pull-up to 3V3) - * 3V3 -> DHT11 VCC - * GND -> DHT11 GND - */ - #include #include "pico/stdlib.h" #include "dht11.h" -/** - * @brief Print pre-computed operator results - * - * @details Prints all six operator demonstration values over UART. - * - * @param arith arithmetic operator result - * @param inc increment operator result - * @param rel relational operator result - * @param logic logical operator result - * @param bitw bitwise operator result - * @param assign assignment operator result - * @retval None - */ -static void print_operator_results(int arith, int inc, bool rel, - bool logic, int bitw, int assign) { - printf("arithmetic_operator: %d\r\n", arith); - printf("increment_operator: %d\r\n", inc); - printf("relational_operator: %d\r\n", rel); - printf("logical_operator: %d\r\n", logic); - printf("bitwise_operator: %d\r\n", bitw); - printf("assignment_operator: %d\r\n", assign); -} - -/** - * @brief Compute arithmetic and increment operator results - * - * @param arith pointer to store multiplication result - * @param incr pointer to store post-increment result - * @param x left operand - * @param y right operand - * @retval None - */ -static void compute_arithmetic_ops(int *arith, int *incr, int x, int y) { - *arith = (x * y); - *incr = x++; -} - -/** - * @brief Compute all operator values and print results - * - * @details Performs arithmetic, relational, logical, bitwise, - * and assignment operations, then prints each result. - * - * @retval None - */ -static void compute_operators(void) { - int x = 5, y = 10; - int arith, incr; - compute_arithmetic_ops(&arith, &incr, x, y); - bool rel = (x > y); - bool logic = (x > y) && (y > x); - int bits = (x << 1); - int assign = (x += 5); - print_operator_results(arith, incr, rel, logic, bits, assign); -} - -/** - * @brief Read and print DHT11 humidity and temperature - * - * @details Attempts a DHT11 read; on success prints humidity and - * temperature, on failure prints an error message. - * - * @retval None - */ -static void print_dht11_reading(void) { - float hum, temp; - if (dht11_read(&hum, &temp)) { - printf("Humidity: %.1f%%, Temperature: %.1f°C\r\n", hum, temp); - } else { - printf("DHT11 read failed\r\n"); - } -} - int main(void) { stdio_init_all(); + dht11_init(4); + + int x = 5; + int y = 10; + int arithmetic_operator = (x * y); + int increment_operator = x++; + bool relational_operator = (x > y); + bool logical_operator = (x > y) && (y > x); + int bitwise_operator = (x<<1); // x is now 6 because of x++ or 0b00000110 and (x<<1) is 0b00001100 or 12 + int assignment_operator = (x += 5); + while (true) { - compute_operators(); - print_dht11_reading(); + printf("arithmetic_operator: %d\r\n", arithmetic_operator); + printf("increment_operator: %d\r\n", increment_operator); + printf("relational_operator: %d\r\n", relational_operator); + printf("logical_operator: %d\r\n", logical_operator); + printf("bitwise_operator: %d\r\n", bitwise_operator); + printf("assignment_operator: %d\r\n", assignment_operator); + + float hum, temp; + if (dht11_read(&hum, &temp)) { + printf("Humidity: %.1f%%, Temperature: %.1f°C\r\n", hum, temp); + } else { + printf("DHT11 read failed\r\n"); + } + sleep_ms(2000); } } \ No newline at end of file diff --git a/0x001a_operators/dht11.c b/0x001a_operators/dht11.c index 28f147f..9a52ba8 100644 --- a/0x001a_operators/dht11.c +++ b/0x001a_operators/dht11.c @@ -31,97 +31,8 @@ #include "hardware/gpio.h" #include "pico/time.h" -/** @brief GPIO pin connected to the DHT11 sensor */ static uint dht_pin; -/** - * @brief Send the DHT11 start signal on the data pin - * - * Drives the pin LOW for 18 ms then HIGH for 40 us before switching - * the pin to input mode to listen for the sensor response. - */ -static void send_start_signal(void) { - gpio_set_dir(dht_pin, GPIO_OUT); - gpio_put(dht_pin, 0); - sleep_ms(18); - gpio_put(dht_pin, 1); - sleep_us(40); - gpio_set_dir(dht_pin, GPIO_IN); -} - -/** - * @brief Wait for the pin to leave a given logic level - * - * Spins until the pin no longer reads the specified level, returning - * false if a timeout of 10 000 iterations is exceeded. - * - * @param level Logic level to wait through (0 or 1) - * @return bool true once the level changed, false on timeout - */ -static bool wait_for_level(int level) { - uint32_t timeout = 10000; - while (gpio_get(dht_pin) == level) - if (--timeout == 0) return false; - return true; -} - -/** - * @brief Wait for the DHT11 response after the start signal - * - * The sensor pulls LOW then HIGH then LOW again; each transition - * is awaited with a timeout. - * - * @return bool true if the full response was received, false on timeout - */ -static bool wait_response(void) { - if (!wait_for_level(1)) return false; - if (!wait_for_level(0)) return false; - if (!wait_for_level(1)) return false; - return true; -} - -/** - * @brief Read a single bit from the DHT11 data stream - * - * Waits for the low-period to end, measures the high-period duration, - * and shifts the result into the appropriate byte of the data array. - * - * @param data 5-byte array accumulating the received bits - * @param i Bit index (0-39) - * @return bool true on success, false on timeout - */ -static bool read_bit(uint8_t *data, int i) { - if (!wait_for_level(0)) return false; - uint32_t start = time_us_32(); - if (!wait_for_level(1)) return false; - uint32_t duration = time_us_32() - start; - data[i / 8] <<= 1; - if (duration > 40) data[i / 8] |= 1; - return true; -} - -/** - * @brief Read all 40 data bits from the DHT11 - * - * @param data 5-byte array filled with the received data - * @return bool true if all 40 bits were read, false on timeout - */ -static bool read_40_bits(uint8_t *data) { - for (int i = 0; i < 40; i++) - if (!read_bit(data, i)) return false; - return true; -} - -/** - * @brief Verify the DHT11 checksum byte - * - * @param data 5-byte received data (bytes 0-3 plus checksum in byte 4) - * @return bool true if the checksum matches, false otherwise - */ -static bool validate_checksum(const uint8_t *data) { - return data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF); -} - void dht11_init(uint8_t pin) { dht_pin = pin; gpio_init(pin); @@ -130,10 +41,38 @@ void dht11_init(uint8_t pin) { bool dht11_read(float *humidity, float *temperature) { uint8_t data[5] = {0}; - send_start_signal(); - if (!wait_response()) return false; - if (!read_40_bits(data)) return false; - if (!validate_checksum(data)) return false; + + // Start signal + gpio_set_dir(dht_pin, GPIO_OUT); + gpio_put(dht_pin, 0); + sleep_ms(18); + gpio_put(dht_pin, 1); + sleep_us(40); + gpio_set_dir(dht_pin, GPIO_IN); + + // Wait for response + uint32_t timeout = 10000; + while (gpio_get(dht_pin) == 1) if (--timeout == 0) return false; + timeout = 10000; + while (gpio_get(dht_pin) == 0) if (--timeout == 0) return false; + timeout = 10000; + while (gpio_get(dht_pin) == 1) if (--timeout == 0) return false; + + // Read 40 bits + for (int i = 0; i < 40; i++) { + timeout = 10000; + while (gpio_get(dht_pin) == 0) if (--timeout == 0) return false; + uint32_t start = time_us_32(); + timeout = 10000; + while (gpio_get(dht_pin) == 1) if (--timeout == 0) return false; + uint32_t duration = time_us_32() - start; + data[i / 8] <<= 1; + if (duration > 40) data[i / 8] |= 1; + } + + // Check checksum + if (data[4] != ((data[0] + data[1] + data[2] + data[3]) & 0xFF)) return false; + *humidity = data[0] + data[1] * 0.1f; *temperature = data[2] + data[3] * 0.1f; return true; diff --git a/0x001d_static-conditionals/0x001d_static-conditionals.c b/0x001d_static-conditionals/0x001d_static-conditionals.c index 6db9a5e..8ad9328 100644 --- a/0x001d_static-conditionals/0x001d_static-conditionals.c +++ b/0x001d_static-conditionals/0x001d_static-conditionals.c @@ -1,106 +1,39 @@ -/** - * @file 0x001d_static-conditionals.c - * @brief Static conditionals: if/else and switch with servo sweep - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Demonstrates static (compile-time known) conditionals using if/else if/else - * and switch/case statements. Also sweeps a servo on GPIO6 between 0 and - * 180 degrees each iteration. - * - * Wiring: - * GPIO6 -> Servo signal wire (orange/white) - * 5V -> Servo VCC (red) - * GND -> Servo GND (brown/black) - */ - #include #include "pico/stdlib.h" #include "servo.h" -/** @brief GPIO pin number for the servo */ #define SERVO_GPIO 6 -/** - * @brief Print choice value using if/else if/else conditional - * - * @details Prints "1", "2", or "?" depending on the choice value. - * - * @param choice integer value to evaluate - * @retval None - */ -static void print_if_else(int choice) { - if (choice == 1) { - printf("1\r\n"); - } else if (choice == 2) { - printf("2\r\n"); - } else { - printf("?\r\n"); - } -} - -/** - * @brief Print choice value using switch/case conditional - * - * @details Prints "one", "two", or "??" depending on the choice value. - * - * @param choice integer value to evaluate - * @retval None - */ -static void print_switch(int choice) { - switch (choice) { - case 1: printf("one\r\n"); break; - case 2: printf("two\r\n"); break; - default: printf("??\r\n"); - } -} - -/** - * @brief Sweep servo between 0 and 180 degrees - * - * @details Sets the servo to 0 degrees, waits 500ms, then sets - * to 180 degrees and waits 500ms. - * - * @retval None - */ -static void sweep_servo(void) { - servo_set_angle(0.0f); - sleep_ms(500); - servo_set_angle(180.0f); - sleep_ms(500); -} - int main(void) { stdio_init_all(); + int choice = 1; + servo_init(SERVO_GPIO); + while (true) { - print_if_else(choice); - print_switch(choice); - sweep_servo(); + if (choice == 1) { + printf("1\r\n"); + } else if (choice == 2) { + printf("2\r\n"); + } else { + printf("?\r\n"); + } + + switch (choice) { + case 1: + printf("one\r\n"); + break; + case 2: + printf("two\r\n"); + break; + default: + printf("??\r\n"); + } + + servo_set_angle(0.0f); + sleep_ms(500); + servo_set_angle(180.0f); + sleep_ms(500); } } \ No newline at end of file diff --git a/0x001d_static-conditionals/servo.c b/0x001d_static-conditionals/servo.c index d0fefbd..ee48f0d 100644 --- a/0x001d_static-conditionals/servo.c +++ b/0x001d_static-conditionals/servo.c @@ -32,66 +32,46 @@ #include "hardware/pwm.h" #include "hardware/clocks.h" -/** @brief Default minimum pulse width in microseconds */ +// Default servo pulse range (SG90 typical) static const uint16_t SERVO_DEFAULT_MIN_US = 1000; -/** @brief Default maximum pulse width in microseconds */ static const uint16_t SERVO_DEFAULT_MAX_US = 2000; -/** @brief GPIO pin assigned to the servo */ +// internal state static uint8_t servo_pin = 0; -/** @brief PWM hardware slice for the servo pin */ static uint servo_slice = 0; -/** @brief PWM channel within the servo slice */ static uint servo_chan = 0; -/** @brief PWM counter wrap value for 50 Hz servo */ -static uint32_t servo_wrap = 20000 - 1; -/** @brief Servo PWM frequency in Hz */ +static uint32_t servo_wrap = 20000 - 1; // wrap to map microseconds for 50Hz static float servo_hz = 50.0f; -/** @brief Flag indicating servo has been initialized */ -static bool servo_initialized = false; -/** - * @brief Convert a pulse width in microseconds to a PWM counter level - * - * Uses the configured PWM wrap and servo frequency to map pulse time - * into the channel compare value expected by the PWM hardware. - * - * @param pulse_us Pulse width in microseconds - * @return uint32_t PWM level suitable for pwm_set_chan_level() - */ +// Convert microsecond pulse to PWM level based on wrap and frequency static uint32_t pulse_us_to_level(uint32_t pulse_us) { - const float period_us = 1000000.0f / servo_hz; + const float period_us = 1000000.0f / servo_hz; // 20000us float counts_per_us = (servo_wrap + 1) / period_us; return (uint32_t)(pulse_us * counts_per_us + 0.5f); } -/** - * @brief Build and apply the PWM slice configuration for 50 Hz servo - * - * Computes the clock divider from the system clock to achieve the - * target servo frequency with the chosen wrap value, then starts - * the PWM slice. - */ -static void apply_servo_config(void) { +void servo_init(uint8_t pin) { + servo_pin = pin; + + // Configure GPIO for PWM + gpio_set_function(servo_pin, GPIO_FUNC_PWM); + servo_slice = pwm_gpio_to_slice_num(servo_pin); + servo_chan = pwm_gpio_to_channel(servo_pin); + pwm_config config = pwm_get_default_config(); + + // Calculate clock divider to achieve 50 Hz with our chosen wrap const uint32_t sys_clock_hz = clock_get_hz(clk_sys); float clock_div = (float)sys_clock_hz / (servo_hz * (servo_wrap + 1)); + pwm_config_set_clkdiv(&config, clock_div); pwm_config_set_wrap(&config, servo_wrap); pwm_init(servo_slice, &config, true); } -void servo_init(uint8_t pin) { - servo_pin = pin; - gpio_set_function(servo_pin, GPIO_FUNC_PWM); - servo_slice = pwm_gpio_to_slice_num(servo_pin); - servo_chan = pwm_gpio_to_channel(servo_pin); - apply_servo_config(); - servo_initialized = true; -} - void servo_set_pulse_us(uint16_t pulse_us) { - if (!servo_initialized) return; + if (servo_pin == 0) return; // not initialized + // clamp to defaults if (pulse_us < SERVO_DEFAULT_MIN_US) pulse_us = SERVO_DEFAULT_MIN_US; if (pulse_us > SERVO_DEFAULT_MAX_US) pulse_us = SERVO_DEFAULT_MAX_US; uint32_t level = pulse_us_to_level(pulse_us); @@ -101,7 +81,9 @@ void servo_set_pulse_us(uint16_t pulse_us) { void servo_set_angle(float degrees) { if (degrees < 0.0f) degrees = 0.0f; if (degrees > 180.0f) degrees = 180.0f; + // linear map 0..180 -> min_us..max_us float ratio = degrees / 180.0f; uint16_t pulse = (uint16_t)(SERVO_DEFAULT_MIN_US + ratio * (SERVO_DEFAULT_MAX_US - SERVO_DEFAULT_MIN_US) + 0.5f); servo_set_pulse_us(pulse); -} \ No newline at end of file +} +# \ No newline at end of file diff --git a/0x0020_dynamic-conditionals/0x0020_dynamic-conditionals.c b/0x0020_dynamic-conditionals/0x0020_dynamic-conditionals.c index 028fcd4..1bef42c 100644 --- a/0x0020_dynamic-conditionals/0x0020_dynamic-conditionals.c +++ b/0x0020_dynamic-conditionals/0x0020_dynamic-conditionals.c @@ -1,111 +1,44 @@ -/** - * @file 0x0020_dynamic-conditionals.c - * @brief Dynamic conditionals: UART input drives if/else and switch with servo - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Demonstrates dynamic (runtime) conditionals using UART input via getchar(). - * Reads a character, evaluates it with if/else and switch/case, and controls - * a servo on GPIO6 based on the input ('1' or '2'). - * - * Wiring: - * GPIO6 -> Servo signal wire (orange/white) - * 5V -> Servo VCC (red) - * GND -> Servo GND (brown/black) - */ - #include #include "pico/stdlib.h" #include "servo.h" -/** @brief GPIO pin number for the servo */ #define SERVO_GPIO 6 -/** - * @brief Evaluate choice with if/else conditional and print result - * - * @details Compares against hex ASCII values 0x31 ('1') and 0x32 ('2'). - * - * @param choice character value received from UART - * @retval None - */ -static void eval_if_else(uint8_t choice) { - if (choice == 0x31) { - printf("1\r\n"); - } else if (choice == 0x32) { - printf("2\r\n"); - } else { - printf("??\r\n"); - } -} - -/** - * @brief Sweep servo from start angle to end angle with a pause - * - * @details Sets the servo to start, waits 500 ms, sets to end, - * waits 500 ms. - * - * @param label text to print before sweeping - * @param start starting angle in degrees - * @param end ending angle in degrees - * @retval None - */ -static void sweep_servo(const char *label, float start, float end) { - printf("%s\r\n", label); - servo_set_angle(start); - sleep_ms(500); - servo_set_angle(end); - sleep_ms(500); -} - -/** - * @brief Process choice with switch/case and drive servo accordingly - * - * @details On '1', sweeps servo 0->180; on '2', sweeps 180->0; - * otherwise prints unknown. - * - * @param choice character value received from UART - * @retval None - */ -static void process_servo_command(uint8_t choice) { - switch (choice) { - case '1': sweep_servo("one", 0.0f, 180.0f); break; - case '2': sweep_servo("two", 180.0f, 0.0f); break; - default: printf("??\r\n"); - } -} - int main(void) { stdio_init_all(); + uint8_t choice = 0; + servo_init(SERVO_GPIO); + while (true) { choice = getchar(); - eval_if_else(choice); - process_servo_command(choice); + + if (choice == 0x31) { + printf("1\r\n"); + } else if (choice == 0x32) { + printf("2\r\n"); + } else { + printf("??\r\n"); + } + + switch (choice) { + case '1': + printf("one\r\n"); + servo_set_angle(0.0f); + sleep_ms(500); + servo_set_angle(180.0f); + sleep_ms(500); + break; + case '2': + printf("two\r\n"); + servo_set_angle(180.0f); + sleep_ms(500); + servo_set_angle(0.0f); + sleep_ms(500); + break; + default: + printf("??\r\n"); + } } } diff --git a/0x0020_dynamic-conditionals/servo.c b/0x0020_dynamic-conditionals/servo.c index d0fefbd..ee48f0d 100644 --- a/0x0020_dynamic-conditionals/servo.c +++ b/0x0020_dynamic-conditionals/servo.c @@ -32,66 +32,46 @@ #include "hardware/pwm.h" #include "hardware/clocks.h" -/** @brief Default minimum pulse width in microseconds */ +// Default servo pulse range (SG90 typical) static const uint16_t SERVO_DEFAULT_MIN_US = 1000; -/** @brief Default maximum pulse width in microseconds */ static const uint16_t SERVO_DEFAULT_MAX_US = 2000; -/** @brief GPIO pin assigned to the servo */ +// internal state static uint8_t servo_pin = 0; -/** @brief PWM hardware slice for the servo pin */ static uint servo_slice = 0; -/** @brief PWM channel within the servo slice */ static uint servo_chan = 0; -/** @brief PWM counter wrap value for 50 Hz servo */ -static uint32_t servo_wrap = 20000 - 1; -/** @brief Servo PWM frequency in Hz */ +static uint32_t servo_wrap = 20000 - 1; // wrap to map microseconds for 50Hz static float servo_hz = 50.0f; -/** @brief Flag indicating servo has been initialized */ -static bool servo_initialized = false; -/** - * @brief Convert a pulse width in microseconds to a PWM counter level - * - * Uses the configured PWM wrap and servo frequency to map pulse time - * into the channel compare value expected by the PWM hardware. - * - * @param pulse_us Pulse width in microseconds - * @return uint32_t PWM level suitable for pwm_set_chan_level() - */ +// Convert microsecond pulse to PWM level based on wrap and frequency static uint32_t pulse_us_to_level(uint32_t pulse_us) { - const float period_us = 1000000.0f / servo_hz; + const float period_us = 1000000.0f / servo_hz; // 20000us float counts_per_us = (servo_wrap + 1) / period_us; return (uint32_t)(pulse_us * counts_per_us + 0.5f); } -/** - * @brief Build and apply the PWM slice configuration for 50 Hz servo - * - * Computes the clock divider from the system clock to achieve the - * target servo frequency with the chosen wrap value, then starts - * the PWM slice. - */ -static void apply_servo_config(void) { +void servo_init(uint8_t pin) { + servo_pin = pin; + + // Configure GPIO for PWM + gpio_set_function(servo_pin, GPIO_FUNC_PWM); + servo_slice = pwm_gpio_to_slice_num(servo_pin); + servo_chan = pwm_gpio_to_channel(servo_pin); + pwm_config config = pwm_get_default_config(); + + // Calculate clock divider to achieve 50 Hz with our chosen wrap const uint32_t sys_clock_hz = clock_get_hz(clk_sys); float clock_div = (float)sys_clock_hz / (servo_hz * (servo_wrap + 1)); + pwm_config_set_clkdiv(&config, clock_div); pwm_config_set_wrap(&config, servo_wrap); pwm_init(servo_slice, &config, true); } -void servo_init(uint8_t pin) { - servo_pin = pin; - gpio_set_function(servo_pin, GPIO_FUNC_PWM); - servo_slice = pwm_gpio_to_slice_num(servo_pin); - servo_chan = pwm_gpio_to_channel(servo_pin); - apply_servo_config(); - servo_initialized = true; -} - void servo_set_pulse_us(uint16_t pulse_us) { - if (!servo_initialized) return; + if (servo_pin == 0) return; // not initialized + // clamp to defaults if (pulse_us < SERVO_DEFAULT_MIN_US) pulse_us = SERVO_DEFAULT_MIN_US; if (pulse_us > SERVO_DEFAULT_MAX_US) pulse_us = SERVO_DEFAULT_MAX_US; uint32_t level = pulse_us_to_level(pulse_us); @@ -101,7 +81,9 @@ void servo_set_pulse_us(uint16_t pulse_us) { void servo_set_angle(float degrees) { if (degrees < 0.0f) degrees = 0.0f; if (degrees > 180.0f) degrees = 180.0f; + // linear map 0..180 -> min_us..max_us float ratio = degrees / 180.0f; uint16_t pulse = (uint16_t)(SERVO_DEFAULT_MIN_US + ratio * (SERVO_DEFAULT_MAX_US - SERVO_DEFAULT_MIN_US) + 0.5f); servo_set_pulse_us(pulse); -} \ No newline at end of file +} +# \ No newline at end of file diff --git a/0x0023_structures/0x0023_structures.c b/0x0023_structures/0x0023_structures.c index 657dc5f..fd802cc 100644 --- a/0x0023_structures/0x0023_structures.c +++ b/0x0023_structures/0x0023_structures.c @@ -1,50 +1,8 @@ -/** - * @file 0x0023_structures.c - * @brief Structures: IR remote controls LEDs via a struct-based controller - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Demonstrates C structures by defining a simple_led_ctrl_t to manage three - * LEDs. An IR receiver on GPIO5 decodes NEC commands and activates the - * corresponding LED (0x0C -> GPIO16, 0x18 -> GPIO17, 0x5E -> GPIO18). - * - * Wiring: - * GPIO5 -> IR receiver OUT - * GPIO16 -> LED1 anode (with current-limiting resistor to GND) - * GPIO17 -> LED2 anode (with current-limiting resistor to GND) - * GPIO18 -> LED3 anode (with current-limiting resistor to GND) - */ - #include #include #include "pico/stdlib.h" #include "ir.h" -/** @brief GPIO pin number for the IR receiver */ #define IR_PIN 5 typedef struct { @@ -56,89 +14,48 @@ typedef struct { bool led3_state; } simple_led_ctrl_t; -/** - * @brief Initialize all three LED GPIO pins as outputs - * - * @details Configures led1_pin, led2_pin, and led3_pin from the - * structure as GPIO outputs. - * - * @param leds pointer to the LED controller structure - * @retval None - */ -static void init_led_gpios(simple_led_ctrl_t *leds) { - gpio_init(leds->led1_pin); - gpio_set_dir(leds->led1_pin, GPIO_OUT); - gpio_init(leds->led2_pin); - gpio_set_dir(leds->led2_pin, GPIO_OUT); - gpio_init(leds->led3_pin); - gpio_set_dir(leds->led3_pin, GPIO_OUT); -} - -/** - * @brief Process an NEC IR key and update LED states - * - * @details Maps NEC command codes to LEDs: 0x0C -> LED1, 0x18 -> LED2, - * 0x5E -> LED3. Turns off all LEDs first, then activates the match. - * - * @param leds pointer to the LED controller structure - * @param key NEC command code from IR receiver - * @retval None - */ -static void process_ir_key(simple_led_ctrl_t *leds, int key) { - printf("NEC command: 0x%02X\n", key); - leds->led1_state = (key == 0x0C); - leds->led2_state = (key == 0x18); - leds->led3_state = (key == 0x5E); - gpio_put(leds->led1_pin, leds->led1_state); - gpio_put(leds->led2_pin, leds->led2_state); - gpio_put(leds->led3_pin, leds->led3_state); - sleep_ms(10); -} - -/** - * @brief Poll IR receiver and dispatch key to handler - * - * @details Reads one IR key; if valid, processes it; otherwise - * yields with a short sleep. - * - * @param leds pointer to the LED controller structure - * @retval None - */ -static void poll_ir(simple_led_ctrl_t *leds) { - int key = ir_getkey(); - if (key >= 0) { - process_ir_key(leds, key); - } else { - sleep_ms(1); - } -} - -/** - * @brief Build the default LED controller structure - * - * @details Initializes pins 16-18 with all LEDs off. - * - * @return simple_led_ctrl_t initialized structure - */ -static simple_led_ctrl_t make_default_leds(void) { - simple_led_ctrl_t leds = { - .led1_pin = 16, - .led2_pin = 17, - .led3_pin = 18, - .led1_state = false, - .led2_state = false, - .led3_state = false - }; - return leds; -} - int main(void) { stdio_init_all(); - simple_led_ctrl_t leds = make_default_leds(); - init_led_gpios(&leds); + + simple_led_ctrl_t leds = { + .led1_pin = 16, + .led2_pin = 17, + .led3_pin = 18, + .led1_state = false, + .led2_state = false, + .led3_state = false + }; + + gpio_init(leds.led1_pin); gpio_set_dir(leds.led1_pin, GPIO_OUT); + gpio_init(leds.led2_pin); gpio_set_dir(leds.led2_pin, GPIO_OUT); + gpio_init(leds.led3_pin); gpio_set_dir(leds.led3_pin, GPIO_OUT); + ir_init(IR_PIN); printf("IR receiver on GPIO %d ready\n", IR_PIN); + while (true) { - poll_ir(&leds); + int key = ir_getkey(); + if (key >= 0) { + printf("NEC command: 0x%02X\n", key); + + // turn all off first + leds.led1_state = false; + leds.led2_state = false; + leds.led3_state = false; + + // check NEC codes + if (key == 0x0C) leds.led1_state = true; // GPIO16 + if (key == 0x18) leds.led2_state = true; // GPIO17 + if (key == 0x5E) leds.led3_state = true; // GPIO18 + + // apply states + gpio_put(leds.led1_pin, leds.led1_state); + gpio_put(leds.led2_pin, leds.led2_state); + gpio_put(leds.led3_pin, leds.led3_state); + + sleep_ms(10); + } else { + sleep_ms(1); + } } } diff --git a/0x0023_structures/ir.c b/0x0023_structures/ir.c index 9d5b42a..b89bd4e 100644 --- a/0x0023_structures/ir.c +++ b/0x0023_structures/ir.c @@ -32,89 +32,19 @@ #include "pico/time.h" #include "hardware/gpio.h" -/** @brief GPIO pin connected to the IR receiver */ static unsigned int ir_pin = 0; -/** - * @brief Wait for a GPIO pin to reach a given logic level - * - * Spins until the pin matches the requested level or a microsecond timeout - * is exceeded. Returns the elapsed time in microseconds, or -1 on timeout. - * - * @param gpio GPIO pin to monitor - * @param level Desired logic level (true = HIGH, false = LOW) - * @param timeout_us Maximum wait in microseconds - * @return int64_t Elapsed microseconds, or -1 on timeout - */ +// Wait for 'gpio' to reach 'level' or timeout (microseconds). Return elapsed us or -1. static int64_t wait_for_level(unsigned int gpio, bool level, uint32_t timeout_us) { absolute_time_t start = get_absolute_time(); while (gpio_get(gpio) != level) { - if (absolute_time_diff_us(start, get_absolute_time()) > (int64_t)timeout_us) + if (absolute_time_diff_us(start, get_absolute_time()) > (int64_t)timeout_us) { return -1; + } } return absolute_time_diff_us(start, get_absolute_time()); } -/** - * @brief Wait for the NEC 9 ms leader pulse and 4.5 ms space - * - * @return bool true if a valid leader was detected, false on timeout - */ -static bool wait_leader(void) { - if (wait_for_level(ir_pin, 0, 150000) < 0) return false; - int64_t t = wait_for_level(ir_pin, 1, 12000); - if (t < 8000 || t > 10000) return false; - t = wait_for_level(ir_pin, 0, 7000); - if (t < 3500 || t > 5000) return false; - return true; -} - -/** - * @brief Read a single NEC-encoded bit from the IR receiver - * - * Measures the mark/space timing and shifts the result into the - * appropriate byte of the data array. - * - * @param data 4-byte array accumulating received bits - * @param i Bit index (0-31) - * @return bool true on success, false on timeout or protocol error - */ -static bool read_nec_bit(uint8_t *data, int i) { - if (wait_for_level(ir_pin, 1, 1000) < 0) return false; - int64_t t = wait_for_level(ir_pin, 0, 2500); - if (t < 200) return false; - int byte_idx = i / 8; - int bit_idx = i % 8; - if (t > 1200) data[byte_idx] |= (1 << bit_idx); - return true; -} - -/** - * @brief Read all 32 data bits of an NEC frame - * - * @param data 4-byte array filled with the received address and command - * @return bool true if all 32 bits were read, false on timeout - */ -static bool read_32_bits(uint8_t *data) { - for (int i = 0; i < 32; ++i) - if (!read_nec_bit(data, i)) return false; - return true; -} - -/** - * @brief Validate an NEC frame and extract the command byte - * - * Checks that the address and command pairs are bitwise-inverted. - * - * @param data 4-byte NEC frame (addr, ~addr, cmd, ~cmd) - * @return int Command byte (0-255) on success, -1 on validation failure - */ -static int validate_nec_frame(const uint8_t *data) { - if ((uint8_t)(data[0] + data[1]) == 0xFF && (uint8_t)(data[2] + data[3]) == 0xFF) - return data[2]; - return -1; -} - void ir_init(uint8_t pin) { ir_pin = pin; gpio_init(pin); @@ -123,8 +53,28 @@ void ir_init(uint8_t pin) { } int ir_getkey(void) { - if (!wait_leader()) return -1; + // leader low (~9 ms) + if (wait_for_level(ir_pin, 0, 150000) < 0) return -1; + + int64_t t = wait_for_level(ir_pin, 1, 12000); + if (t < 8000 || t > 10000) return -1; + + t = wait_for_level(ir_pin, 0, 7000); + if (t < 3500 || t > 5000) return -1; + uint8_t data[4] = {0, 0, 0, 0}; - if (!read_32_bits(data)) return -1; - return validate_nec_frame(data); + for (int i = 0; i < 32; ++i) { + if (wait_for_level(ir_pin, 1, 1000) < 0) return -1; + t = wait_for_level(ir_pin, 0, 2500); + if (t < 200) return -1; + int byte_idx = i / 8; + int bit_idx = i % 8; + if (t > 1200) data[byte_idx] |= (1 << bit_idx); // logical '1' + } + + // Validate address/data inverted pairs + if ((uint8_t)(data[0] + data[1]) == 0xFF && (uint8_t)(data[2] + data[3]) == 0xFF) { + return data[2]; + } + return -1; } diff --git a/0x0026_functions/0x0026_functions.c b/0x0026_functions/0x0026_functions.c index 210c7cc..518f5c0 100644 --- a/0x0026_functions/0x0026_functions.c +++ b/0x0026_functions/0x0026_functions.c @@ -1,50 +1,8 @@ -/** - * @file 0x0026_functions.c - * @brief Functions: IR remote controls LEDs with helper function decomposition - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Demonstrates function decomposition by breaking IR-controlled LED logic - * into small, focused helper functions. An IR receiver on GPIO5 decodes - * NEC commands and activates the corresponding LED with a blink effect. - * - * Wiring: - * GPIO5 -> IR receiver OUT - * GPIO16 -> LED1 anode (with current-limiting resistor to GND) - * GPIO17 -> LED2 anode (with current-limiting resistor to GND) - * GPIO18 -> LED3 anode (with current-limiting resistor to GND) - */ - #include #include #include "pico/stdlib.h" #include "ir.h" -/** @brief GPIO pin number for the IR receiver */ #define IR_PIN 5 typedef struct { @@ -59,13 +17,13 @@ typedef struct { /** * @brief Map NEC IR command code to LED number * - * @details Translates a received NEC IR command code to a logical - * LED number. Supports three button mappings. + * Translates a received NEC IR command code to a logical LED number. + * Supports three button mappings for controlling individual LEDs. * * @param ir_command NEC command code from IR receiver - * @retval 1-3 for matched LED, 0 if no match + * @return int LED number (1-3) or 0 if no match */ -static int ir_to_led_number(int ir_command) { +int ir_to_led_number(int ir_command) { if (ir_command == 0x0C) return 1; if (ir_command == 0x18) return 2; if (ir_command == 0x5E) return 3; @@ -75,14 +33,14 @@ static int ir_to_led_number(int ir_command) { /** * @brief Get GPIO pin number for a given LED number * - * @details Retrieves the GPIO pin associated with a logical LED - * number from the LED controller structure. + * Retrieves the GPIO pin associated with a logical LED number + * from the LED controller structure. * - * @param leds pointer to LED controller structure + * @param leds Pointer to LED controller structure * @param led_num LED number (1-3) - * @retval GPIO pin number or 0 if invalid + * @return uint8_t GPIO pin number or 0 if invalid */ -static uint8_t get_led_pin(simple_led_ctrl_t *leds, int led_num) { +uint8_t get_led_pin(simple_led_ctrl_t *leds, int led_num) { if (led_num == 1) return leds->led1_pin; if (led_num == 2) return leds->led2_pin; if (led_num == 3) return leds->led3_pin; @@ -92,12 +50,11 @@ static uint8_t get_led_pin(simple_led_ctrl_t *leds, int led_num) { /** * @brief Turn off all LEDs in the controller * - * @details Sets all three LED GPIO outputs to low. + * Sets all three LED GPIO outputs to low, turning off all LEDs. * - * @param leds pointer to LED controller structure - * @retval None + * @param leds Pointer to LED controller structure */ -static void leds_all_off(simple_led_ctrl_t *leds) { +void leds_all_off(simple_led_ctrl_t *leds) { gpio_put(leds->led1_pin, false); gpio_put(leds->led2_pin, false); gpio_put(leds->led3_pin, false); @@ -106,15 +63,14 @@ static void leds_all_off(simple_led_ctrl_t *leds) { /** * @brief Blink an LED pin a specified number of times * - * @details Toggles the specified GPIO pin on and off for the given - * count, with configurable delay between transitions. + * Toggles the specified GPIO pin on and off for the given count, + * with configurable delay between transitions. * - * @param pin GPIO pin number to blink - * @param count number of blink cycles - * @param delay_ms delay in milliseconds for on/off periods - * @retval None + * @param pin GPIO pin number to blink + * @param count Number of blink cycles + * @param delay_ms Delay in milliseconds for on/off periods */ -static void blink_led(uint8_t pin, uint8_t count, uint32_t delay_ms) { +void blink_led(uint8_t pin, uint8_t count, uint32_t delay_ms) { for (uint8_t i = 0; i < count; i++) { gpio_put(pin, true); sleep_ms(delay_ms); @@ -126,15 +82,15 @@ static void blink_led(uint8_t pin, uint8_t count, uint32_t delay_ms) { /** * @brief Process IR command and activate corresponding LED * - * @details Turns off all LEDs, maps the command to an LED number, - * blinks it, then holds it steady. + * Handles incoming IR commands by turning off all LEDs, mapping the + * command to an LED, blinking it, then holding it steady. * - * @param ir_command NEC command code from IR receiver - * @param leds pointer to LED controller structure - * @param blink_count number of blinks before steady state - * @retval LED number activated (1-3), 0 if none, -1 if invalid + * @param ir_command NEC command code from IR receiver + * @param leds Pointer to LED controller structure + * @param blink_count Number of blinks before steady state + * @return int LED number activated (1-3), 0 if none, -1 if invalid */ -static int process_ir_led_command(int ir_command, simple_led_ctrl_t *leds, uint8_t blink_count) { +int process_ir_led_command(int ir_command, simple_led_ctrl_t *leds, uint8_t blink_count) { if (!leds || ir_command < 0) return -1; leds_all_off(leds); int led_num = ir_to_led_number(ir_command); @@ -145,93 +101,49 @@ static int process_ir_led_command(int ir_command, simple_led_ctrl_t *leds, uint8 return led_num; } -/** - * @brief Initialize all three LED GPIO pins as outputs - * - * @details Configures led1_pin, led2_pin, and led3_pin from the - * structure as GPIO outputs. - * - * @param leds pointer to the LED controller structure - * @retval None - */ -static void init_led_gpios(simple_led_ctrl_t *leds) { - gpio_init(leds->led1_pin); - gpio_set_dir(leds->led1_pin, GPIO_OUT); - gpio_init(leds->led2_pin); - gpio_set_dir(leds->led2_pin, GPIO_OUT); - gpio_init(leds->led3_pin); - gpio_set_dir(leds->led3_pin, GPIO_OUT); -} - -/** - * @brief Poll IR and handle a single received key - * - * @details Reads an IR key, processes the command with 3 blinks, - * and prints the result. - * - * @param leds pointer to the LED controller structure - * @retval None - */ -/** - * @brief Handle a valid IR key press - * - * @details Prints the NEC command, processes it with 3 blinks, - * and reports the activated LED. - * - * @param leds pointer to the LED controller structure - * @param key NEC command code - * @retval None - */ -static void handle_ir_key(simple_led_ctrl_t *leds, int key) { - printf("NEC command: 0x%02X\n", key); - int activated_led = process_ir_led_command(key, leds, 3); - if (activated_led > 0) { - printf("LED %d activated on GPIO %d\n", activated_led, - get_led_pin(leds, activated_led)); - } - sleep_ms(10); -} - -/** - * @brief Poll IR and handle a single received key - * - * @details Reads an IR key; if valid dispatches to handler, - * otherwise yields with a short sleep. - * - * @param leds pointer to the LED controller structure - * @retval None - */ -static void poll_and_handle_ir(simple_led_ctrl_t *leds) { - int key = ir_getkey(); - if (key >= 0) { - handle_ir_key(leds, key); - } else { - sleep_ms(1); - } -} - -/** - * @brief Build the default LED controller structure - * - * @details Initializes pins 16-18 with all LEDs off. - * - * @return simple_led_ctrl_t initialized structure - */ -static simple_led_ctrl_t make_default_leds(void) { - simple_led_ctrl_t leds = { - .led1_pin = 16, .led2_pin = 17, .led3_pin = 18, - .led1_state = false, .led2_state = false, .led3_state = false - }; - return leds; -} - int main(void) { stdio_init_all(); - simple_led_ctrl_t leds = make_default_leds(); - init_led_gpios(&leds); + + simple_led_ctrl_t leds = { + .led1_pin = 16, + .led2_pin = 17, + .led3_pin = 18, + .led1_state = false, + .led2_state = false, + .led3_state = false + }; + + // Initialize LED GPIOs + gpio_init(leds.led1_pin); gpio_set_dir(leds.led1_pin, GPIO_OUT); + gpio_init(leds.led2_pin); gpio_set_dir(leds.led2_pin, GPIO_OUT); + gpio_init(leds.led3_pin); gpio_set_dir(leds.led3_pin, GPIO_OUT); + + // Initialize IR receiver ir_init(IR_PIN); printf("IR receiver on GPIO %d ready\n", IR_PIN); + printf("Press remote buttons to control LEDs with blink effects!\n"); + while (true) { - poll_and_handle_ir(&leds); + int key = ir_getkey(); + if (key >= 0) { + printf("NEC command: 0x%02X\n", key); + + // Process the IR command with 3 blinks before steady state + int activated_led = process_ir_led_command(key, &leds, 3); + + if (activated_led > 0) { + printf("LED %d activated on GPIO %d\n", activated_led, + (activated_led == 1) ? leds.led1_pin : + (activated_led == 2) ? leds.led2_pin : leds.led3_pin); + } else if (activated_led == 0) { + printf("No LED matched or chase effect played\n"); + } else { + printf("Invalid command or null pointer\n"); + } + + sleep_ms(10); + } else { + sleep_ms(1); + } } } diff --git a/0x0026_functions/ir.c b/0x0026_functions/ir.c index 9d5b42a..b89bd4e 100644 --- a/0x0026_functions/ir.c +++ b/0x0026_functions/ir.c @@ -32,89 +32,19 @@ #include "pico/time.h" #include "hardware/gpio.h" -/** @brief GPIO pin connected to the IR receiver */ static unsigned int ir_pin = 0; -/** - * @brief Wait for a GPIO pin to reach a given logic level - * - * Spins until the pin matches the requested level or a microsecond timeout - * is exceeded. Returns the elapsed time in microseconds, or -1 on timeout. - * - * @param gpio GPIO pin to monitor - * @param level Desired logic level (true = HIGH, false = LOW) - * @param timeout_us Maximum wait in microseconds - * @return int64_t Elapsed microseconds, or -1 on timeout - */ +// Wait for 'gpio' to reach 'level' or timeout (microseconds). Return elapsed us or -1. static int64_t wait_for_level(unsigned int gpio, bool level, uint32_t timeout_us) { absolute_time_t start = get_absolute_time(); while (gpio_get(gpio) != level) { - if (absolute_time_diff_us(start, get_absolute_time()) > (int64_t)timeout_us) + if (absolute_time_diff_us(start, get_absolute_time()) > (int64_t)timeout_us) { return -1; + } } return absolute_time_diff_us(start, get_absolute_time()); } -/** - * @brief Wait for the NEC 9 ms leader pulse and 4.5 ms space - * - * @return bool true if a valid leader was detected, false on timeout - */ -static bool wait_leader(void) { - if (wait_for_level(ir_pin, 0, 150000) < 0) return false; - int64_t t = wait_for_level(ir_pin, 1, 12000); - if (t < 8000 || t > 10000) return false; - t = wait_for_level(ir_pin, 0, 7000); - if (t < 3500 || t > 5000) return false; - return true; -} - -/** - * @brief Read a single NEC-encoded bit from the IR receiver - * - * Measures the mark/space timing and shifts the result into the - * appropriate byte of the data array. - * - * @param data 4-byte array accumulating received bits - * @param i Bit index (0-31) - * @return bool true on success, false on timeout or protocol error - */ -static bool read_nec_bit(uint8_t *data, int i) { - if (wait_for_level(ir_pin, 1, 1000) < 0) return false; - int64_t t = wait_for_level(ir_pin, 0, 2500); - if (t < 200) return false; - int byte_idx = i / 8; - int bit_idx = i % 8; - if (t > 1200) data[byte_idx] |= (1 << bit_idx); - return true; -} - -/** - * @brief Read all 32 data bits of an NEC frame - * - * @param data 4-byte array filled with the received address and command - * @return bool true if all 32 bits were read, false on timeout - */ -static bool read_32_bits(uint8_t *data) { - for (int i = 0; i < 32; ++i) - if (!read_nec_bit(data, i)) return false; - return true; -} - -/** - * @brief Validate an NEC frame and extract the command byte - * - * Checks that the address and command pairs are bitwise-inverted. - * - * @param data 4-byte NEC frame (addr, ~addr, cmd, ~cmd) - * @return int Command byte (0-255) on success, -1 on validation failure - */ -static int validate_nec_frame(const uint8_t *data) { - if ((uint8_t)(data[0] + data[1]) == 0xFF && (uint8_t)(data[2] + data[3]) == 0xFF) - return data[2]; - return -1; -} - void ir_init(uint8_t pin) { ir_pin = pin; gpio_init(pin); @@ -123,8 +53,28 @@ void ir_init(uint8_t pin) { } int ir_getkey(void) { - if (!wait_leader()) return -1; + // leader low (~9 ms) + if (wait_for_level(ir_pin, 0, 150000) < 0) return -1; + + int64_t t = wait_for_level(ir_pin, 1, 12000); + if (t < 8000 || t > 10000) return -1; + + t = wait_for_level(ir_pin, 0, 7000); + if (t < 3500 || t > 5000) return -1; + uint8_t data[4] = {0, 0, 0, 0}; - if (!read_32_bits(data)) return -1; - return validate_nec_frame(data); + for (int i = 0; i < 32; ++i) { + if (wait_for_level(ir_pin, 1, 1000) < 0) return -1; + t = wait_for_level(ir_pin, 0, 2500); + if (t < 200) return -1; + int byte_idx = i / 8; + int bit_idx = i % 8; + if (t > 1200) data[byte_idx] |= (1 << bit_idx); // logical '1' + } + + // Validate address/data inverted pairs + if ((uint8_t)(data[0] + data[1]) == 0xFF && (uint8_t)(data[2] + data[3]) == 0xFF) { + return data[2]; + } + return -1; } diff --git a/WEEK01/0x0001_hello-world/0x0001_hello-world.c b/WEEK01/0x0001_hello-world/0x0001_hello-world.c index 7f7b062..096aba7 100644 --- a/WEEK01/0x0001_hello-world/0x0001_hello-world.c +++ b/WEEK01/0x0001_hello-world/0x0001_hello-world.c @@ -1,46 +1,9 @@ -/** - * @file 0x0001_hello-world.c - * @brief Hello World: print a greeting over UART in an infinite loop - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Demonstrates the minimal "hello, world" program on the Raspberry Pi Pico 2. - * Initializes stdio over UART and prints a greeting in an infinite loop. - * - * Wiring: - * No external wiring required (USB serial). - */ - #include #include "pico/stdlib.h" int main(void) { stdio_init_all(); - while (true) { + + while (true) printf("hello, world\r\n"); - } } diff --git a/WEEK02/0x0001_hello-world/0x0001_hello-world.c b/WEEK02/0x0001_hello-world/0x0001_hello-world.c index 7f7b062..096aba7 100644 --- a/WEEK02/0x0001_hello-world/0x0001_hello-world.c +++ b/WEEK02/0x0001_hello-world/0x0001_hello-world.c @@ -1,46 +1,9 @@ -/** - * @file 0x0001_hello-world.c - * @brief Hello World: print a greeting over UART in an infinite loop - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Demonstrates the minimal "hello, world" program on the Raspberry Pi Pico 2. - * Initializes stdio over UART and prints a greeting in an infinite loop. - * - * Wiring: - * No external wiring required (USB serial). - */ - #include #include "pico/stdlib.h" int main(void) { stdio_init_all(); - while (true) { + + while (true) printf("hello, world\r\n"); - } } diff --git a/WEEK03/0x0001_hello-world/0x0001_hello-world.c b/WEEK03/0x0001_hello-world/0x0001_hello-world.c index 7f7b062..096aba7 100644 --- a/WEEK03/0x0001_hello-world/0x0001_hello-world.c +++ b/WEEK03/0x0001_hello-world/0x0001_hello-world.c @@ -1,46 +1,9 @@ -/** - * @file 0x0001_hello-world.c - * @brief Hello World: print a greeting over UART in an infinite loop - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Demonstrates the minimal "hello, world" program on the Raspberry Pi Pico 2. - * Initializes stdio over UART and prints a greeting in an infinite loop. - * - * Wiring: - * No external wiring required (USB serial). - */ - #include #include "pico/stdlib.h" int main(void) { stdio_init_all(); - while (true) { + + while (true) printf("hello, world\r\n"); - } } diff --git a/WEEK04/0x0005_intro-to-variables/0x0005_intro-to-variables.c b/WEEK04/0x0005_intro-to-variables/0x0005_intro-to-variables.c index 29f6b2d..7b2b3ae 100644 --- a/WEEK04/0x0005_intro-to-variables/0x0005_intro-to-variables.c +++ b/WEEK04/0x0005_intro-to-variables/0x0005_intro-to-variables.c @@ -1,48 +1,13 @@ -/** - * @file 0x0005_intro-to-variables.c - * @brief Introduction to variables: declare, assign, and print a uint8_t - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Demonstrates declaring, initializing, and reassigning a uint8_t variable. - * Prints the variable value over UART in an infinite loop. - * - * Wiring: - * No external wiring required (USB serial). - */ - #include #include "pico/stdlib.h" int main(void) { uint8_t age = 42; + age = 43; + stdio_init_all(); - while (true) { + + while (true) printf("age: %d\r\n", age); - } } diff --git a/WEEK04/0x0008_uninitialized-variables-a/0x0008_uninitialized-variables-a.c b/WEEK04/0x0008_uninitialized-variables-a/0x0008_uninitialized-variables-a.c index 9d2ddb3..656a992 100644 --- a/WEEK04/0x0008_uninitialized-variables-a/0x0008_uninitialized-variables-a.c +++ b/WEEK04/0x0008_uninitialized-variables-a/0x0008_uninitialized-variables-a.c @@ -1,52 +1,17 @@ -/** - * @file 0x0008_uninitialized-variables-a.c - * @brief Blink LED using SDK gpio functions (no UART) - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Blinks an LED on GPIO16 using the standard Pico SDK gpio_init / gpio_put - * functions. No UART output; pure GPIO blink demonstration. - * - * Wiring: - * GPIO16 -> LED anode (with current-limiting resistor to GND) - */ - #include #include "pico/stdlib.h" -/** @brief GPIO pin number for the LED */ -#define LED_PIN 16 +#define LED_PIN 16 -int main(void) { +int main(void) +{ gpio_init(LED_PIN); gpio_set_dir(LED_PIN, GPIO_OUT); + while (true) { gpio_put(LED_PIN, 1); sleep_ms(500); + gpio_put(LED_PIN, 0); sleep_ms(500); } diff --git a/WEEK04/0x0008_uninitialized-variables-b/0x0008_uninitialized-variables-b.c b/WEEK04/0x0008_uninitialized-variables-b/0x0008_uninitialized-variables-b.c index b42c544..365d7eb 100644 --- a/WEEK04/0x0008_uninitialized-variables-b/0x0008_uninitialized-variables-b.c +++ b/WEEK04/0x0008_uninitialized-variables-b/0x0008_uninitialized-variables-b.c @@ -1,80 +1,27 @@ -/** - * @file 0x0008_uninitialized-variables-b.c - * @brief Blink LED using gpioc coprocessor bit-level functions - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Blinks an LED on GPIO16 using the RP2350 gpioc coprocessor bit-level - * functions (gpioc_bit_oe_put / gpioc_bit_out_put) instead of the standard - * gpio_init / gpio_put SDK calls. - * - * Wiring: - * GPIO16 -> LED anode (with current-limiting resistor to GND) - */ - #include #include "pico/stdlib.h" -/** @brief GPIO pin number for the LED */ -#define LED_PIN 16 +#define LED_PIN 16 -/** - * @brief Initialize GPIO16 for output using coprocessor bit functions - * - * @details Configures the pad for SIO, sets direction to input first, - * clears the output, selects SIO function, then enables output. - * - * @retval None - */ -static void gpio_coprocessor_init(void) { +int main(void) +{ + // gpio_init(LED_PIN); gpio_set_dir(LED_PIN, GPIO_IN); gpio_put(LED_PIN, 0); gpio_set_function(LED_PIN, GPIO_FUNC_SIO); + + // gpio_set_dir(LED_PIN, GPIO_OUT); gpioc_bit_oe_put(LED_PIN, GPIO_OUT); -} -/** - * @brief Blink LED using coprocessor bit output functions - * - * @details Toggles the LED on and off with 500ms delays using - * gpioc_bit_out_put and sleep_us. - * - * @retval None - */ -static void blink_cycle(void) { - gpioc_bit_out_put(LED_PIN, 1); - sleep_us(500 * 1000ull); - gpioc_bit_out_put(LED_PIN, 0); - sleep_us(500 * 1000ull); -} - -int main(void) { - gpio_coprocessor_init(); while (true) { - blink_cycle(); + // gpio_put(LED_PIN, 1); + gpioc_bit_out_put(LED_PIN, 1); + // sleep_ms(500); + sleep_us(500 * 1000ull); + + // gpio_put(LED_PIN, 0); + gpioc_bit_out_put(LED_PIN, 0); + // sleep_ms(500); + sleep_us(500 * 1000ull); } } diff --git a/WEEK04/0x0008_uninitialized-variables-c/0x0008_uninitialized-variables-c.c b/WEEK04/0x0008_uninitialized-variables-c/0x0008_uninitialized-variables-c.c index 40771de..5136c35 100644 --- a/WEEK04/0x0008_uninitialized-variables-c/0x0008_uninitialized-variables-c.c +++ b/WEEK04/0x0008_uninitialized-variables-c/0x0008_uninitialized-variables-c.c @@ -1,85 +1,35 @@ -/** - * @file 0x0008_uninitialized-variables-c.c - * @brief Blink LED using direct register-level pad and IO bank configuration - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Blinks an LED on GPIO16 using direct register writes to PADS_BANK0 and - * IO_BANK0 for pad configuration, plus gpioc coprocessor bit-level functions - * for output enable and data. Demonstrates the register-level equivalent of - * gpio_init / gpio_set_function. - * - * Wiring: - * GPIO16 -> LED anode (with current-limiting resistor to GND) - */ - #include #include "pico/stdlib.h" -/** @brief GPIO pin number for the LED */ -#define LED_PIN 16 +#define LED_PIN 16 -/** - * @brief Configure pad and IO bank registers for GPIO16 as SIO output - * - * @details Sets PADS_BANK0 IE/OD bits, assigns FUNCSEL to SIO in IO_BANK0, - * clears the ISO bit, and enables output via the coprocessor. - * - * @retval None - */ -static void configure_pad_and_iobank(void) { +int main(void) +{ + // gpio_init(LED_PIN); + /// gpio_set_dir(LED_PIN, GPIO_IN); gpioc_bit_oe_put(LED_PIN, GPIO_OUT); + /// gpio_put(LED_PIN, 0); gpioc_bit_out_put(LED_PIN, 0); + /// gpio_set_function(LED_PIN, GPIO_FUNC_SIO); hw_write_masked(&pads_bank0_hw->io[LED_PIN], PADS_BANK0_GPIO0_IE_BITS, - PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS); + PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS + ); io_bank0_hw->io[LED_PIN].ctrl = GPIO_FUNC_SIO << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB; hw_clear_bits(&pads_bank0_hw->io[LED_PIN], PADS_BANK0_GPIO0_ISO_BITS); + + // gpio_set_dir(LED_PIN, GPIO_OUT); gpioc_bit_oe_put(LED_PIN, GPIO_OUT); -} -/** - * @brief Blink LED using coprocessor bit output functions - * - * @details Toggles the LED on and off with 500ms delays using - * gpioc_bit_out_put and sleep_us. - * - * @retval None - */ -static void blink_cycle(void) { - gpioc_bit_out_put(LED_PIN, 1); - sleep_us(500 * 1000ull); - gpioc_bit_out_put(LED_PIN, 0); - sleep_us(500 * 1000ull); -} - -int main(void) { - configure_pad_and_iobank(); while (true) { - blink_cycle(); + // gpio_put(LED_PIN, 1); + gpioc_bit_out_put(LED_PIN, 1); + // sleep_ms(500); + sleep_us(500 * 1000ull); + + // gpio_put(LED_PIN, 0); + gpioc_bit_out_put(LED_PIN, 0); + // sleep_ms(500); + sleep_us(500 * 1000ull); } } diff --git a/WEEK04/0x0008_uninitialized-variables-d/0x0008_uninitialized-variables-d.c b/WEEK04/0x0008_uninitialized-variables-d/0x0008_uninitialized-variables-d.c index b834115..457ed9a 100644 --- a/WEEK04/0x0008_uninitialized-variables-d/0x0008_uninitialized-variables-d.c +++ b/WEEK04/0x0008_uninitialized-variables-d/0x0008_uninitialized-variables-d.c @@ -1,70 +1,23 @@ -/** - * @file 0x0008_uninitialized-variables-d.c - * @brief Blink LED using pico_default_asm_volatile coprocessor instructions - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Blinks an LED on GPIO16 using pico_default_asm_volatile to emit mcrr - * coprocessor instructions for GPIO output enable and data, plus inline - * assembly for pad configuration (hw_write_masked, IO_BANK0 FUNCSEL, - * hw_clear_bits equivalents). - * - * Wiring: - * GPIO16 -> LED anode (with current-limiting resistor to GND) - */ - #include #include "pico/stdlib.h" -/** @brief GPIO pin number for the LED */ -#define LED_PIN 16 +#define LED_PIN 16 -/** - * @brief Enable output and set initial coprocessor OE/OUT via mcrr - * - * @details Issues two mcrr p0 instructions: one to enable output direction, - * one to set the initial output state. - * - * @retval None - */ -static void asm_set_oe_and_out(void) { +int main(void) +{ + // gpio_init(LED_PIN); + /// gpio_set_dir(LED_PIN, GPIO_IN); + //// gpioc_bit_oe_put(LED_PIN, GPIO_OUT); pico_default_asm_volatile ("mcrr p0, #4, %0, %1, c4" : : "r" (LED_PIN), "r" (GPIO_OUT)); + /// gpio_put(LED_PIN, 0); + //// gpioc_bit_out_put(LED_PIN, 0); pico_default_asm_volatile ("mcrr p0, #4, %0, %1, c4" : : "r" (LED_PIN), "r" (GPIO_OUT)); -} - -/** - * @brief Configure PADS_BANK0 IE/OD bits via inline assembly hw_xor_bits - * - * @details Performs a read-modify-write on the pad register to set IE - * and clear OD, replicating hw_write_masked behavior. - * - * @retval None - */ -static void asm_configure_pad(void) { + /// gpio_set_function(LED_PIN, GPIO_FUNC_SIO); + //// hw_write_masked(&pads_bank0_hw->io[LED_PIN], + //// PADS_BANK0_GPIO0_IE_BITS, + //// PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS + //// ); + //// hw_xor_bits(addr, (*addr ^ values) & write_mask); pico_default_asm_volatile ( "ldr r2, [%0]\n" // load current pad register "eor r2, r2, %1\n" // xor with IE bit @@ -77,17 +30,8 @@ static void asm_configure_pad(void) { "r" (PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS) : "r2", "memory" ); -} -/** - * @brief Set IO_BANK0 FUNCSEL to SIO via inline assembly store - * - * @details Writes the SIO function select value directly to the - * IO_BANK0 GPIO control register. - * - * @retval None - */ -static void asm_set_funcsel(void) { + /// io_bank0_hw->io[LED_PIN].ctrl = GPIO_FUNC_SIO << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB; pico_default_asm_volatile ( "str %1, [%0]\n" : @@ -95,50 +39,32 @@ static void asm_set_funcsel(void) { "r" (GPIO_FUNC_SIO << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB) : "memory" ); -} - -/** - * @brief Clear ISO bits in PADS_BANK0 via inline assembly - * - * @details Performs a read-modify-write to clear the pad isolation - * bit, un-isolating the pad for normal operation. - * - * @retval None - */ -static void asm_clear_iso(void) { + /// hw_clear_bits(&pads_bank0_hw->io[LED_PIN], PADS_BANK0_GPIO0_ISO_BITS); pico_default_asm_volatile ( "ldr r2, [%0]\n" // load current register value "bic r2, r2, %1\n" // clear the ISO bits (bit clear) - "str r2, [%0]\n" // write back + "str r2, [%0]\n" // write back : : "r" (&pads_bank0_hw->io[LED_PIN]), "r" (PADS_BANK0_GPIO0_ISO_BITS) : "r2", "memory" ); -} -/** - * @brief Blink LED using coprocessor mcrr output instructions - * - * @details Toggles the LED on and off with 500ms delays using - * pico_default_asm_volatile mcrr instructions. - * - * @retval None - */ -static void asm_blink_cycle(void) { - pico_default_asm_volatile ("mcrr p0, #4, %0, %1, c0" : : "r" (LED_PIN), "r" (1)); - sleep_us(500 * 1000ull); - pico_default_asm_volatile ("mcrr p0, #4, %0, %1, c0" : : "r" (LED_PIN), "r" (0)); - sleep_us(500 * 1000ull); -} - -int main(void) { - asm_set_oe_and_out(); - asm_configure_pad(); - asm_set_funcsel(); - asm_clear_iso(); + // gpio_set_dir(LED_PIN, GPIO_OUT); + /// gpioc_bit_oe_put(LED_PIN, GPIO_OUT); pico_default_asm_volatile ("mcrr p0, #4, %0, %1, c4" : : "r" (LED_PIN), "r" (GPIO_OUT)); + while (true) { - asm_blink_cycle(); + // gpio_put(LED_PIN, 1); + /// gpioc_bit_out_put(LED_PIN, 1); + pico_default_asm_volatile ("mcrr p0, #4, %0, %1, c0" : : "r" (LED_PIN), "r" (1)); + /// sleep_ms(500); + sleep_us(500 * 1000ull); + + // gpio_put(LED_PIN, 0); + /// gpioc_bit_out_put(LED_PIN, 0); + pico_default_asm_volatile ("mcrr p0, #4, %0, %1, c0" : : "r" (LED_PIN), "r" (0)); + /// sleep_ms(500); + sleep_us(500 * 1000ull); } } diff --git a/WEEK04/0x0008_uninitialized-variables-e/0x0008_uninitialized-variables-e.c b/WEEK04/0x0008_uninitialized-variables-e/0x0008_uninitialized-variables-e.c index ac572c8..5dba746 100644 --- a/WEEK04/0x0008_uninitialized-variables-e/0x0008_uninitialized-variables-e.c +++ b/WEEK04/0x0008_uninitialized-variables-e/0x0008_uninitialized-variables-e.c @@ -1,43 +1,5 @@ -/** - * @file 0x0008_uninitialized-variables-e.c - * @brief Blink LED using pure inline ARM assembly with direct register addresses - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Blinks an LED on GPIO16 using pure inline ARM assembly. No SDK calls, no - * includes. Configures PADS_BANK0, IO_BANK0, and GPIO coprocessor via direct - * register addresses and mcrr instructions, with a busy-wait delay loop. - * - * Wiring: - * GPIO16 -> LED anode (with current-limiting resistor to GND) - */ - -int main(void) { - __asm__ volatile ( +int main(void) { + __asm__ volatile ( // gpio_init(LED_PIN); /// gpio_set_dir(LED_PIN, GPIO_IN); //// gpioc_bit_oe_put(LED_PIN, GPIO_OUT); diff --git a/WEEK04/0x0008_uninitialized-variables/0x0008_uninitialized-variables.c b/WEEK04/0x0008_uninitialized-variables/0x0008_uninitialized-variables.c index 8e9dc42..0c94677 100644 --- a/WEEK04/0x0008_uninitialized-variables/0x0008_uninitialized-variables.c +++ b/WEEK04/0x0008_uninitialized-variables/0x0008_uninitialized-variables.c @@ -1,68 +1,23 @@ -/** - * @file 0x0008_uninitialized-variables.c - * @brief Uninitialized variables: demonstrate undefined behavior with printf - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Demonstrates the danger of uninitialized variables. Prints the value of an - * uninitialized uint8_t over UART while blinking an LED on GPIO16. - * - * Wiring: - * GPIO16 -> LED anode (with current-limiting resistor to GND) - */ - #include #include "pico/stdlib.h" -/** @brief GPIO pin number for the LED */ -#define LED_PIN 16 - -/** - * @brief Toggle LED and print uninitialized variable value - * - * @details Blinks the LED on and off with a 500ms delay between each - * transition and prints the age variable each cycle. - * - * @param age value to print (uninitialized in this demo) - */ -static void blink_and_print(uint8_t age) { - printf("age: %d\r\n", age); - gpio_put(LED_PIN, 1); - sleep_ms(500); - gpio_put(LED_PIN, 0); - sleep_ms(500); -} +#define LED_PIN 16 int main(void) { uint8_t age; + stdio_init_all(); + gpio_init(LED_PIN); gpio_set_dir(LED_PIN, GPIO_OUT); + while (true) { - blink_and_print(age); + printf("age: %d\r\n", age); + + gpio_put(LED_PIN, 1); + sleep_ms(500); + + gpio_put(LED_PIN, 0); + sleep_ms(500); } } diff --git a/WEEK05/0x000b_integer-data-type/0x000b_integer-data-type.c b/WEEK05/0x000b_integer-data-type/0x000b_integer-data-type.c index c923449..6a0d6ab 100644 --- a/WEEK05/0x000b_integer-data-type/0x000b_integer-data-type.c +++ b/WEEK05/0x000b_integer-data-type/0x000b_integer-data-type.c @@ -1,59 +1,17 @@ -/** - * @file 0x000b_integer-data-type.c - * @brief Integer data types: cycle LEDs on GPIO16-18 with asm, print int values - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Demonstrates uint8_t and int8_t integer data types. Initializes GPIO16-18 - * via inline assembly (PADS_BANK0, IO_BANK0, coprocessor OE), then cycles - * LEDs using coprocessor mcrr instructions while printing integer values. - * - * Wiring: - * GPIO16 -> LED1 anode (with current-limiting resistor to GND) - * GPIO17 -> LED2 anode (with current-limiting resistor to GND) - * GPIO18 -> LED3 anode (with current-limiting resistor to GND) - */ +#include +#include "pico/stdlib.h" -#include -#include "pico/stdlib.h" +int main(void) { + uint8_t age = 43; + int8_t range = -42; -/** - * @brief Initialize GPIO16-18 as SIO outputs via inline assembly loop - * - * @details Configures PADS_BANK0 (clear OD+ISO, set IE), IO_BANK0 - * (FUNCSEL=5 SIO), and coprocessor OE for pins 16-18. - * - * @retval None - */ -static void asm_init_gpio_range(void) { - __asm volatile ( + stdio_init_all(); + + __asm volatile ( "ldr r3, =0x40038000\n" // address of PADS_BANK0_BASE "ldr r2, =0x40028004\n" // address of IO_BANK0 GPIO0.ctrl "movs r0, #16\n" // GPIO16 (start pin) + "init_loop:\n" // loop start "lsls r1, r0, #2\n" // pin * 4 (pad offset) "adds r4, r3, r1\n" // PADS base + offset @@ -61,72 +19,49 @@ static void asm_init_gpio_range(void) { "bic r5, r5, #0x180\n" // clear OD+ISO "orr r5, r5, #0x40\n" // set IE "str r5, [r4]\n" // store updated config + "lsls r1, r0, #3\n" // pin * 8 (ctrl offset) "adds r4, r2, r1\n" // IO_BANK0 base + offset "ldr r5, [r4]\n" // load current config "bic r5, r5, #0x1f\n" // clear FUNCSEL bits [4:0] "orr r5, r5, #5\n" // set FUNCSEL = 5 (SIO) "str r5, [r4]\n" // store updated config + "mov r4, r0\n" // pin "movs r5, #1\n" // bit 1; used for OUT/OE writes "mcrr p0, #4, r4, r5, c4\n" // gpioc_bit_oe_put(pin,1) "adds r0, r0, #1\n" // increment pin "cmp r0, #20\n" // stop after pin 18 "blt init_loop\n" // loop until r0 == 20 - ); -} + ); -/** - * @brief Blink a single pin using coprocessor mcrr instructions - * - * @details Turns the specified pin on for 500ms, then off for 500ms - * using inline asm mcrr coprocessor output instructions. - * - * @param pin GPIO pin number to blink - * @retval None - */ -static void asm_blink_pin(uint8_t pin) { - __asm volatile ( - "mov r4, %0\n" - "movs r5, #0x01\n" - "mcrr p0, #4, r4, r5, c0\n" - : : "r"(pin) : "r4", "r5" - ); - sleep_ms(500); - __asm volatile ( - "mov r4, %0\n" - "movs r5, #0\n" - "mcrr p0, #4, r4, r5, c0\n" - : : "r"(pin) : "r4", "r5" - ); - sleep_ms(500); -} + uint8_t pin = 16; -/** - * @brief Blink LED, advance pin, and print age/range - * - * @details Blinks the current pin, wraps pin 16-18, - * and prints both integer variables. - * - * @param pin pointer to the current GPIO pin number - * @param age unsigned 8-bit age value - * @param range signed 8-bit range value - * @retval None - */ -static void blink_and_print(uint8_t *pin, uint8_t age, int8_t range) { - asm_blink_pin(*pin); - *pin = (*pin > 18) ? 16 : *pin + 1; - printf("age: %d\r\n", age); - printf("range: %d\r\n", range); -} + while (1) { + __asm volatile ( + "mov r4, %0\n" // pin + "movs r5, #0x01\n" // bit 1; used for OUT/OE writes + "mcrr p0, #4, r4, r5, c0\n" // gpioc_bit_out_put(16, 1) + : + : "r"(pin) + : "r4","r5" + ); + sleep_ms(500); -int main(void) { - uint8_t age = 43; - int8_t range = -42; - stdio_init_all(); - asm_init_gpio_range(); - uint8_t pin = 16; - while (1) { - blink_and_print(&pin, age, range); - } + __asm volatile ( + "mov r4, %0\n" // pin + "movs r5, #0\n" // bit 0; used for OUT/OE writes + "mcrr p0, #4, r4, r5, c0\n" // gpioc_bit_out_put(16, 0) + : + : "r"(pin) + : "r4","r5" + ); + sleep_ms(500); + + pin++; + if (pin > 18) pin = 16; + + printf("age: %d\r\n", age); + printf("range: %d\r\n", range); + } } diff --git a/WEEK05/0x000e_floating-point-data-type/0x000e_floating-point-data-type.c b/WEEK05/0x000e_floating-point-data-type/0x000e_floating-point-data-type.c index f0a3bac..fb3d382 100644 --- a/WEEK05/0x000e_floating-point-data-type/0x000e_floating-point-data-type.c +++ b/WEEK05/0x000e_floating-point-data-type/0x000e_floating-point-data-type.c @@ -1,47 +1,11 @@ -/** - * @file 0x000e_floating-point-data-type.c - * @brief Floating-point data type: print a float value over UART - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Demonstrates the float data type on the Raspberry Pi Pico 2. Initializes - * a float variable and prints its value over UART in an infinite loop. - * - * Wiring: - * No external wiring required (USB serial). - */ - #include #include "pico/stdlib.h" int main(void) { float fav_num = 42.5; + stdio_init_all(); - while (true) { + + while (true) printf("fav_num: %f\r\n", fav_num); - } } diff --git a/WEEK05/0x0011_double-floating-point-data-type/0x0011_double-floating-point-data-type.c b/WEEK05/0x0011_double-floating-point-data-type/0x0011_double-floating-point-data-type.c index 753f51d..d4f3d11 100644 --- a/WEEK05/0x0011_double-floating-point-data-type/0x0011_double-floating-point-data-type.c +++ b/WEEK05/0x0011_double-floating-point-data-type/0x0011_double-floating-point-data-type.c @@ -1,47 +1,11 @@ -/** - * @file 0x0011_double-floating-point-data-type.c - * @brief Double floating-point data type: print a double value over UART - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Demonstrates the double data type on the Raspberry Pi Pico 2. Initializes - * a double variable and prints its value over UART in an infinite loop. - * - * Wiring: - * No external wiring required (USB serial). - */ - #include #include "pico/stdlib.h" int main(void) { double fav_num = 42.52525; + stdio_init_all(); - while (true) { + + while (true) printf("fav_num: %lf\r\n", fav_num); - } } diff --git a/WEEK06/0x0014_static-variables/0x0014_static-variables.c b/WEEK06/0x0014_static-variables/0x0014_static-variables.c index ff5fd32..bb34259 100644 --- a/WEEK06/0x0014_static-variables/0x0014_static-variables.c +++ b/WEEK06/0x0014_static-variables/0x0014_static-variables.c @@ -1,90 +1,31 @@ -/** - * @file 0x0014_static-variables.c - * @brief Static variables: compare regular vs static local variable persistence - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Demonstrates the difference between regular and static local variables. - * A regular variable resets to 42 each iteration while a static variable - * persists and increments across loop iterations. Also reads a button on - * GPIO15 and mirrors its state to an LED on GPIO16. - * - * Wiring: - * GPIO15 -> Button (with pull-up, active low) - * GPIO16 -> LED anode (with current-limiting resistor to GND) - */ - #include #include "pico/stdlib.h" -/** @brief GPIO pin number for the button input */ -#define BUTTON_GPIO 15 -/** @brief GPIO pin number for the LED output */ -#define LED_GPIO 16 +int main(void) { + stdio_init_all(); + + const uint BUTTON_GPIO = 15; + const uint LED_GPIO = 16; + bool pressed = 0; -/** - * @brief Initialize button and LED GPIO pins - * - * @details Configures the button pin as input with pull-up and the - * LED pin as output. - * - * @retval None - */ -static void init_gpio(void) { gpio_init(BUTTON_GPIO); gpio_set_dir(BUTTON_GPIO, GPIO_IN); gpio_pull_up(BUTTON_GPIO); + gpio_init(LED_GPIO); gpio_set_dir(LED_GPIO, GPIO_OUT); -} -/** - * @brief Print and increment regular vs static variables, update LED - * - * @details Prints both variable values, increments them, reads the - * button state and drives the LED accordingly. - * - * @retval None - */ -static void demo_static_variable(void) { - uint8_t regular_fav_num = 42; - static uint8_t static_fav_num = 42; - printf("regular_fav_num: %d\r\n", regular_fav_num); - printf("static_fav_num: %d\r\n", static_fav_num); - regular_fav_num++; - static_fav_num++; - bool pressed = gpio_get(BUTTON_GPIO); - gpio_put(LED_GPIO, pressed ? 0 : 1); -} - -int main(void) { - stdio_init_all(); - init_gpio(); while (true) { - demo_static_variable(); + uint8_t regular_fav_num = 42; + static uint8_t static_fav_num = 42; + + printf("regular_fav_num: %d\r\n", regular_fav_num); + printf("static_fav_num: %d\r\n", static_fav_num); + + regular_fav_num++; + static_fav_num++; + + pressed = gpio_get(BUTTON_GPIO); + gpio_put(LED_GPIO, pressed ? 0 : 1); } } diff --git a/WEEK07/0x0017_constants/0x0017_constants.c b/WEEK07/0x0017_constants/0x0017_constants.c index f3b5182..b762ca1 100644 --- a/WEEK07/0x0017_constants/0x0017_constants.c +++ b/WEEK07/0x0017_constants/0x0017_constants.c @@ -1,98 +1,33 @@ -/** - * @file 0x0017_constants.c - * @brief Constants: demonstrate #define and const with LCD1602 I2C display - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Demonstrates #define macro constants and const-qualified variables. - * Initializes an LCD1602 display over I2C and prints constant values - * over UART in an infinite loop. - * - * Wiring: - * GPIO2 (SDA) -> LCD1602 PCF8574 SDA - * GPIO3 (SCL) -> LCD1602 PCF8574 SCL - * 3V3 -> LCD1602 VCC - * GND -> LCD1602 GND - */ - #include #include #include "pico/stdlib.h" #include "hardware/i2c.h" #include "lcd_1602.h" -/** @brief Macro constant for favorite number */ -#define FAV_NUM 42 -/** @brief I2C peripheral instance */ -#define I2C_PORT i2c1 -/** @brief GPIO pin for I2C SDA */ +#define FAV_NUM 42 + +#define I2C_PORT i2c1 #define I2C_SDA_PIN 2 -/** @brief GPIO pin for I2C SCL */ #define I2C_SCL_PIN 3 -/** @brief Const-qualified favorite number */ const int OTHER_FAV_NUM = 1337; -/** - * @brief Initialize I2C bus and LCD1602 display - * - * @details Configures I2C1 at 100kHz on GPIO2/3, initializes the - * LCD via PCF8574 at address 0x27, and writes two lines. - * - * @retval None - */ -static void init_i2c_and_lcd(void) { +int main(void) { + stdio_init_all(); + i2c_init(I2C_PORT, 100000); gpio_set_function(I2C_SDA_PIN, GPIO_FUNC_I2C); gpio_set_function(I2C_SCL_PIN, GPIO_FUNC_I2C); gpio_pull_up(I2C_SDA_PIN); gpio_pull_up(I2C_SCL_PIN); - lcd_i2c_init(I2C_PORT, 0x27, 4, 0x08); -} -/** - * @brief Write greeting text to the LCD display - * - * @details Sets cursor to line 0 and writes "Reverse", then sets - * cursor to line 1 and writes "Engineering". - * - * @retval None - */ -static void write_lcd_greeting(void) { + lcd_i2c_init(I2C_PORT, 0x27, 4, 0x08); + lcd_set_cursor(0, 0); lcd_puts("Reverse"); lcd_set_cursor(1, 0); lcd_puts("Engineering"); -} -int main(void) { - stdio_init_all(); - init_i2c_and_lcd(); - write_lcd_greeting(); while (true) { printf("FAV_NUM: %d\r\n", FAV_NUM); printf("OTHER_FAV_NUM: %d\r\n", OTHER_FAV_NUM); diff --git a/WEEK07/0x0017_constants/lcd_1602.c b/WEEK07/0x0017_constants/lcd_1602.c index 80054cc..7425cf1 100644 --- a/WEEK07/0x0017_constants/lcd_1602.c +++ b/WEEK07/0x0017_constants/lcd_1602.c @@ -31,37 +31,21 @@ #include #include -/** @brief I2C instance pointer for the LCD */ static i2c_inst_t *lcd_i2c = NULL; -/** @brief I2C address of the PCF8574 backpack */ static uint8_t lcd_addr = 0x27; -/** @brief Bit shift for 4-bit nibble position */ static int lcd_nibble_shift = 4; -/** @brief PCF8574 bit mask controlling the backlight */ static uint8_t lcd_backlight_mask = 0x08; -/** @brief PCF8574 bit mask for Register Select */ +/* PCF8574 -> LCD control pins */ #define PIN_RS 0x01 -/** @brief PCF8574 bit mask for Read/Write */ #define PIN_RW 0x02 -/** @brief PCF8574 bit mask for Enable */ #define PIN_EN 0x04 -/** - * @brief Write one raw byte to the PCF8574 expander over I2C - * - * @param data Output byte to send to the expander - */ static void pcf_write_byte(uint8_t data) { if (!lcd_i2c) return; i2c_write_blocking(lcd_i2c, lcd_addr, &data, 1, false); } -/** - * @brief Toggle EN to latch a nibble into the LCD controller - * - * @param data Current control/data bus byte (with RS and backlight already set) - */ static void pcf_pulse_enable(uint8_t data) { pcf_write_byte(data | PIN_EN); sleep_us(1); @@ -69,12 +53,6 @@ static void pcf_pulse_enable(uint8_t data) { sleep_us(50); } -/** - * @brief Write one 4-bit nibble to the LCD - * - * @param nibble Lower 4 bits to write - * @param mode 0 for command, non-zero for character data - */ static void lcd_write4(uint8_t nibble, uint8_t mode) { uint8_t data = (nibble & 0x0F) << lcd_nibble_shift; data |= mode ? PIN_RS : 0; @@ -82,37 +60,18 @@ static void lcd_write4(uint8_t nibble, uint8_t mode) { pcf_pulse_enable(data); } -/** - * @brief Send one full 8-bit command/data value as two nibbles - * - * @param value Byte to send to the LCD - * @param mode 0 for command, non-zero for character data - */ static void lcd_send(uint8_t value, uint8_t mode) { lcd_write4((value >> 4) & 0x0F, mode); lcd_write4(value & 0x0F, mode); } -/** - * @brief Store LCD driver configuration in module-level state - * - * @param i2c Pointer to the I2C instance - * @param pcf_addr 7-bit PCF8574 address - * @param nibble_shift Bit shift for 4-bit nibbles - * @param backlight_mask Backlight control bit mask - */ -static void lcd_store_config(i2c_inst_t *i2c, uint8_t pcf_addr, - int nibble_shift, uint8_t backlight_mask) { +void lcd_i2c_init(i2c_inst_t *i2c, uint8_t pcf_addr, int nibble_shift, uint8_t backlight_mask) { lcd_i2c = i2c; lcd_addr = pcf_addr; lcd_nibble_shift = nibble_shift; lcd_backlight_mask = backlight_mask; -} -/** - * @brief Execute the HD44780 4-bit mode power-on reset sequence - */ -static void lcd_hd44780_reset(void) { + // Follow init sequence for HD44780 in 4-bit mode lcd_write4(0x03, 0); sleep_ms(5); lcd_write4(0x03, 0); @@ -121,26 +80,19 @@ static void lcd_hd44780_reset(void) { sleep_us(150); lcd_write4(0x02, 0); sleep_us(150); -} -/** - * @brief Send post-reset configuration commands to the HD44780 - * - * Sets 4-bit mode with 2 display lines, turns the display on with - * cursor hidden, clears the screen, and selects left-to-right entry mode. - */ -static void lcd_hd44780_configure(void) { + // Function set: 4-bit, 2 lines lcd_send(0x28, 0); + + // Display on, cursor off lcd_send(0x0C, 0); + + // Clear lcd_send(0x01, 0); sleep_ms(2); - lcd_send(0x06, 0); -} -void lcd_i2c_init(i2c_inst_t *i2c, uint8_t pcf_addr, int nibble_shift, uint8_t backlight_mask) { - lcd_store_config(i2c, pcf_addr, nibble_shift, backlight_mask); - lcd_hd44780_reset(); - lcd_hd44780_configure(); + // Entry mode set + lcd_send(0x06, 0); } void lcd_clear(void) { @@ -150,11 +102,13 @@ void lcd_clear(void) { void lcd_set_cursor(int line, int position) { const uint8_t row_offsets[] = {0x00, 0x40}; + if (line > 1) line = 1; lcd_send(0x80 | (position + row_offsets[line]), 0); } void lcd_puts(const char *s) { - while (*s) + while (*s) { lcd_send((uint8_t)*s++, 1); + } } diff --git a/WEEK09/0x001a_operators/0x001a_operators.c b/WEEK09/0x001a_operators/0x001a_operators.c index 1eecc97..d9ddccf 100644 --- a/WEEK09/0x001a_operators/0x001a_operators.c +++ b/WEEK09/0x001a_operators/0x001a_operators.c @@ -1,126 +1,36 @@ -/** - * @file 0x001a_operators.c - * @brief Operators: demonstrate C operators with DHT11 temperature sensor - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Demonstrates arithmetic, increment, relational, logical, bitwise, and - * assignment operators in C. Also reads humidity and temperature from a - * DHT11 sensor on GPIO4. - * - * Wiring: - * GPIO4 -> DHT11 data pin (with 10k pull-up to 3V3) - * 3V3 -> DHT11 VCC - * GND -> DHT11 GND - */ - #include #include "pico/stdlib.h" #include "dht11.h" -/** - * @brief Print pre-computed operator results - * - * @details Prints all six operator demonstration values over UART. - * - * @param arith arithmetic operator result - * @param inc increment operator result - * @param rel relational operator result - * @param logic logical operator result - * @param bitw bitwise operator result - * @param assign assignment operator result - * @retval None - */ -static void print_operator_results(int arith, int inc, bool rel, - bool logic, int bitw, int assign) { - printf("arithmetic_operator: %d\r\n", arith); - printf("increment_operator: %d\r\n", inc); - printf("relational_operator: %d\r\n", rel); - printf("logical_operator: %d\r\n", logic); - printf("bitwise_operator: %d\r\n", bitw); - printf("assignment_operator: %d\r\n", assign); -} - -/** - * @brief Compute arithmetic and increment operator results - * - * @param arith pointer to store multiplication result - * @param incr pointer to store post-increment result - * @param x left operand - * @param y right operand - * @retval None - */ -static void compute_arithmetic_ops(int *arith, int *incr, int x, int y) { - *arith = (x * y); - *incr = x++; -} - -/** - * @brief Compute all operator values and print results - * - * @details Performs arithmetic, relational, logical, bitwise, - * and assignment operations, then prints each result. - * - * @retval None - */ -static void compute_operators(void) { - int x = 5, y = 10; - int arith, incr; - compute_arithmetic_ops(&arith, &incr, x, y); - bool rel = (x > y); - bool logic = (x > y) && (y > x); - int bits = (x << 1); - int assign = (x += 5); - print_operator_results(arith, incr, rel, logic, bits, assign); -} - -/** - * @brief Read and print DHT11 humidity and temperature - * - * @details Attempts a DHT11 read; on success prints humidity and - * temperature, on failure prints an error message. - * - * @retval None - */ -static void print_dht11_reading(void) { - float hum, temp; - if (dht11_read(&hum, &temp)) { - printf("Humidity: %.1f%%, Temperature: %.1f°C\r\n", hum, temp); - } else { - printf("DHT11 read failed\r\n"); - } -} - int main(void) { stdio_init_all(); + dht11_init(4); + + int x = 5; + int y = 10; + int arithmetic_operator = (x * y); + int increment_operator = x++; + bool relational_operator = (x > y); + bool logical_operator = (x > y) && (y > x); + int bitwise_operator = (x<<1); // x is now 6 because of x++ or 0b00000110 and (x<<1) is 0b00001100 or 12 + int assignment_operator = (x += 5); + while (true) { - compute_operators(); - print_dht11_reading(); + printf("arithmetic_operator: %d\r\n", arithmetic_operator); + printf("increment_operator: %d\r\n", increment_operator); + printf("relational_operator: %d\r\n", relational_operator); + printf("logical_operator: %d\r\n", logical_operator); + printf("bitwise_operator: %d\r\n", bitwise_operator); + printf("assignment_operator: %d\r\n", assignment_operator); + + float hum, temp; + if (dht11_read(&hum, &temp)) { + printf("Humidity: %.1f%%, Temperature: %.1f°C\r\n", hum, temp); + } else { + printf("DHT11 read failed\r\n"); + } + sleep_ms(2000); } } \ No newline at end of file diff --git a/WEEK09/0x001a_operators/dht11.c b/WEEK09/0x001a_operators/dht11.c index 28f147f..9a52ba8 100644 --- a/WEEK09/0x001a_operators/dht11.c +++ b/WEEK09/0x001a_operators/dht11.c @@ -31,97 +31,8 @@ #include "hardware/gpio.h" #include "pico/time.h" -/** @brief GPIO pin connected to the DHT11 sensor */ static uint dht_pin; -/** - * @brief Send the DHT11 start signal on the data pin - * - * Drives the pin LOW for 18 ms then HIGH for 40 us before switching - * the pin to input mode to listen for the sensor response. - */ -static void send_start_signal(void) { - gpio_set_dir(dht_pin, GPIO_OUT); - gpio_put(dht_pin, 0); - sleep_ms(18); - gpio_put(dht_pin, 1); - sleep_us(40); - gpio_set_dir(dht_pin, GPIO_IN); -} - -/** - * @brief Wait for the pin to leave a given logic level - * - * Spins until the pin no longer reads the specified level, returning - * false if a timeout of 10 000 iterations is exceeded. - * - * @param level Logic level to wait through (0 or 1) - * @return bool true once the level changed, false on timeout - */ -static bool wait_for_level(int level) { - uint32_t timeout = 10000; - while (gpio_get(dht_pin) == level) - if (--timeout == 0) return false; - return true; -} - -/** - * @brief Wait for the DHT11 response after the start signal - * - * The sensor pulls LOW then HIGH then LOW again; each transition - * is awaited with a timeout. - * - * @return bool true if the full response was received, false on timeout - */ -static bool wait_response(void) { - if (!wait_for_level(1)) return false; - if (!wait_for_level(0)) return false; - if (!wait_for_level(1)) return false; - return true; -} - -/** - * @brief Read a single bit from the DHT11 data stream - * - * Waits for the low-period to end, measures the high-period duration, - * and shifts the result into the appropriate byte of the data array. - * - * @param data 5-byte array accumulating the received bits - * @param i Bit index (0-39) - * @return bool true on success, false on timeout - */ -static bool read_bit(uint8_t *data, int i) { - if (!wait_for_level(0)) return false; - uint32_t start = time_us_32(); - if (!wait_for_level(1)) return false; - uint32_t duration = time_us_32() - start; - data[i / 8] <<= 1; - if (duration > 40) data[i / 8] |= 1; - return true; -} - -/** - * @brief Read all 40 data bits from the DHT11 - * - * @param data 5-byte array filled with the received data - * @return bool true if all 40 bits were read, false on timeout - */ -static bool read_40_bits(uint8_t *data) { - for (int i = 0; i < 40; i++) - if (!read_bit(data, i)) return false; - return true; -} - -/** - * @brief Verify the DHT11 checksum byte - * - * @param data 5-byte received data (bytes 0-3 plus checksum in byte 4) - * @return bool true if the checksum matches, false otherwise - */ -static bool validate_checksum(const uint8_t *data) { - return data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF); -} - void dht11_init(uint8_t pin) { dht_pin = pin; gpio_init(pin); @@ -130,10 +41,38 @@ void dht11_init(uint8_t pin) { bool dht11_read(float *humidity, float *temperature) { uint8_t data[5] = {0}; - send_start_signal(); - if (!wait_response()) return false; - if (!read_40_bits(data)) return false; - if (!validate_checksum(data)) return false; + + // Start signal + gpio_set_dir(dht_pin, GPIO_OUT); + gpio_put(dht_pin, 0); + sleep_ms(18); + gpio_put(dht_pin, 1); + sleep_us(40); + gpio_set_dir(dht_pin, GPIO_IN); + + // Wait for response + uint32_t timeout = 10000; + while (gpio_get(dht_pin) == 1) if (--timeout == 0) return false; + timeout = 10000; + while (gpio_get(dht_pin) == 0) if (--timeout == 0) return false; + timeout = 10000; + while (gpio_get(dht_pin) == 1) if (--timeout == 0) return false; + + // Read 40 bits + for (int i = 0; i < 40; i++) { + timeout = 10000; + while (gpio_get(dht_pin) == 0) if (--timeout == 0) return false; + uint32_t start = time_us_32(); + timeout = 10000; + while (gpio_get(dht_pin) == 1) if (--timeout == 0) return false; + uint32_t duration = time_us_32() - start; + data[i / 8] <<= 1; + if (duration > 40) data[i / 8] |= 1; + } + + // Check checksum + if (data[4] != ((data[0] + data[1] + data[2] + data[3]) & 0xFF)) return false; + *humidity = data[0] + data[1] * 0.1f; *temperature = data[2] + data[3] * 0.1f; return true; diff --git a/WEEK10/0x001d_static-conditionals/0x001d_static-conditionals.c b/WEEK10/0x001d_static-conditionals/0x001d_static-conditionals.c index 6db9a5e..8ad9328 100644 --- a/WEEK10/0x001d_static-conditionals/0x001d_static-conditionals.c +++ b/WEEK10/0x001d_static-conditionals/0x001d_static-conditionals.c @@ -1,106 +1,39 @@ -/** - * @file 0x001d_static-conditionals.c - * @brief Static conditionals: if/else and switch with servo sweep - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Demonstrates static (compile-time known) conditionals using if/else if/else - * and switch/case statements. Also sweeps a servo on GPIO6 between 0 and - * 180 degrees each iteration. - * - * Wiring: - * GPIO6 -> Servo signal wire (orange/white) - * 5V -> Servo VCC (red) - * GND -> Servo GND (brown/black) - */ - #include #include "pico/stdlib.h" #include "servo.h" -/** @brief GPIO pin number for the servo */ #define SERVO_GPIO 6 -/** - * @brief Print choice value using if/else if/else conditional - * - * @details Prints "1", "2", or "?" depending on the choice value. - * - * @param choice integer value to evaluate - * @retval None - */ -static void print_if_else(int choice) { - if (choice == 1) { - printf("1\r\n"); - } else if (choice == 2) { - printf("2\r\n"); - } else { - printf("?\r\n"); - } -} - -/** - * @brief Print choice value using switch/case conditional - * - * @details Prints "one", "two", or "??" depending on the choice value. - * - * @param choice integer value to evaluate - * @retval None - */ -static void print_switch(int choice) { - switch (choice) { - case 1: printf("one\r\n"); break; - case 2: printf("two\r\n"); break; - default: printf("??\r\n"); - } -} - -/** - * @brief Sweep servo between 0 and 180 degrees - * - * @details Sets the servo to 0 degrees, waits 500ms, then sets - * to 180 degrees and waits 500ms. - * - * @retval None - */ -static void sweep_servo(void) { - servo_set_angle(0.0f); - sleep_ms(500); - servo_set_angle(180.0f); - sleep_ms(500); -} - int main(void) { stdio_init_all(); + int choice = 1; + servo_init(SERVO_GPIO); + while (true) { - print_if_else(choice); - print_switch(choice); - sweep_servo(); + if (choice == 1) { + printf("1\r\n"); + } else if (choice == 2) { + printf("2\r\n"); + } else { + printf("?\r\n"); + } + + switch (choice) { + case 1: + printf("one\r\n"); + break; + case 2: + printf("two\r\n"); + break; + default: + printf("??\r\n"); + } + + servo_set_angle(0.0f); + sleep_ms(500); + servo_set_angle(180.0f); + sleep_ms(500); } } \ No newline at end of file diff --git a/WEEK10/0x001d_static-conditionals/servo.c b/WEEK10/0x001d_static-conditionals/servo.c index d0fefbd..ee48f0d 100644 --- a/WEEK10/0x001d_static-conditionals/servo.c +++ b/WEEK10/0x001d_static-conditionals/servo.c @@ -32,66 +32,46 @@ #include "hardware/pwm.h" #include "hardware/clocks.h" -/** @brief Default minimum pulse width in microseconds */ +// Default servo pulse range (SG90 typical) static const uint16_t SERVO_DEFAULT_MIN_US = 1000; -/** @brief Default maximum pulse width in microseconds */ static const uint16_t SERVO_DEFAULT_MAX_US = 2000; -/** @brief GPIO pin assigned to the servo */ +// internal state static uint8_t servo_pin = 0; -/** @brief PWM hardware slice for the servo pin */ static uint servo_slice = 0; -/** @brief PWM channel within the servo slice */ static uint servo_chan = 0; -/** @brief PWM counter wrap value for 50 Hz servo */ -static uint32_t servo_wrap = 20000 - 1; -/** @brief Servo PWM frequency in Hz */ +static uint32_t servo_wrap = 20000 - 1; // wrap to map microseconds for 50Hz static float servo_hz = 50.0f; -/** @brief Flag indicating servo has been initialized */ -static bool servo_initialized = false; -/** - * @brief Convert a pulse width in microseconds to a PWM counter level - * - * Uses the configured PWM wrap and servo frequency to map pulse time - * into the channel compare value expected by the PWM hardware. - * - * @param pulse_us Pulse width in microseconds - * @return uint32_t PWM level suitable for pwm_set_chan_level() - */ +// Convert microsecond pulse to PWM level based on wrap and frequency static uint32_t pulse_us_to_level(uint32_t pulse_us) { - const float period_us = 1000000.0f / servo_hz; + const float period_us = 1000000.0f / servo_hz; // 20000us float counts_per_us = (servo_wrap + 1) / period_us; return (uint32_t)(pulse_us * counts_per_us + 0.5f); } -/** - * @brief Build and apply the PWM slice configuration for 50 Hz servo - * - * Computes the clock divider from the system clock to achieve the - * target servo frequency with the chosen wrap value, then starts - * the PWM slice. - */ -static void apply_servo_config(void) { +void servo_init(uint8_t pin) { + servo_pin = pin; + + // Configure GPIO for PWM + gpio_set_function(servo_pin, GPIO_FUNC_PWM); + servo_slice = pwm_gpio_to_slice_num(servo_pin); + servo_chan = pwm_gpio_to_channel(servo_pin); + pwm_config config = pwm_get_default_config(); + + // Calculate clock divider to achieve 50 Hz with our chosen wrap const uint32_t sys_clock_hz = clock_get_hz(clk_sys); float clock_div = (float)sys_clock_hz / (servo_hz * (servo_wrap + 1)); + pwm_config_set_clkdiv(&config, clock_div); pwm_config_set_wrap(&config, servo_wrap); pwm_init(servo_slice, &config, true); } -void servo_init(uint8_t pin) { - servo_pin = pin; - gpio_set_function(servo_pin, GPIO_FUNC_PWM); - servo_slice = pwm_gpio_to_slice_num(servo_pin); - servo_chan = pwm_gpio_to_channel(servo_pin); - apply_servo_config(); - servo_initialized = true; -} - void servo_set_pulse_us(uint16_t pulse_us) { - if (!servo_initialized) return; + if (servo_pin == 0) return; // not initialized + // clamp to defaults if (pulse_us < SERVO_DEFAULT_MIN_US) pulse_us = SERVO_DEFAULT_MIN_US; if (pulse_us > SERVO_DEFAULT_MAX_US) pulse_us = SERVO_DEFAULT_MAX_US; uint32_t level = pulse_us_to_level(pulse_us); @@ -101,7 +81,9 @@ void servo_set_pulse_us(uint16_t pulse_us) { void servo_set_angle(float degrees) { if (degrees < 0.0f) degrees = 0.0f; if (degrees > 180.0f) degrees = 180.0f; + // linear map 0..180 -> min_us..max_us float ratio = degrees / 180.0f; uint16_t pulse = (uint16_t)(SERVO_DEFAULT_MIN_US + ratio * (SERVO_DEFAULT_MAX_US - SERVO_DEFAULT_MIN_US) + 0.5f); servo_set_pulse_us(pulse); -} \ No newline at end of file +} +# \ No newline at end of file diff --git a/WEEK10/0x0020_dynamic-conditionals/0x0020_dynamic-conditionals.c b/WEEK10/0x0020_dynamic-conditionals/0x0020_dynamic-conditionals.c index 028fcd4..1bef42c 100644 --- a/WEEK10/0x0020_dynamic-conditionals/0x0020_dynamic-conditionals.c +++ b/WEEK10/0x0020_dynamic-conditionals/0x0020_dynamic-conditionals.c @@ -1,111 +1,44 @@ -/** - * @file 0x0020_dynamic-conditionals.c - * @brief Dynamic conditionals: UART input drives if/else and switch with servo - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Demonstrates dynamic (runtime) conditionals using UART input via getchar(). - * Reads a character, evaluates it with if/else and switch/case, and controls - * a servo on GPIO6 based on the input ('1' or '2'). - * - * Wiring: - * GPIO6 -> Servo signal wire (orange/white) - * 5V -> Servo VCC (red) - * GND -> Servo GND (brown/black) - */ - #include #include "pico/stdlib.h" #include "servo.h" -/** @brief GPIO pin number for the servo */ #define SERVO_GPIO 6 -/** - * @brief Evaluate choice with if/else conditional and print result - * - * @details Compares against hex ASCII values 0x31 ('1') and 0x32 ('2'). - * - * @param choice character value received from UART - * @retval None - */ -static void eval_if_else(uint8_t choice) { - if (choice == 0x31) { - printf("1\r\n"); - } else if (choice == 0x32) { - printf("2\r\n"); - } else { - printf("??\r\n"); - } -} - -/** - * @brief Sweep servo from start angle to end angle with a pause - * - * @details Sets the servo to start, waits 500 ms, sets to end, - * waits 500 ms. - * - * @param label text to print before sweeping - * @param start starting angle in degrees - * @param end ending angle in degrees - * @retval None - */ -static void sweep_servo(const char *label, float start, float end) { - printf("%s\r\n", label); - servo_set_angle(start); - sleep_ms(500); - servo_set_angle(end); - sleep_ms(500); -} - -/** - * @brief Process choice with switch/case and drive servo accordingly - * - * @details On '1', sweeps servo 0->180; on '2', sweeps 180->0; - * otherwise prints unknown. - * - * @param choice character value received from UART - * @retval None - */ -static void process_servo_command(uint8_t choice) { - switch (choice) { - case '1': sweep_servo("one", 0.0f, 180.0f); break; - case '2': sweep_servo("two", 180.0f, 0.0f); break; - default: printf("??\r\n"); - } -} - int main(void) { stdio_init_all(); + uint8_t choice = 0; + servo_init(SERVO_GPIO); + while (true) { choice = getchar(); - eval_if_else(choice); - process_servo_command(choice); + + if (choice == 0x31) { + printf("1\r\n"); + } else if (choice == 0x32) { + printf("2\r\n"); + } else { + printf("??\r\n"); + } + + switch (choice) { + case '1': + printf("one\r\n"); + servo_set_angle(0.0f); + sleep_ms(500); + servo_set_angle(180.0f); + sleep_ms(500); + break; + case '2': + printf("two\r\n"); + servo_set_angle(180.0f); + sleep_ms(500); + servo_set_angle(0.0f); + sleep_ms(500); + break; + default: + printf("??\r\n"); + } } } diff --git a/WEEK10/0x0020_dynamic-conditionals/servo.c b/WEEK10/0x0020_dynamic-conditionals/servo.c index d0fefbd..ee48f0d 100644 --- a/WEEK10/0x0020_dynamic-conditionals/servo.c +++ b/WEEK10/0x0020_dynamic-conditionals/servo.c @@ -32,66 +32,46 @@ #include "hardware/pwm.h" #include "hardware/clocks.h" -/** @brief Default minimum pulse width in microseconds */ +// Default servo pulse range (SG90 typical) static const uint16_t SERVO_DEFAULT_MIN_US = 1000; -/** @brief Default maximum pulse width in microseconds */ static const uint16_t SERVO_DEFAULT_MAX_US = 2000; -/** @brief GPIO pin assigned to the servo */ +// internal state static uint8_t servo_pin = 0; -/** @brief PWM hardware slice for the servo pin */ static uint servo_slice = 0; -/** @brief PWM channel within the servo slice */ static uint servo_chan = 0; -/** @brief PWM counter wrap value for 50 Hz servo */ -static uint32_t servo_wrap = 20000 - 1; -/** @brief Servo PWM frequency in Hz */ +static uint32_t servo_wrap = 20000 - 1; // wrap to map microseconds for 50Hz static float servo_hz = 50.0f; -/** @brief Flag indicating servo has been initialized */ -static bool servo_initialized = false; -/** - * @brief Convert a pulse width in microseconds to a PWM counter level - * - * Uses the configured PWM wrap and servo frequency to map pulse time - * into the channel compare value expected by the PWM hardware. - * - * @param pulse_us Pulse width in microseconds - * @return uint32_t PWM level suitable for pwm_set_chan_level() - */ +// Convert microsecond pulse to PWM level based on wrap and frequency static uint32_t pulse_us_to_level(uint32_t pulse_us) { - const float period_us = 1000000.0f / servo_hz; + const float period_us = 1000000.0f / servo_hz; // 20000us float counts_per_us = (servo_wrap + 1) / period_us; return (uint32_t)(pulse_us * counts_per_us + 0.5f); } -/** - * @brief Build and apply the PWM slice configuration for 50 Hz servo - * - * Computes the clock divider from the system clock to achieve the - * target servo frequency with the chosen wrap value, then starts - * the PWM slice. - */ -static void apply_servo_config(void) { +void servo_init(uint8_t pin) { + servo_pin = pin; + + // Configure GPIO for PWM + gpio_set_function(servo_pin, GPIO_FUNC_PWM); + servo_slice = pwm_gpio_to_slice_num(servo_pin); + servo_chan = pwm_gpio_to_channel(servo_pin); + pwm_config config = pwm_get_default_config(); + + // Calculate clock divider to achieve 50 Hz with our chosen wrap const uint32_t sys_clock_hz = clock_get_hz(clk_sys); float clock_div = (float)sys_clock_hz / (servo_hz * (servo_wrap + 1)); + pwm_config_set_clkdiv(&config, clock_div); pwm_config_set_wrap(&config, servo_wrap); pwm_init(servo_slice, &config, true); } -void servo_init(uint8_t pin) { - servo_pin = pin; - gpio_set_function(servo_pin, GPIO_FUNC_PWM); - servo_slice = pwm_gpio_to_slice_num(servo_pin); - servo_chan = pwm_gpio_to_channel(servo_pin); - apply_servo_config(); - servo_initialized = true; -} - void servo_set_pulse_us(uint16_t pulse_us) { - if (!servo_initialized) return; + if (servo_pin == 0) return; // not initialized + // clamp to defaults if (pulse_us < SERVO_DEFAULT_MIN_US) pulse_us = SERVO_DEFAULT_MIN_US; if (pulse_us > SERVO_DEFAULT_MAX_US) pulse_us = SERVO_DEFAULT_MAX_US; uint32_t level = pulse_us_to_level(pulse_us); @@ -101,7 +81,9 @@ void servo_set_pulse_us(uint16_t pulse_us) { void servo_set_angle(float degrees) { if (degrees < 0.0f) degrees = 0.0f; if (degrees > 180.0f) degrees = 180.0f; + // linear map 0..180 -> min_us..max_us float ratio = degrees / 180.0f; uint16_t pulse = (uint16_t)(SERVO_DEFAULT_MIN_US + ratio * (SERVO_DEFAULT_MAX_US - SERVO_DEFAULT_MIN_US) + 0.5f); servo_set_pulse_us(pulse); -} \ No newline at end of file +} +# \ No newline at end of file diff --git a/WEEK11/0x0023_structures/0x0023_structures.c b/WEEK11/0x0023_structures/0x0023_structures.c index 657dc5f..fd802cc 100644 --- a/WEEK11/0x0023_structures/0x0023_structures.c +++ b/WEEK11/0x0023_structures/0x0023_structures.c @@ -1,50 +1,8 @@ -/** - * @file 0x0023_structures.c - * @brief Structures: IR remote controls LEDs via a struct-based controller - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Demonstrates C structures by defining a simple_led_ctrl_t to manage three - * LEDs. An IR receiver on GPIO5 decodes NEC commands and activates the - * corresponding LED (0x0C -> GPIO16, 0x18 -> GPIO17, 0x5E -> GPIO18). - * - * Wiring: - * GPIO5 -> IR receiver OUT - * GPIO16 -> LED1 anode (with current-limiting resistor to GND) - * GPIO17 -> LED2 anode (with current-limiting resistor to GND) - * GPIO18 -> LED3 anode (with current-limiting resistor to GND) - */ - #include #include #include "pico/stdlib.h" #include "ir.h" -/** @brief GPIO pin number for the IR receiver */ #define IR_PIN 5 typedef struct { @@ -56,89 +14,48 @@ typedef struct { bool led3_state; } simple_led_ctrl_t; -/** - * @brief Initialize all three LED GPIO pins as outputs - * - * @details Configures led1_pin, led2_pin, and led3_pin from the - * structure as GPIO outputs. - * - * @param leds pointer to the LED controller structure - * @retval None - */ -static void init_led_gpios(simple_led_ctrl_t *leds) { - gpio_init(leds->led1_pin); - gpio_set_dir(leds->led1_pin, GPIO_OUT); - gpio_init(leds->led2_pin); - gpio_set_dir(leds->led2_pin, GPIO_OUT); - gpio_init(leds->led3_pin); - gpio_set_dir(leds->led3_pin, GPIO_OUT); -} - -/** - * @brief Process an NEC IR key and update LED states - * - * @details Maps NEC command codes to LEDs: 0x0C -> LED1, 0x18 -> LED2, - * 0x5E -> LED3. Turns off all LEDs first, then activates the match. - * - * @param leds pointer to the LED controller structure - * @param key NEC command code from IR receiver - * @retval None - */ -static void process_ir_key(simple_led_ctrl_t *leds, int key) { - printf("NEC command: 0x%02X\n", key); - leds->led1_state = (key == 0x0C); - leds->led2_state = (key == 0x18); - leds->led3_state = (key == 0x5E); - gpio_put(leds->led1_pin, leds->led1_state); - gpio_put(leds->led2_pin, leds->led2_state); - gpio_put(leds->led3_pin, leds->led3_state); - sleep_ms(10); -} - -/** - * @brief Poll IR receiver and dispatch key to handler - * - * @details Reads one IR key; if valid, processes it; otherwise - * yields with a short sleep. - * - * @param leds pointer to the LED controller structure - * @retval None - */ -static void poll_ir(simple_led_ctrl_t *leds) { - int key = ir_getkey(); - if (key >= 0) { - process_ir_key(leds, key); - } else { - sleep_ms(1); - } -} - -/** - * @brief Build the default LED controller structure - * - * @details Initializes pins 16-18 with all LEDs off. - * - * @return simple_led_ctrl_t initialized structure - */ -static simple_led_ctrl_t make_default_leds(void) { - simple_led_ctrl_t leds = { - .led1_pin = 16, - .led2_pin = 17, - .led3_pin = 18, - .led1_state = false, - .led2_state = false, - .led3_state = false - }; - return leds; -} - int main(void) { stdio_init_all(); - simple_led_ctrl_t leds = make_default_leds(); - init_led_gpios(&leds); + + simple_led_ctrl_t leds = { + .led1_pin = 16, + .led2_pin = 17, + .led3_pin = 18, + .led1_state = false, + .led2_state = false, + .led3_state = false + }; + + gpio_init(leds.led1_pin); gpio_set_dir(leds.led1_pin, GPIO_OUT); + gpio_init(leds.led2_pin); gpio_set_dir(leds.led2_pin, GPIO_OUT); + gpio_init(leds.led3_pin); gpio_set_dir(leds.led3_pin, GPIO_OUT); + ir_init(IR_PIN); printf("IR receiver on GPIO %d ready\n", IR_PIN); + while (true) { - poll_ir(&leds); + int key = ir_getkey(); + if (key >= 0) { + printf("NEC command: 0x%02X\n", key); + + // turn all off first + leds.led1_state = false; + leds.led2_state = false; + leds.led3_state = false; + + // check NEC codes + if (key == 0x0C) leds.led1_state = true; // GPIO16 + if (key == 0x18) leds.led2_state = true; // GPIO17 + if (key == 0x5E) leds.led3_state = true; // GPIO18 + + // apply states + gpio_put(leds.led1_pin, leds.led1_state); + gpio_put(leds.led2_pin, leds.led2_state); + gpio_put(leds.led3_pin, leds.led3_state); + + sleep_ms(10); + } else { + sleep_ms(1); + } } } diff --git a/WEEK11/0x0023_structures/ir.c b/WEEK11/0x0023_structures/ir.c index 9d5b42a..b89bd4e 100644 --- a/WEEK11/0x0023_structures/ir.c +++ b/WEEK11/0x0023_structures/ir.c @@ -32,89 +32,19 @@ #include "pico/time.h" #include "hardware/gpio.h" -/** @brief GPIO pin connected to the IR receiver */ static unsigned int ir_pin = 0; -/** - * @brief Wait for a GPIO pin to reach a given logic level - * - * Spins until the pin matches the requested level or a microsecond timeout - * is exceeded. Returns the elapsed time in microseconds, or -1 on timeout. - * - * @param gpio GPIO pin to monitor - * @param level Desired logic level (true = HIGH, false = LOW) - * @param timeout_us Maximum wait in microseconds - * @return int64_t Elapsed microseconds, or -1 on timeout - */ +// Wait for 'gpio' to reach 'level' or timeout (microseconds). Return elapsed us or -1. static int64_t wait_for_level(unsigned int gpio, bool level, uint32_t timeout_us) { absolute_time_t start = get_absolute_time(); while (gpio_get(gpio) != level) { - if (absolute_time_diff_us(start, get_absolute_time()) > (int64_t)timeout_us) + if (absolute_time_diff_us(start, get_absolute_time()) > (int64_t)timeout_us) { return -1; + } } return absolute_time_diff_us(start, get_absolute_time()); } -/** - * @brief Wait for the NEC 9 ms leader pulse and 4.5 ms space - * - * @return bool true if a valid leader was detected, false on timeout - */ -static bool wait_leader(void) { - if (wait_for_level(ir_pin, 0, 150000) < 0) return false; - int64_t t = wait_for_level(ir_pin, 1, 12000); - if (t < 8000 || t > 10000) return false; - t = wait_for_level(ir_pin, 0, 7000); - if (t < 3500 || t > 5000) return false; - return true; -} - -/** - * @brief Read a single NEC-encoded bit from the IR receiver - * - * Measures the mark/space timing and shifts the result into the - * appropriate byte of the data array. - * - * @param data 4-byte array accumulating received bits - * @param i Bit index (0-31) - * @return bool true on success, false on timeout or protocol error - */ -static bool read_nec_bit(uint8_t *data, int i) { - if (wait_for_level(ir_pin, 1, 1000) < 0) return false; - int64_t t = wait_for_level(ir_pin, 0, 2500); - if (t < 200) return false; - int byte_idx = i / 8; - int bit_idx = i % 8; - if (t > 1200) data[byte_idx] |= (1 << bit_idx); - return true; -} - -/** - * @brief Read all 32 data bits of an NEC frame - * - * @param data 4-byte array filled with the received address and command - * @return bool true if all 32 bits were read, false on timeout - */ -static bool read_32_bits(uint8_t *data) { - for (int i = 0; i < 32; ++i) - if (!read_nec_bit(data, i)) return false; - return true; -} - -/** - * @brief Validate an NEC frame and extract the command byte - * - * Checks that the address and command pairs are bitwise-inverted. - * - * @param data 4-byte NEC frame (addr, ~addr, cmd, ~cmd) - * @return int Command byte (0-255) on success, -1 on validation failure - */ -static int validate_nec_frame(const uint8_t *data) { - if ((uint8_t)(data[0] + data[1]) == 0xFF && (uint8_t)(data[2] + data[3]) == 0xFF) - return data[2]; - return -1; -} - void ir_init(uint8_t pin) { ir_pin = pin; gpio_init(pin); @@ -123,8 +53,28 @@ void ir_init(uint8_t pin) { } int ir_getkey(void) { - if (!wait_leader()) return -1; + // leader low (~9 ms) + if (wait_for_level(ir_pin, 0, 150000) < 0) return -1; + + int64_t t = wait_for_level(ir_pin, 1, 12000); + if (t < 8000 || t > 10000) return -1; + + t = wait_for_level(ir_pin, 0, 7000); + if (t < 3500 || t > 5000) return -1; + uint8_t data[4] = {0, 0, 0, 0}; - if (!read_32_bits(data)) return -1; - return validate_nec_frame(data); + for (int i = 0; i < 32; ++i) { + if (wait_for_level(ir_pin, 1, 1000) < 0) return -1; + t = wait_for_level(ir_pin, 0, 2500); + if (t < 200) return -1; + int byte_idx = i / 8; + int bit_idx = i % 8; + if (t > 1200) data[byte_idx] |= (1 << bit_idx); // logical '1' + } + + // Validate address/data inverted pairs + if ((uint8_t)(data[0] + data[1]) == 0xFF && (uint8_t)(data[2] + data[3]) == 0xFF) { + return data[2]; + } + return -1; } diff --git a/WEEK11/0x0026_functions/0x0026_functions.c b/WEEK11/0x0026_functions/0x0026_functions.c index 210c7cc..518f5c0 100644 --- a/WEEK11/0x0026_functions/0x0026_functions.c +++ b/WEEK11/0x0026_functions/0x0026_functions.c @@ -1,50 +1,8 @@ -/** - * @file 0x0026_functions.c - * @brief Functions: IR remote controls LEDs with helper function decomposition - * @author Kevin Thomas - * @date 2025 - * - * MIT License - * - * Copyright (c) 2025 Kevin Thomas - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * ----------------------------------------------------------------------------- - * - * Demonstrates function decomposition by breaking IR-controlled LED logic - * into small, focused helper functions. An IR receiver on GPIO5 decodes - * NEC commands and activates the corresponding LED with a blink effect. - * - * Wiring: - * GPIO5 -> IR receiver OUT - * GPIO16 -> LED1 anode (with current-limiting resistor to GND) - * GPIO17 -> LED2 anode (with current-limiting resistor to GND) - * GPIO18 -> LED3 anode (with current-limiting resistor to GND) - */ - #include #include #include "pico/stdlib.h" #include "ir.h" -/** @brief GPIO pin number for the IR receiver */ #define IR_PIN 5 typedef struct { @@ -59,13 +17,13 @@ typedef struct { /** * @brief Map NEC IR command code to LED number * - * @details Translates a received NEC IR command code to a logical - * LED number. Supports three button mappings. + * Translates a received NEC IR command code to a logical LED number. + * Supports three button mappings for controlling individual LEDs. * * @param ir_command NEC command code from IR receiver - * @retval 1-3 for matched LED, 0 if no match + * @return int LED number (1-3) or 0 if no match */ -static int ir_to_led_number(int ir_command) { +int ir_to_led_number(int ir_command) { if (ir_command == 0x0C) return 1; if (ir_command == 0x18) return 2; if (ir_command == 0x5E) return 3; @@ -75,14 +33,14 @@ static int ir_to_led_number(int ir_command) { /** * @brief Get GPIO pin number for a given LED number * - * @details Retrieves the GPIO pin associated with a logical LED - * number from the LED controller structure. + * Retrieves the GPIO pin associated with a logical LED number + * from the LED controller structure. * - * @param leds pointer to LED controller structure + * @param leds Pointer to LED controller structure * @param led_num LED number (1-3) - * @retval GPIO pin number or 0 if invalid + * @return uint8_t GPIO pin number or 0 if invalid */ -static uint8_t get_led_pin(simple_led_ctrl_t *leds, int led_num) { +uint8_t get_led_pin(simple_led_ctrl_t *leds, int led_num) { if (led_num == 1) return leds->led1_pin; if (led_num == 2) return leds->led2_pin; if (led_num == 3) return leds->led3_pin; @@ -92,12 +50,11 @@ static uint8_t get_led_pin(simple_led_ctrl_t *leds, int led_num) { /** * @brief Turn off all LEDs in the controller * - * @details Sets all three LED GPIO outputs to low. + * Sets all three LED GPIO outputs to low, turning off all LEDs. * - * @param leds pointer to LED controller structure - * @retval None + * @param leds Pointer to LED controller structure */ -static void leds_all_off(simple_led_ctrl_t *leds) { +void leds_all_off(simple_led_ctrl_t *leds) { gpio_put(leds->led1_pin, false); gpio_put(leds->led2_pin, false); gpio_put(leds->led3_pin, false); @@ -106,15 +63,14 @@ static void leds_all_off(simple_led_ctrl_t *leds) { /** * @brief Blink an LED pin a specified number of times * - * @details Toggles the specified GPIO pin on and off for the given - * count, with configurable delay between transitions. + * Toggles the specified GPIO pin on and off for the given count, + * with configurable delay between transitions. * - * @param pin GPIO pin number to blink - * @param count number of blink cycles - * @param delay_ms delay in milliseconds for on/off periods - * @retval None + * @param pin GPIO pin number to blink + * @param count Number of blink cycles + * @param delay_ms Delay in milliseconds for on/off periods */ -static void blink_led(uint8_t pin, uint8_t count, uint32_t delay_ms) { +void blink_led(uint8_t pin, uint8_t count, uint32_t delay_ms) { for (uint8_t i = 0; i < count; i++) { gpio_put(pin, true); sleep_ms(delay_ms); @@ -126,15 +82,15 @@ static void blink_led(uint8_t pin, uint8_t count, uint32_t delay_ms) { /** * @brief Process IR command and activate corresponding LED * - * @details Turns off all LEDs, maps the command to an LED number, - * blinks it, then holds it steady. + * Handles incoming IR commands by turning off all LEDs, mapping the + * command to an LED, blinking it, then holding it steady. * - * @param ir_command NEC command code from IR receiver - * @param leds pointer to LED controller structure - * @param blink_count number of blinks before steady state - * @retval LED number activated (1-3), 0 if none, -1 if invalid + * @param ir_command NEC command code from IR receiver + * @param leds Pointer to LED controller structure + * @param blink_count Number of blinks before steady state + * @return int LED number activated (1-3), 0 if none, -1 if invalid */ -static int process_ir_led_command(int ir_command, simple_led_ctrl_t *leds, uint8_t blink_count) { +int process_ir_led_command(int ir_command, simple_led_ctrl_t *leds, uint8_t blink_count) { if (!leds || ir_command < 0) return -1; leds_all_off(leds); int led_num = ir_to_led_number(ir_command); @@ -145,93 +101,49 @@ static int process_ir_led_command(int ir_command, simple_led_ctrl_t *leds, uint8 return led_num; } -/** - * @brief Initialize all three LED GPIO pins as outputs - * - * @details Configures led1_pin, led2_pin, and led3_pin from the - * structure as GPIO outputs. - * - * @param leds pointer to the LED controller structure - * @retval None - */ -static void init_led_gpios(simple_led_ctrl_t *leds) { - gpio_init(leds->led1_pin); - gpio_set_dir(leds->led1_pin, GPIO_OUT); - gpio_init(leds->led2_pin); - gpio_set_dir(leds->led2_pin, GPIO_OUT); - gpio_init(leds->led3_pin); - gpio_set_dir(leds->led3_pin, GPIO_OUT); -} - -/** - * @brief Poll IR and handle a single received key - * - * @details Reads an IR key, processes the command with 3 blinks, - * and prints the result. - * - * @param leds pointer to the LED controller structure - * @retval None - */ -/** - * @brief Handle a valid IR key press - * - * @details Prints the NEC command, processes it with 3 blinks, - * and reports the activated LED. - * - * @param leds pointer to the LED controller structure - * @param key NEC command code - * @retval None - */ -static void handle_ir_key(simple_led_ctrl_t *leds, int key) { - printf("NEC command: 0x%02X\n", key); - int activated_led = process_ir_led_command(key, leds, 3); - if (activated_led > 0) { - printf("LED %d activated on GPIO %d\n", activated_led, - get_led_pin(leds, activated_led)); - } - sleep_ms(10); -} - -/** - * @brief Poll IR and handle a single received key - * - * @details Reads an IR key; if valid dispatches to handler, - * otherwise yields with a short sleep. - * - * @param leds pointer to the LED controller structure - * @retval None - */ -static void poll_and_handle_ir(simple_led_ctrl_t *leds) { - int key = ir_getkey(); - if (key >= 0) { - handle_ir_key(leds, key); - } else { - sleep_ms(1); - } -} - -/** - * @brief Build the default LED controller structure - * - * @details Initializes pins 16-18 with all LEDs off. - * - * @return simple_led_ctrl_t initialized structure - */ -static simple_led_ctrl_t make_default_leds(void) { - simple_led_ctrl_t leds = { - .led1_pin = 16, .led2_pin = 17, .led3_pin = 18, - .led1_state = false, .led2_state = false, .led3_state = false - }; - return leds; -} - int main(void) { stdio_init_all(); - simple_led_ctrl_t leds = make_default_leds(); - init_led_gpios(&leds); + + simple_led_ctrl_t leds = { + .led1_pin = 16, + .led2_pin = 17, + .led3_pin = 18, + .led1_state = false, + .led2_state = false, + .led3_state = false + }; + + // Initialize LED GPIOs + gpio_init(leds.led1_pin); gpio_set_dir(leds.led1_pin, GPIO_OUT); + gpio_init(leds.led2_pin); gpio_set_dir(leds.led2_pin, GPIO_OUT); + gpio_init(leds.led3_pin); gpio_set_dir(leds.led3_pin, GPIO_OUT); + + // Initialize IR receiver ir_init(IR_PIN); printf("IR receiver on GPIO %d ready\n", IR_PIN); + printf("Press remote buttons to control LEDs with blink effects!\n"); + while (true) { - poll_and_handle_ir(&leds); + int key = ir_getkey(); + if (key >= 0) { + printf("NEC command: 0x%02X\n", key); + + // Process the IR command with 3 blinks before steady state + int activated_led = process_ir_led_command(key, &leds, 3); + + if (activated_led > 0) { + printf("LED %d activated on GPIO %d\n", activated_led, + (activated_led == 1) ? leds.led1_pin : + (activated_led == 2) ? leds.led2_pin : leds.led3_pin); + } else if (activated_led == 0) { + printf("No LED matched or chase effect played\n"); + } else { + printf("Invalid command or null pointer\n"); + } + + sleep_ms(10); + } else { + sleep_ms(1); + } } } diff --git a/WEEK11/0x0026_functions/ir.c b/WEEK11/0x0026_functions/ir.c index 9d5b42a..b89bd4e 100644 --- a/WEEK11/0x0026_functions/ir.c +++ b/WEEK11/0x0026_functions/ir.c @@ -32,89 +32,19 @@ #include "pico/time.h" #include "hardware/gpio.h" -/** @brief GPIO pin connected to the IR receiver */ static unsigned int ir_pin = 0; -/** - * @brief Wait for a GPIO pin to reach a given logic level - * - * Spins until the pin matches the requested level or a microsecond timeout - * is exceeded. Returns the elapsed time in microseconds, or -1 on timeout. - * - * @param gpio GPIO pin to monitor - * @param level Desired logic level (true = HIGH, false = LOW) - * @param timeout_us Maximum wait in microseconds - * @return int64_t Elapsed microseconds, or -1 on timeout - */ +// Wait for 'gpio' to reach 'level' or timeout (microseconds). Return elapsed us or -1. static int64_t wait_for_level(unsigned int gpio, bool level, uint32_t timeout_us) { absolute_time_t start = get_absolute_time(); while (gpio_get(gpio) != level) { - if (absolute_time_diff_us(start, get_absolute_time()) > (int64_t)timeout_us) + if (absolute_time_diff_us(start, get_absolute_time()) > (int64_t)timeout_us) { return -1; + } } return absolute_time_diff_us(start, get_absolute_time()); } -/** - * @brief Wait for the NEC 9 ms leader pulse and 4.5 ms space - * - * @return bool true if a valid leader was detected, false on timeout - */ -static bool wait_leader(void) { - if (wait_for_level(ir_pin, 0, 150000) < 0) return false; - int64_t t = wait_for_level(ir_pin, 1, 12000); - if (t < 8000 || t > 10000) return false; - t = wait_for_level(ir_pin, 0, 7000); - if (t < 3500 || t > 5000) return false; - return true; -} - -/** - * @brief Read a single NEC-encoded bit from the IR receiver - * - * Measures the mark/space timing and shifts the result into the - * appropriate byte of the data array. - * - * @param data 4-byte array accumulating received bits - * @param i Bit index (0-31) - * @return bool true on success, false on timeout or protocol error - */ -static bool read_nec_bit(uint8_t *data, int i) { - if (wait_for_level(ir_pin, 1, 1000) < 0) return false; - int64_t t = wait_for_level(ir_pin, 0, 2500); - if (t < 200) return false; - int byte_idx = i / 8; - int bit_idx = i % 8; - if (t > 1200) data[byte_idx] |= (1 << bit_idx); - return true; -} - -/** - * @brief Read all 32 data bits of an NEC frame - * - * @param data 4-byte array filled with the received address and command - * @return bool true if all 32 bits were read, false on timeout - */ -static bool read_32_bits(uint8_t *data) { - for (int i = 0; i < 32; ++i) - if (!read_nec_bit(data, i)) return false; - return true; -} - -/** - * @brief Validate an NEC frame and extract the command byte - * - * Checks that the address and command pairs are bitwise-inverted. - * - * @param data 4-byte NEC frame (addr, ~addr, cmd, ~cmd) - * @return int Command byte (0-255) on success, -1 on validation failure - */ -static int validate_nec_frame(const uint8_t *data) { - if ((uint8_t)(data[0] + data[1]) == 0xFF && (uint8_t)(data[2] + data[3]) == 0xFF) - return data[2]; - return -1; -} - void ir_init(uint8_t pin) { ir_pin = pin; gpio_init(pin); @@ -123,8 +53,28 @@ void ir_init(uint8_t pin) { } int ir_getkey(void) { - if (!wait_leader()) return -1; + // leader low (~9 ms) + if (wait_for_level(ir_pin, 0, 150000) < 0) return -1; + + int64_t t = wait_for_level(ir_pin, 1, 12000); + if (t < 8000 || t > 10000) return -1; + + t = wait_for_level(ir_pin, 0, 7000); + if (t < 3500 || t > 5000) return -1; + uint8_t data[4] = {0, 0, 0, 0}; - if (!read_32_bits(data)) return -1; - return validate_nec_frame(data); + for (int i = 0; i < 32; ++i) { + if (wait_for_level(ir_pin, 1, 1000) < 0) return -1; + t = wait_for_level(ir_pin, 0, 2500); + if (t < 200) return -1; + int byte_idx = i / 8; + int bit_idx = i % 8; + if (t > 1200) data[byte_idx] |= (1 << bit_idx); // logical '1' + } + + // Validate address/data inverted pairs + if ((uint8_t)(data[0] + data[1]) == 0xFF && (uint8_t)(data[2] + data[3]) == 0xFF) { + return data[2]; + } + return -1; }