Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for using a ws2812 led for DAP_STATUS #34

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions platform/rp2040/generated/ws2812.pio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// -------------------------------------------------- //
// This file is autogenerated by pioasm; do not edit! //
// -------------------------------------------------- //

#pragma once

#if !PICO_NO_HARDWARE
#include "hardware/pio.h"
#endif

// ------ //
// ws2812 //
// ------ //

#define ws2812_wrap_target 0
#define ws2812_wrap 3

#define ws2812_T1 2
#define ws2812_T2 5
#define ws2812_T3 3

static const uint16_t ws2812_program_instructions[] = {
// .wrap_target
0x6221, // 0: out x, 1 side 0 [2]
0x1123, // 1: jmp !x, 3 side 1 [1]
0x1400, // 2: jmp 0 side 1 [4]
0xa442, // 3: nop side 0 [4]
// .wrap
};

#if !PICO_NO_HARDWARE
static const struct pio_program ws2812_program = {
.instructions = ws2812_program_instructions,
.length = 4,
.origin = -1,
};

static inline pio_sm_config ws2812_program_get_default_config(uint offset) {
pio_sm_config c = pio_get_default_sm_config();
sm_config_set_wrap(&c, offset + ws2812_wrap_target, offset + ws2812_wrap);
sm_config_set_sideset(&c, 1, false, false);
return c;
}
#endif

6 changes: 6 additions & 0 deletions platform/rp2040/hal_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,20 @@
#include "hal_gpio.h"

/*- Definitions -------------------------------------------------------------*/
#define DAP_STATUS_USE_WS2812

HAL_GPIO_PIN(SWCLK_TCK, 0, 11, sio_11)
HAL_GPIO_PIN(SWDIO_TMS, 0, 12, sio_12)
HAL_GPIO_PIN(TDI, 0, 13, sio_13)
HAL_GPIO_PIN(TDO, 0, 14, sio_14)
HAL_GPIO_PIN(nRESET, 0, 15, sio_15)

HAL_GPIO_PIN(VCP_STATUS, 0, 2, sio_2);
#ifdef DAP_STATUS_USE_WS2812
HAL_GPIO_PIN(DAP_STATUS2, 0, 25, sio_25);
#else
HAL_GPIO_PIN(DAP_STATUS, 0, 25, sio_25);
#endif // DAP_STATUS_USE_WS2812

HAL_GPIO_PIN(UART_TX, 0, 0, uart0_tx)
HAL_GPIO_PIN(UART_RX, 0, 1, uart0_rx)
Expand Down
44 changes: 44 additions & 0 deletions platform/rp2040/include/hardware/pio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/

#ifndef _HARDWARE_PIO_H
#define _HARDWARE_PIO_H

typedef uint32_t uint;

typedef struct pio_program {
//typedef struct {
const uint16_t *instructions;
uint8_t length;
int8_t origin; // required instruction memory origin or -1
} pio_program;

typedef struct {
uint32_t clkdiv;
uint32_t execctrl;
uint32_t shiftctrl;
uint32_t pinctrl;
} pio_sm_config;

static inline pio_sm_config pio_get_default_sm_config(void) {
pio_sm_config c = {0, 0, 0, 0};
return c;
}

static inline void sm_config_set_wrap(pio_sm_config *c, uint wrap_target, uint wrap) {
(void) c; // silence unused parameter warning
(void) wrap_target; // silence unused parameter warning
(void) wrap; // silence unused parameter warning
}

static inline void sm_config_set_sideset(pio_sm_config *c, uint bit_count, bool optional, bool pindirs) {
(void) c; // silence unused parameter warning
(void) bit_count; // silence unused parameter warning
(void) optional; // silence unused parameter warning
(void) pindirs; // silence unused parameter warning
}

#endif // _PIO_H_
59 changes: 59 additions & 0 deletions platform/rp2040/include/ws2812_pio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2021, Alex Taradov <[email protected]>. All rights reserved.

#ifndef _WS2812_PIO_H_
#define _WS2812_PIO_H_

#ifdef DAP_STATUS_USE_WS2812
//- Definitions ---------------------------------------------------------------

// color pattern ---------> 0xGGRRBB00
#define WS2812_COLOR_SET 0x02060000
#define WS2812_COLOR_CLR 0x00020200

void pio_init(uint32_t f_cpu);

//- Variables -----------------------------------------------------------------
static bool DAP_STATUS_is_set = false;

//- Implementations -----------------------------------------------------------

//-----------------------------------------------------------------------------
static inline void HAL_GPIO_DAP_STATUS_out(void)
{
HAL_GPIO_DAP_STATUS2_out();
(void)HAL_GPIO_DAP_STATUS_out;
}

//-----------------------------------------------------------------------------
static inline void HAL_GPIO_DAP_STATUS_set(void)
{
HAL_GPIO_DAP_STATUS2_set();
PIO0->TXF0 = WS2812_COLOR_SET;
DAP_STATUS_is_set = true;
(void)HAL_GPIO_DAP_STATUS_set;
}

//-----------------------------------------------------------------------------
static inline void HAL_GPIO_DAP_STATUS_clr(void)
{
HAL_GPIO_DAP_STATUS2_clr();
PIO0->TXF0 = WS2812_COLOR_CLR;
DAP_STATUS_is_set = false;
(void)HAL_GPIO_DAP_STATUS_clr;
}

//-----------------------------------------------------------------------------
static inline void HAL_GPIO_DAP_STATUS_toggle(void)
{
HAL_GPIO_DAP_STATUS2_toggle();
if (DAP_STATUS_is_set) {
HAL_GPIO_DAP_STATUS_clr();
} else {
HAL_GPIO_DAP_STATUS_set();
}
(void)HAL_GPIO_DAP_STATUS_toggle;
}
#endif // DAP_STATUS_USE_WS2812

