From 33448ed14e4fa80c0a541b1b93a34046106ed658 Mon Sep 17 00:00:00 2001 From: Alexander Bessman Date: Thu, 7 Mar 2024 16:12:19 +0100 Subject: [PATCH] Refactor Logic Analyzer --- CMakeLists.txt | 1 + src/CMakeLists.txt | 7 + src/commands.c | 14 +- src/helpers/buffer.h | 32 +-- src/instruments/CMakeLists.txt | 5 +- src/instruments/logic_analyzer.c | 336 +++++++++++++++++++++++++++++++ src/instruments/logic_analyzer.h | 59 ++++++ src/instruments/logicanalyzer.c | 179 ---------------- src/instruments/logicanalyzer.h | 229 --------------------- 9 files changed, 429 insertions(+), 433 deletions(-) create mode 100644 src/instruments/logic_analyzer.c create mode 100644 src/instruments/logic_analyzer.h delete mode 100644 src/instruments/logicanalyzer.c delete mode 100644 src/instruments/logicanalyzer.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f9c526c..ce087b5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,7 @@ cmake_minimum_required(VERSION 3.16) set(CMAKE_TOOLCHAIN_FILE external/cmake-microchip/toolchain.cmake) set(MICROCHIP_MCU PIC24EP256GP204) +set(CMAKE_SYSTEM_NAME Generic) project(PSLAB_FIRMWARE LANGUAGES C ASM) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5c8e7a8..8b88a0c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,9 +3,16 @@ add_subdirectory(bus) add_subdirectory(helpers) add_subdirectory(instruments) add_subdirectory(registers) +add_subdirectory(registers_ng) add_subdirectory(sdcard) target_sources(pslab-firmware.elf PRIVATE commands.c main.c states.c) + +target_include_directories(pslab-firmware.elf PRIVATE + $(CMAKE_CURRENT_SOURCE_DIR) + registers_ng + helpers +) diff --git a/src/commands.c b/src/commands.c index a97993e..ae83390 100644 --- a/src/commands.c +++ b/src/commands.c @@ -9,7 +9,7 @@ #include "helpers/interval.h" #include "helpers/light.h" #include "helpers/rtc.h" -#include "instruments/logicanalyzer.h" +#include "instruments/logic_analyzer.h" #include "instruments/multimeter.h" #include "instruments/oscilloscope.h" #include "instruments/powersource.h" @@ -217,7 +217,7 @@ command_func_t* const cmd_table[NUM_PRIMARY_CMDS + 1][NUM_SECONDARY_CMDS_MAX + 1 }, { // 9 DIN // 0 1 GET_STATE 2 GET_STATES 3 - Undefined, Unimplemented, PIN_MANAGER_GetLAPinState, Undefined, + Undefined, Unimplemented, LA_get_states, Undefined, // 4 5 6 7 Undefined, Undefined, Undefined, Undefined, // 8 9 10 11 @@ -235,13 +235,13 @@ command_func_t* const cmd_table[NUM_PRIMARY_CMDS + 1][NUM_SECONDARY_CMDS_MAX + 1 // 0 1 GET_TIMING 2 3 Undefined, Unimplemented, Undefined, Undefined, // 4 START_ONE_CHAN_LA 5 START_TWO_CHAN_LA 6 START_FOUR_CHAN_LA 7 FETCH_DMA_DATA - LOGICANALYZER_OneChannel, LOGICANALYZER_TwoChannel, LOGICANALYZER_FourChannel, Removed, + LA_capture, Removed, Removed, Removed, // 8 FETCH_INT_DMA_DATA 9 FETCH_LONG_DMA_DATA 10 COMPARATOR_TO_LA 11 GET_INITIAL_STATES - BUFFER_FetchInt, BUFFER_FetchLong, Unimplemented, INTERVAL_GetState, + BUFFER_FetchInt, BUFFER_FetchLong, Unimplemented, LA_get_initial_states, // 12 TIMING_MEASUREMENTS 13 INTERVAL_MEASUREMENTS 14 CONFIGURE_COMPARATOR 15 START_ALTERNATE_ONE_CHAN_LA - Unimplemented, Unimplemented, Removed, LOGICANALYZER_OneChannelAlt, + Unimplemented, Unimplemented, Removed, Removed, // 16 START_THREE_CHAN_LA 17 STOP_LA 18 19 - LOGICANALYZER_ThreeChannel, LOGICANALYZER_Stop, Undefined, Undefined, + Removed, LA_stop, Undefined, Undefined, // 20 21 22 23 Undefined, Undefined, Undefined, Undefined, // 24 25 26 27 @@ -310,5 +310,5 @@ command_func_t* const cmd_table[NUM_PRIMARY_CMDS + 1][NUM_SECONDARY_CMDS_MAX + 1 Undefined, Undefined, Undefined, Undefined, // 24 25 26 27 Undefined, Undefined, Undefined, Undefined, - }, + }, }; diff --git a/src/helpers/buffer.h b/src/helpers/buffer.h index f9a7331..f9b4109 100644 --- a/src/helpers/buffer.h +++ b/src/helpers/buffer.h @@ -3,6 +3,8 @@ #include +#include "commands.h" + #define BUFFER_SIZE 10000 #ifdef __cplusplus @@ -10,24 +12,24 @@ extern "C" { #endif extern uint16_t volatile __attribute__((section(".adc_buffer"), far)) BUFFER[BUFFER_SIZE]; - + /** * @brief Send buffer contents. - * + * * @description * This command function takes two arguments over serial: * 1. The starting index in the buffer from which to send values. * 2. The number of values to be sent. * It returns the requested data over serial. * It sends an acknowledge byte (SUCCESS) - * + * * @return SUCCESS */ response_t BUFFER_Retrieve(void); - + /** * @brief Send buffer content as integers. - * + * * @description * This command function takes two arguments over serial: * 1. The starting index in the buffer from which to send values. @@ -35,14 +37,14 @@ extern "C" { * * It returns the requested data over serial. * It sends an acknowledge byte (SUCCESS) - * + * * @return SUCCESS */ response_t BUFFER_FetchInt(void); - + /** * @brief Send buffer content as longs. - * + * * @description * This command function takes two arguments over serial: * 1. The starting index in the buffer from which to send values. @@ -50,29 +52,29 @@ extern "C" { * * It returns the requested data over serial. * It sends an acknowledge byte (SUCCESS) - * + * * @return SUCCESS */ response_t BUFFER_FetchLong(void); /** * @brief Populate BUFFER array - * + * * @description * This command function takes two arguments over serial: * 1. The starting index in the buffer from which to fill values. * 2. The number of values to be sent. - * + * * It does not return anything over serial. * It sends an acknowledge byte (SUCCESS) - * + * * @return SUCCESS */ response_t BUFFER_Fill(void); - + /** * @brief Clear BUFFER array - * + * * @description * This command function takes two arguments over serial: * 1. The starting index in the buffer from which it should be emptied @@ -80,7 +82,7 @@ extern "C" { * * It does not return anything over serial. * It sends an acknowledge byte (SUCCESS) - * + * * @return SUCCESS */ response_t BUFFER_Clear(void); diff --git a/src/instruments/CMakeLists.txt b/src/instruments/CMakeLists.txt index 78deed1..ccc2ffc 100644 --- a/src/instruments/CMakeLists.txt +++ b/src/instruments/CMakeLists.txt @@ -1,5 +1,5 @@ target_sources(pslab-firmware.elf PRIVATE - logicanalyzer.c + logic_analyzer.c multimeter.c oscilloscope.c powersource.c @@ -8,5 +8,4 @@ target_sources(pslab-firmware.elf PRIVATE ) target_include_directories(pslab-firmware.elf - PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) - + INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/src/instruments/logic_analyzer.c b/src/instruments/logic_analyzer.c new file mode 100644 index 0000000..f466bb1 --- /dev/null +++ b/src/instruments/logic_analyzer.c @@ -0,0 +1,336 @@ +/** + * @file logic_analyzer.c + * @author Alexander Bessman (alexander.bessman@gmail.com) + * @brief High-level driver for the PSLab's Logic Analyzer instrument + * @details + * # Implementation + * + * The logic analyzer uses the following resources: + * + * ## Pins LA1-4 + * + * When the logic level on an active pin changes, a timestamp is stored in the + * sample buffer. Three types of logic level changes (edges) can be captured: + * ANY, FALLING, or RISING. + * + * If the configured edge type is ANY, a timestamp is stored every time the + * logic level changes from low to high, or from high to low. + * + * If the configured edge type is RISING, a timestamp is stored every time the + * logic level changes from low to high, but not from high to low. Vice versa + * for edge type FALLING. + * + * Up to 10k timestamps can be captured, across all four channels. + * + * ## Input Capture (IC) channels IC1-4 + * + * Each ICx channel is associated with the corresponding LAx pin. When the + * configured edge type is detected on LAx, the current value of ICxTMR is + * copied to ICxBUF. + * + * IC interrupt is used to trigger delayed capture, if edge type is FALLING or + * RISING. If edge type is ANY, delayed capture is instead triggered by CN. + * + * ## Input Change Notification (CN) + * + * One pin may be designated as the trigger pin, in which case capture begins + * when the configured edge type is detected on that pin. If no pin is selected + * as trigger, capture begins immediatedely. + * + * If the edge type is ANY, CN interrupt is used to start capture. If the edge + * type is FALLING or RISING, IC interrupt is used instead. + * + * ## Timer TMR5 + * + * When the trigger condition is met, TMR5 is started. TMR5 is used as trigger + * source to start the enabled IC channels' ICxTMR, as well as clock source to + * clock the same. + * + * ## Direct Memory Access (DMA) channels DMA0-3 + * + * ICx drives DMA(x-1). Every time a new value is copied to ICxBUF, DMA(x-1) + * copies it to the sample buffer. + * + * When the requested number of timestamps have been captured on LAx, DMA(x-1) + * interrupts and resets itself and ICx. If ICx is the last active channel, + * TMR5 is reset. + * + * ## Sample Buffer + * + * Captured timestamps are stored in the sample buffer. + */ + +#include +#include + +#include "../bus/uart/uart.h" +#include "helpers/buffer.h" +#include "commands.h" +#include "registers_ng/cn.h" +#include "registers_ng/dma.h" +#include "registers_ng/ic.h" +#include "registers_ng/pins.h" +#include "registers_ng/tmr.h" +#include "types.h" + +/*********************/ +/* Static Prototypes */ +/*********************/ + +/** + * @brief Start TMR and DMA + * @details + * May be called directly to trigger manually, or by an interrupt callback. + */ +static void trigger(void); + +/** + * @brief Trigger from Input Capture interrupt + * @details + * Register with `IC_interrupt_enable`. Disables IC interrupt and then calls + * `trigger`. Used when triggering on either FALLING or RISING edges, not both. + * + * @param channel + */ +static void ic_callback(Channel channel); + +/** + * @brief Trigger from Input Change Notification interrupt + * @details + * Register with `CN_interrupt_enable`. Disables CN interrupt and then calls + * `trigger`. Used when triggering on ANY edge. + * + * @param channel + * Unused. + */ +static void cn_callback(Channel channel); + +/** + * @brief Stop IC, DMA, and TMR when all events have been captured + * + * @details Called by DMA interrupts to cleanup after capture is complete. + * + * @param channel + */ +static void cleanup_callback(Channel channel); + +/** + * @brief Capture logic level changes on on LA1-4 + * + * @param num_channels + * @param events + * @param edge + * @param trigger_pin + */ +static void capture( + uint8_t num_channels, + uint16_t events, + Edge edge, + Channel trigger_pin +); + +/** + * @brief Choose trigger method based on pin and edge type + * @details + * Manually triggers immediately if `trigger_pin` is NONE. + * + * Uses IC interrupt if `edge` is RISING or FALLING, CN interrupt if edge is + * ANY. + * + * @param edge + * @param trigger_pin + */ +static void configure_trigger(Edge edge, Channel trigger_pin); + +/** + * @brief Convert TMR to corresponding IC clock source + * + * @param timer + * @return IC_Timer + */ +static IC_Timer timer2ictsel(TMR_Timer timer); + +/***********/ +/* Globals */ +/***********/ + +static uint8_t g_num_channels = 0; + +static uint8_t g_initial_states = 0; + +static TMR_Timer const g_TIMER = TMR_TIMER_5; + +/********************/ +/* Static Functions */ +/********************/ + +static void trigger(void) +{ + // Set timer period to a small value to assert sync when timer starts. + TMR_set_period(g_TIMER, 1); + TMR_start(g_TIMER); + g_initial_states = PINS_get_la_states(); + + /* When DMA starts, every time a value is copied to ICxBUF it will be + * further copied to sample buffer. + * DMA channels cannot be started simultaneously. It is possible we might + * miss edges between timer start and DMA start. The alternative is to + * start DMA first, which risks copying spurious zeros to sample buffer. + */ + /* Unroll loop; saving even a single clock cycle between DMA channel + * starts is meaningful. */ + switch (g_num_channels) { + case 4: // NOLINT(readability-magic-numbers) + DMA_start(CHANNEL_4); + case 3: // NOLINT(readability-magic-numbers) + DMA_start(CHANNEL_3); + case 2: + DMA_start(CHANNEL_2); + case 1: + DMA_start(CHANNEL_1); + default: + break; + } + + // Timer sync output is only needed once; disable it after trigger is done. + TMR_set_period(g_TIMER, 0); +} + +static void ic_callback(Channel const channel) +{ + IC_interrupt_disable(channel); + trigger(); +} + +static void cn_callback(__attribute__((unused)) Channel const channel) +{ + CN_reset(); + trigger(); +} + +static void cleanup_callback(Channel const channel) +{ + DMA_reset(channel); + IC_reset(channel); + --g_num_channels; + + // Reset the clock if this was the last active channel. + if (!g_num_channels) { + TMR_reset(g_TIMER); + } +} + +static void capture( + uint8_t const num_channels, + uint16_t const events, + Edge const edge, + Channel const trigger_pin +) +{ + CN_reset(); + g_num_channels = num_channels; + + for (uint8_t i = 0; i < num_channels; ++i) { + IC_reset(i); + DMA_reset(i); + size_t const address = + (size_t)(BUFFER + i * BUFFER_SIZE / num_channels); + DMA_setup(i, events, address, DMA_SOURCE_IC); + /* DMA interrupt is enabled here, but the DMA transfer itself is + * started in trigger callback. */ + DMA_interrupt_enable(i, cleanup_callback); + /* IC is started here. IC will now begin copying the value of ICxTMR to + * ICxBUF whenever an event occurs. Until the trigger event starts the + * clock source, ICxTMR will be held at zero. This is not a problem, + * because although zeros will be copied to ICxBUF, they won't be + * copied to the sample buffer until DMA is started by the trigger + * callback. */ + IC_start(i, edge, timer2ictsel(g_TIMER)); + } + + configure_trigger(edge, trigger_pin); +} + +static void configure_trigger(Edge const edge, Channel const trigger_pin) +{ + if (trigger_pin == CHANNEL_NONE) { + // Start immediately. + trigger(); + return; + } + + if (edge == EDGE_ANY) { + /* IC cannot interrupt on both falling and rising edge, only one or the + * other. Must use CN instead. */ + CN_interrupt_enable(trigger_pin, cn_callback); + return; + } + + IC_interrupt_enable(trigger_pin, ic_callback); +} + +static IC_Timer timer2ictsel(TMR_Timer const timer) +{ + switch (timer) { + case TMR_TIMER_5: + return IC_TIMER_TMR5; + default: + return IC_TIMER_PERIPHERAL; + } +} + +/********************/ +/* Public Functions */ +/********************/ + +response_t LA_capture(void) +{ + uint8_t const num_channels = UART1_Read(); + uint16_t const events = UART1_ReadInt(); + Edge const edge = (int8_t)UART1_Read(); + Channel const trigger = (int8_t)UART1_Read(); + + if (num_channels == 0) { + return ARGUMENT_ERROR; + } + + if (num_channels > CHANNEL_NUMEL) { + return ARGUMENT_ERROR; + } + + if (events > BUFFER_SIZE) { + return ARGUMENT_ERROR; + } + + if (edge == EDGE_NONE) { + return ARGUMENT_ERROR; + } + + capture(num_channels, events, edge, trigger); + return SUCCESS; +} + +response_t LA_stop(void) +{ + CN_reset(); + TMR_reset(g_TIMER); + + for (size_t i = 0; i < CHANNEL_NUMEL; ++i) { + IC_reset(i); + DMA_reset(i); + } + + return SUCCESS; +} + +response_t LA_get_states(void) +{ + UART1_Write(PINS_get_la_states()); + return SUCCESS; +} + +response_t LA_get_initial_states(void) +{ + UART1_Write(g_initial_states); + return SUCCESS; +} diff --git a/src/instruments/logic_analyzer.h b/src/instruments/logic_analyzer.h new file mode 100644 index 0000000..0f45944 --- /dev/null +++ b/src/instruments/logic_analyzer.h @@ -0,0 +1,59 @@ +#ifndef LOGICANALYZER_H +#define LOGICANALYZER_H + +#include "../commands.h" + +/** + * @brief Capture logic level changes on pins LA1-4 + * + * @details + * Every time the logic level changes on an active pin, a timestamp is copied + * to the sample buffer. + * + * Three types of logic level change can be captured: any, falling, or rising. + * + * One pin may be chosen as trigger. If so, capture only starts once an edge is + * detected on that pin. Otherwise, capture begins immediately. + * + * @param uint8_t num_channels + * Value from 1 to 4, determining how many of the LA pins to use. + * @param uint16_t events + * Number of edges to capture per channel. + * @param Edge edge + * @param Channel trigger + * + * @return SUCCESS + */ +response_t LA_capture(void); + +/** + * @brief Stop capture + * + * @details + * Stop edge capture ahead of time, and release associated resourses. + * + * @return SUCCESS + */ +response_t LA_stop(void); + +/** + * @brief Get states of LA1-4 + * + * @details + * Low nibble of returned byte correspond to pins LA1-4, one pin per bit. + * + * @return SUCCESS + */ +response_t LA_get_states(void); + +/** + * @brief Get states of LA1-4 immediately before capture started + * + * @details + * Low nibble of returned byte correspond to pins LA1-4, one pin per bit. + * + * @return SUCCESS + */ +response_t LA_get_initial_states(void); + +#endif /* LOGICANALYZER_H */ diff --git a/src/instruments/logicanalyzer.c b/src/instruments/logicanalyzer.c deleted file mode 100644 index 73ebe3f..0000000 --- a/src/instruments/logicanalyzer.c +++ /dev/null @@ -1,179 +0,0 @@ -#include -#include "../bus/uart/uart.h" -#include "../helpers/interval.h" -#include "../registers/comparators/ic1.h" -#include "../registers/comparators/ic2.h" -#include "../registers/comparators/ic3.h" -#include "../registers/comparators/ic4.h" -#include "../registers/comparators/ic_params.h" -#include "../registers/system/interrupt_manager.h" -#include "../registers/system/pin_manager.h" -#include "../registers/timers/tmr2.h" -#include "../commands.h" - -#define FALLING_EDGE 1 -#define RISING_EDGE 0 - -static uint8_t LA_TRIGGER_CHANNEL = 32; -void SetLA_TRIGGER_CHANNEL(uint8_t V) { LA_TRIGGER_CHANNEL = V; } -uint8_t GetLA_TRIGGER_CHANNEL(void) { return LA_TRIGGER_CHANNEL; } - -static uint8_t LA_TRIGGER_STATE = 0; -void SetLA_TRIGGER_STATE(uint8_t V) { LA_TRIGGER_STATE = V; } -uint8_t GetLA_TRIGGER_STATE(void) { return LA_TRIGGER_STATE; } - -response_t LOGICANALYZER_OneChannel(void) { - - uint16_t points = UART1_ReadInt(); - uint8_t trigger = UART1_Read(); - uint8_t config = UART1_Read(); - - if (trigger & 1) { - INTCON2bits.INT2EP = trigger & 2 ? FALLING_EDGE : RISING_EDGE; - RPINR1bits.INT2R = PIN_MANAGER_DIGITAL_PINS[(trigger >> 4) & 0xF]; - } - - INTERVAL_CaptureOne(points, (config >> 4) & 0xF, config & 0xF, 0); - - if (trigger & 1) { - INTERRUPT_ClearExternalInterrupt2Flag(); - INTERRUPT_EnableExternalInterrupt2(); - } else { - SetDefaultDIGITAL_STATES(); - IC1_ManualTriggerSet(); - IC2_ManualTriggerSet(); - } - - return SUCCESS; -} - -response_t LOGICANALYZER_OneChannelAlt(void) { - - uint16_t points = UART1_ReadInt(); - uint8_t config = UART1_Read(); - uint8_t trigger = UART1_Read(); - - IC4_InterruptHighPriority(); - IC4_InterruptFlagClear(); - IC4_InterruptDisable(); - - if (trigger & 7) { - INTERVAL_CaptureOne(points, (config >> 4) & 0xF, config & 0xF, trigger); - IC4_InterruptEnable(); - } else { - INTERVAL_CaptureOne(points, (config >> 4) & 0xF, config & 0xF, 0); - SetDefaultDIGITAL_STATES(); - IC1_ManualTriggerSet(); - IC2_ManualTriggerSet(); - } - - return SUCCESS; -} - -response_t LOGICANALYZER_TwoChannel(void) { - - uint16_t points = UART1_ReadInt(); - uint8_t trigger = UART1_Read(); - uint8_t config = UART1_Read(); - uint8_t channel = UART1_Read(); - - if (trigger & 1) { - INTCON2bits.INT2EP = trigger & 2 ? FALLING_EDGE : RISING_EDGE; - RPINR1bits.INT2R = PIN_MANAGER_DIGITAL_PINS[(trigger >> 4) & 0xF]; - } - - INTERVAL_CaptureTwo(points, config, channel); - - if (trigger & 1) { - INTERRUPT_ClearExternalInterrupt2Flag(); - INTERRUPT_EnableExternalInterrupt2(); - } else { - SetDefaultDIGITAL_STATES(); - IC_PARAMS_ManualTriggerAll(); - SetDefaultDIGITAL_STATES_ERROR(); - } - - return SUCCESS; - - // TODO: Implement trigger actions for any of the two channels. Right now - // only one channel can be set as trigger source. Using CN interrupts, this - // can be extended to listen to multiple trigger sources. -} - -response_t LOGICANALYZER_ThreeChannel(void) { - - uint16_t points = UART1_ReadInt(); - uint8_t config = UART1_ReadInt(); - uint8_t trigger = UART1_Read(); - - IC4_InterruptHighPriority(); - IC4_InterruptFlagClear(); - IC4_InterruptDisable(); - - if (trigger & 7) { - INTERVAL_CaptureThree(points, config & 0x0FFF, trigger); - IC4_InterruptEnable(); - } else { - INTERVAL_CaptureThree(points, config & 0x0FFF, 0); - SetDefaultDIGITAL_STATES(); - IC1_ManualTriggerSet(); - IC2_ManualTriggerSet(); - IC3_ManualTriggerSet(); - SetDefaultDIGITAL_STATES_ERROR(); - } - - return SUCCESS; - - // TODO: Implement trigger actions for any of the three channels. Right now - // only one channel can be set as trigger source. Using CN interrupts, this - // can be extended to listen to multiple trigger sources. -} - -response_t LOGICANALYZER_FourChannel(void) { - - uint16_t points = UART1_ReadInt(); - uint16_t mode = UART1_ReadInt(); - uint8_t prescaler = UART1_Read(); - uint8_t trigger = UART1_Read(); - - SetDIGITAL_STATES(0); - INTERVAL_CaptureFour(points, mode, prescaler); - - if (trigger & 1) { - LA_TRIGGER_STATE = trigger & 2 ? RISING_EDGE : FALLING_EDGE; - LA_TRIGGER_CHANNEL = 0; - - if ((trigger >> 2) & 1) { - INTERRUPT_LA1PinChange(true); - LA_TRIGGER_CHANNEL |= 1; - } - if ((trigger >> 3) & 1) { - INTERRUPT_LA2PinChange(true); - LA_TRIGGER_CHANNEL |= 2; - } - if ((trigger >> 4) & 1) { - INTERRUPT_LA3PinChange(true); - LA_TRIGGER_CHANNEL |= 4; - } - if ((trigger >> 5) & 1) { - INTERRUPT_LA4PinChange(true); - LA_TRIGGER_CHANNEL |= 8; - } - INTERRUPT_ClearPinChangeInterruptsFlag(); - INTERRUPT_EnablePinChangeInterrupts(); - } else { - TMR2_Start(); - SetDefaultDIGITAL_STATES(); - IC_PARAMS_ManualTriggerAll(); - SetDefaultDIGITAL_STATES_ERROR(); - } - - return SUCCESS; -} - -response_t LOGICANALYZER_Stop(void) { - - IC_PARAMS_DisableAllModules(); - - return SUCCESS; -} diff --git a/src/instruments/logicanalyzer.h b/src/instruments/logicanalyzer.h deleted file mode 100644 index dfdf1d6..0000000 --- a/src/instruments/logicanalyzer.h +++ /dev/null @@ -1,229 +0,0 @@ -#ifndef LOGICANALYZER_H -#define LOGICANALYZER_H - -#include "../commands.h" - -/** - * @brief Capture logic level changes on a single channel. - * - * @description - * This routine will log timer values for the changes occurred in a pin defined - * by the configuration byte. - * - * If a trigger is enabled, this will use an external interrupt service routine - * attached to a pin defined by the trigger byte. Once the logic level is observed - * to be the same as in EDGE bit, IC1 and IC2 modules will start the combined - * timer (32-bits) and pass them to BUFFER using first two DMA channels. - * - * If no trigger is set, the timers will be started right away once the function - * is called and logic level changes will logged referring to IC1 and IC2 capture - * timers in BUFFER using the same DMA channels. - * - * This command function takes three arguments over serial: - * 1. (uint16) number of data points to capture - * 2. (uint8) trigger conditions: - * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | - * | TRIGGER PIN | X | X | EDGE | EN | - * PIN: Digital pin from map: - * 0: LA1, - * 1: LA2, - * 2: LA3, - * 3: LA4, - * 4: COMP4, - * 5: SPI_CS, - * 6: FREQ - * EDGE: Falling (1) or Rising (0) edge trigger - * EN: Enable trigger - * 3. (uint8) channel and mode configurations: - * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | - * | DIGITAL PIN | TRANSITIONS | - * CHANNEL: Digital pin from the same map as above `PIN` maps - * MODE: Logic transitions to capture. Refer `IC_PARAMS_CAPTURE_MODE` - * - * The data captured from this method should be read using - * - * It returns nothing over serial. - * It sends an acknowledge byte (SUCCESS). - * - * @return SUCCESS - */ -response_t LOGICANALYZER_OneChannel(void); - -/** - * @brief Capture logic level changes in one channel - * - * @description - * This routine is much similar to `LOGICANALYZER_OneChannel` except the trigger - * is handled differently. If trigger is enabled, IC4 pin will be connected to a - * pin defined by the trigger byte and an ISR will be activated for IC4 module. - * This will trigger an interrupt when a logic change defined by the trigger byte - * is observed at the pin attached to IC4. At the same time, IC1 and IC2 start - * their timers and log timer values to BUFFER using DMA0 and DMA1 channels - * - * This command function takes three arguments over serial: - * 1. (uint16) number of data points to capture - * 2. (uint8) channel and mode configuration: - * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | - * | DIGITAL PIN | TRANSITIONS | - * 3. (uint8) trigger conditions: - * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | - * | TRIG PIN | X | TRIG MODE | - * PIN: Digital pin from map: - * 0: LA1, - * 1: LA2, - * 2: LA3, - * 3: LA4, - * 4: COMP4, - * 5: SPI_CS, - * 6: FREQ - * - * It returns nothing over serial. - * It sends an acknowledge byte (SUCCESS). - * - * @return SUCCESS - */ -response_t LOGICANALYZER_OneChannelAlt(void); - -/** - * @brief Capture logic level changes in two channels - * - * @description - * This routine will log timer values on logic level changes in two different - * pins defined by the channel byte. - * - * If a trigger is enabled, this will use an external interrupt service routine - * attached to a pin defined by trigger byte. Once the logic level is observed - * to be the same as in EDGE bit, All IC modules will start the combined - * timers (32-bits) and pass them to BUFFER using all four DMA channels. - * - * If no trigger is enabled, the timers will be started right away once the - * function is called and logic level changes will logged referring to IC1 and - * IC3 combined capture timers in BUFFER using the same DMA channels. - * - * This command function takes four arguments over serial: - * 1. (uint16) number of data points to capture - * 2. (uint8) trigger conditions: - * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | - * | TRIG PIN | X | X | EDGE | EN | - * PIN: Digital pin from map: - * 0: LA1, - * 1: LA2, - * 2: LA3, - * 3: LA4, - * 4: COMP4, - * 5: SPI_CS, - * 6: FREQ - * 3. (uint8) mode configurations: - * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | - * | PIN 2 MODES | PIN 1 MODES | - * 4. (uint8) channel configurations: - * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | - * | PIN 2 CHANNEL | PIN 1 CHANNEL | - * - * It returns nothing over serial. - * It sends an acknowledge byte (SUCCESS). - * - * @return SUCCESS - */ -response_t LOGICANALYZER_TwoChannel(void); - -/** - * @brief Capture logic level changes in three channels - * - * @description - * This routine will log timer values on logic level changes in LA1, LA2 and LA3 - * pins. These pins are fixed for this mode of operation. - * - * If a trigger is enabled, this will use IC4 module as a trigger source to start - * IC1, 2 and 3 timers. Once the logic level change as defined in trigger byte is - * observed at IC4, it will generate an interrupt that will turn on all IC1,2,3 - * timers which will capture logic level changes defined in configuration integer. - * IC modules will have 16-bit timers and the value is logged to BUFFER using - * three DMA channels. - * - * If no trigger is enabled, the timers will be started right away once the - * function is called and logic level changes will logged referring to IC1, 2 - * and IC3 combined capture timers in BUFFER using the same DMA channels. - * - * This command function takes three arguments over serial: - * 1. (uint16) number of data points to capture - * 2. (uint16) configurations: - * | F | E | D | C | B | A | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | - * | X | X | X | X | LA3 EDGES | LA2 EDGES | LA1 EDGES | - * 3. (uint8) trigger conditions: - * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | - * | TRIG PIN | X | TRIG MODE | - * PIN: Trig pin from map: - * 0: LA1, - * 1: LA2, - * 2: LA3, - * 3: LA4, - * 4: COMP4, - * 5: SPI_CS, - * 6: FREQ - * - * It returns nothing over serial. - * It sends an acknowledge byte (SUCCESS). - * - * @return SUCCESS - */ -response_t LOGICANALYZER_ThreeChannel(void); - -/** - * @brief Capture logic level changes in four channels - * - * @description - * This routine will log timer values on logic level changes in LA1, LA2, LA3 - * and LA4 pins. These pins are fixed for this mode of operation. - * - * If a trigger is enabled, this will use CN (Change Notifier) Interrupt Service - * Routine to trigger the IC timers to log logic level changes. If any of the 4 - * pins observe a logic change as defined in trigger byte, the timers will get - * started logging logic level changes in all 4 pins defined in the configuration - * integer. IC modules will have 16-bit timers and the value is logged to BUFFER - * using all four DMA channels. - * - * If no trigger is enabled, the timers will be started right away once the - * function is called and logic level changes will logged referring to IC1, IC2, - * IC3 and IC4 capture timers in BUFFER using the same DMA channels. - * - * This command function takes four arguments over serial: - * 1. (uint16) number of data points to capture - * 2. (uint16) mode configurations: - * | F | E | D | C | B | A | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | - * | LA4 EDGES | LA3 EDGES | LA2 EDGES | LA1 EDGES | - * 3. (uint8) pre-scaler settings for timer 2 - * 4. (uint8) trigger settings: - * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | - * | X | X | LA4 | LA3 | LA2 | LA1 | EDGE | EN | - * - * It returns nothing over serial. - * It sends an acknowledge byte (SUCCESS). - * - * @return SUCCESS - */ -response_t LOGICANALYZER_FourChannel(void); - -/** - * @brief Stop capture modules - * - * @description - * This command function does not take any arguments over serial. It will stop - * all the input capture modules. - * - * It returns nothing over serial. - * It sends an acknowledge byte (SUCCESS). - * - * @return SUCCESS - */ -response_t LOGICANALYZER_Stop(void); - -// Getters and setters - -void SetLA_TRIGGER_CHANNEL(uint8_t); -uint8_t GetLA_TRIGGER_CHANNEL(void); - -void SetLA_TRIGGER_STATE(uint8_t); -uint8_t GetLA_TRIGGER_STATE(void); - -#endif /* LOGICANALYZER_H */