#endif // _WS2812_PIO_H_
4 changes: 4 additions & 0 deletions platform/rp2040/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "uart.h"
#include "dap.h"
#include "dap_config.h"
#include "ws2812_pio.h"

/*- Definitions -------------------------------------------------------------*/
#define USB_BUFFER_SIZE 64
Expand Down Expand Up @@ -355,6 +356,9 @@ int main(void)
usb_cdc_init();
usb_hid_init();
serial_number_init();
#ifdef DAP_STATUS_USE_WS2812
pio_init(F_CPU);
#endif

app_status_timeout = STATUS_TIMEOUT;

Expand Down
8 changes: 6 additions & 2 deletions platform/rp2040/make/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ BIN = free_dap_rp2040
CC = arm-none-eabi-gcc
OBJCOPY = arm-none-eabi-objcopy
SIZE = arm-none-eabi-size
BIN2UF2 = bin2uf2
## BIN2UF2 = bin2uf2
BIN2UF2 = ./bin2uf2.exe

ifeq ($(OS), Windows_NT)
MKDIR = gmkdir
## MKDIR = gmkdir
MKDIR = mkdir
else
MKDIR = mkdir
endif
Expand All @@ -33,6 +35,7 @@ INCLUDES += \
-I../include \
-I../usb \
-I../../.. \
-I../generated \
-I..

SRCS += \
Expand All @@ -45,6 +48,7 @@ SRCS += \
../usb/usb_winusb.c \
../usb_descriptors.c \
../startup_rp2040.c \
../ws2812_pio.c \
../../../dap.c \

DEFINES += \
Expand Down
24 changes: 24 additions & 0 deletions platform/rp2040/ws2812.pio
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
;
; Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
;
; SPDX-License-Identifier: BSD-3-Clause
;

// based on Pico-v1.5.1-Examples/pico-examples/pio/ws28127ws2812.pio

.program ws2812
.side_set 1

.define public T1 2
.define public T2 5
.define public T3 3

.wrap_target
bitloop:
out x, 1 side 0 [T3 - 1] ; Side-set still takes place when instruction stalls
jmp !x do_zero side 1 [T1 - 1] ; Branch on the bit we shifted out. Positive pulse
do_one:
jmp bitloop side 1 [T2 - 1] ; Continue driving high, for a long pulse
do_zero:
nop side 0 [T2 - 1] ; Or drive low, for a short pulse
.wrap
69 changes: 69 additions & 0 deletions platform/rp2040/ws2812_pio.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2021, Alex Taradov <[email protected]>. All rights reserved.

//- Includes ------------------------------------------------------------------
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include "rp2040.h"
#include "ws2812.pio.h"

//- Definitions ---------------------------------------------------------------
#define F_WS2812 800000 // 800 kHz for ws2812
#define WS2812_LOOP_CYCLES (ws2812_T1 + ws2812_T2 + ws2812_T3)

//- Variables -----------------------------------------------------------------

//- Implementations -----------------------------------------------------------

//-----------------------------------------------------------------------------
void pio_init(uint32_t f_cpu)
{
//Life with David - BMA Chapter 06 - Demo 1 - PIO blink with PLL clock

// Enable pio0
RESETS_CLR->RESET = RESETS_RESET_pio0_Msk;
while (0 == RESETS->RESET_DONE_b.pio0);

// Upload pio program to instruction memory
volatile uint32_t *instr_mem = &PIO0->INSTR_MEM0; // = start of the pio0 program memory
for (uint32_t i = 0; i < ws2812_program.length; i++) {
uint16_t instr = ws2812_program_instructions[i];
*instr_mem++ = instr;
}

// Enable output for GPIO16 and connect to pio0
IO_BANK0->GPIO16_CTRL = 0;
IO_BANK0->GPIO16_CTRL_b.OEOVER = IO_BANK0_GPIO16_CTRL_OEOVER_ENABLE;
IO_BANK0->GPIO16_CTRL_b.FUNCSEL = IO_BANK0_GPIO16_CTRL_FUNCSEL_pio0_16;

// Setting gpio16 as sideset base and 1 pin
PIO0->SM0_PINCTRL = 0;
PIO0->SM0_PINCTRL_b.SIDESET_BASE = 16;
PIO0->SM0_PINCTRL_b.SIDESET_COUNT = 1;

// Set up clock divider
PIO0->SM0_CLKDIV = 0;
PIO0->SM0_CLKDIV_b.INT = f_cpu / (F_WS2812 * WS2812_LOOP_CYCLES);

// Set up wrapping
PIO0->SM0_EXECCTRL = 0;
PIO0->SM0_EXECCTRL_b.WRAP_BOTTOM = 0;
PIO0->SM0_EXECCTRL_b.WRAP_TOP = 3;

// Set up autopull
PIO0->SM0_SHIFTCTRL = 0;
PIO0->SM0_SHIFTCTRL_b.OUT_SHIFTDIR = 0; // shift out of output shift register to left
PIO0->SM0_SHIFTCTRL_b.AUTOPULL = 1; // pull automatically
PIO0->SM0_SHIFTCTRL_b.PULL_THRESH = 24; // number of bits shifted out of OSR before autopull

// Cleanly start state machine
PIO0->CTRL = 0;
PIO0->CTRL_b.SM_RESTART = 1; // restart SM0
PIO0->CTRL_b.CLKDIV_RESTART = 1; // restart the clock

PIO0->SM0_INSTR_b.SM0_INSTR = 0; // forced jump to start of PIO program

PIO0->CTRL_b.SM_ENABLE = 1; // enable SM0
}