Add I2C communication. Start writing DMX TX. Break generation already implemented
This commit is contained in:
		
							
								
								
									
										7
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -3,3 +3,10 @@
 | 
			
		||||
*.elf
 | 
			
		||||
*.lss
 | 
			
		||||
*.d
 | 
			
		||||
 | 
			
		||||
*.jdebug
 | 
			
		||||
*.jdebug.user
 | 
			
		||||
 | 
			
		||||
# ClangD Ignopre files
 | 
			
		||||
.cache/*
 | 
			
		||||
compile_commands.json
 | 
			
		||||
							
								
								
									
										8
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								Makefile
									
									
									
									
									
								
							@@ -11,7 +11,9 @@ endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#Add Files and Folders below#########################################################
 | 
			
		||||
CFILES 	= main.c setup/system_init.c startup/startup_stm32f0xx.c systick.c
 | 
			
		||||
CFILES 	:= main.c setup/system_init.c startup/startup_stm32f0xx.c systick.c
 | 
			
		||||
CFILES += i2c.c
 | 
			
		||||
CFILES += dmx.c
 | 
			
		||||
ASFILES = 
 | 
			
		||||
INCLUDEPATH = -Iinclude -Iinclude/cmsis
 | 
			
		||||
 | 
			
		||||
@@ -35,11 +37,11 @@ OBJCOPY := $(CROSS_COMPILE)objcopy
 | 
			
		||||
OBJDUMP := $(CROSS_COMPILE)objdump
 | 
			
		||||
SIZE := $(CROSS_COMPILE)size
 | 
			
		||||
 | 
			
		||||
LFLAGS = -mlittle-endian -mthumb -mcpu=cortex-m0 -mthumb-interwork 
 | 
			
		||||
LFLAGS = -mlittle-endian -mthumb -mcpu=cortex-m0
 | 
			
		||||
LFLAGS += -mfloat-abi=soft --disable-newlib-supplied-syscalls -nostartfiles
 | 
			
		||||
LFLAGS += -Tstartup/stm32f030.ld -Wl,-Map=$(mapfile).map -Wl,--gc-sections -Wl,--print-memory-usage -g
 | 
			
		||||
 | 
			
		||||
CFLAGS = -c -fmessage-length=0 -mlittle-endian -mthumb -mcpu=cortex-m0 -mthumb-interwork
 | 
			
		||||
CFLAGS = -c -fmessage-length=0 -mlittle-endian -mthumb -mcpu=cortex-m0
 | 
			
		||||
CFLAGS += -mfloat-abi=soft -nostartfiles -Wall -g3 -O0
 | 
			
		||||
 | 
			
		||||
####################################################################################
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										134
									
								
								dmx.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								dmx.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,134 @@
 | 
			
		||||
#include "stm32f030x6.h"
 | 
			
		||||
#include <dmx.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stm32f0xx.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stm-periph/stm32-gpio-macros.h>
 | 
			
		||||
 | 
			
		||||
static GPIO_TypeDef *dmx_tx_port;
 | 
			
		||||
static uint8_t dmx_tx_pin;
 | 
			
		||||
static uint32_t dmx_universe_length;
 | 
			
		||||
static uint8_t *dmx_data_ptr;
 | 
			
		||||
static uint16_t dmx_tx_break_len;
 | 
			
		||||
static uint16_t dmx_tx_break_pause;
 | 
			
		||||
 | 
			
		||||
enum dmx_tx_state {
 | 
			
		||||
	DMX_TX_OFF,
 | 
			
		||||
	DMX_TX_IDLE,
 | 
			
		||||
	DMX_TX_BREAK,
 | 
			
		||||
	DMX_TX_BREAK_PAUSE,
 | 
			
		||||
	DMX_TX_NULLBYTE,
 | 
			
		||||
	DMX_TX_DATA,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static volatile enum dmx_tx_state tx_state;
 | 
			
		||||
 | 
			
		||||
/* USART1 TX is mapped on DMA Channel2 */
 | 
			
		||||
 | 
			
		||||
static void dmx_break(bool break_enable)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t tmp;
 | 
			
		||||
 | 
			
		||||
	/* Force pin to low */
 | 
			
		||||
	dmx_tx_port->BSRR |= (1 << (dmx_tx_pin + 16));
 | 
			
		||||
	
 | 
			
		||||
	/* Change pin mode from alternate function (UART) to output and vice versa */
 | 
			
		||||
	tmp = dmx_tx_port->MODER;
 | 
			
		||||
	if (break_enable) {
 | 
			
		||||
		tmp &= MODER_DELETE(dmx_tx_pin);
 | 
			
		||||
		tmp |= OUTPUT(dmx_tx_pin);
 | 
			
		||||
	} else {
 | 
			
		||||
		tmp &= MODER_DELETE(dmx_tx_pin);
 | 
			
		||||
		tmp |= ALTFUNC(dmx_tx_pin);
 | 
			
		||||
	}
 | 
			
		||||
	dmx_tx_port->MODER = tmp;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void dmx_init(uint8_t *data, uint32_t universe_length, GPIO_TypeDef *tx_port, uint8_t tx_pin,
 | 
			
		||||
		uint16_t dmx_delay, uint16_t dmx_break_len, uint16_t break_pause)
 | 
			
		||||
{
 | 
			
		||||
	dmx_tx_pin = tx_pin;
 | 
			
		||||
	dmx_tx_port = tx_port;
 | 
			
		||||
	dmx_data_ptr = data;
 | 
			
		||||
	dmx_tx_break_len = dmx_break_len;
 | 
			
		||||
	dmx_tx_break_pause = break_pause;
 | 
			
		||||
 | 
			
		||||
	/* Enable UART1 and TIM14 clock */
 | 
			
		||||
	RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
 | 
			
		||||
	RCC->APB1ENR |= RCC_APB1ENR_TIM14EN;
 | 
			
		||||
 | 
			
		||||
	/* Enable DMA clock */
 | 
			
		||||
	RCC->AHBENR |= RCC_AHBENR_DMAEN;
 | 
			
		||||
 | 
			
		||||
	/* Set baudrate: 48MHz / 250k = 129 */
 | 
			
		||||
	USART1->BRR = 192u;
 | 
			
		||||
 | 
			
		||||
	/* Two stop bits */
 | 
			
		||||
	USART1->CR2 = USART_CR2_STOP_1;
 | 
			
		||||
 | 
			
		||||
	/* Transmitter enable, USART enable */
 | 
			
		||||
	USART1->CR1 = USART_CR1_TE | USART_CR1_UE;
 | 
			
		||||
	
 | 
			
		||||
	/* Configure TIM14 to count in 10 us steps */
 | 
			
		||||
	TIM14->PSC = 480u;
 | 
			
		||||
 | 
			
		||||
	/* Configure the reload value. Must be higher or equal to 200 */
 | 
			
		||||
	if (dmx_delay < 2000)
 | 
			
		||||
		dmx_delay = 2000;
 | 
			
		||||
	TIM14->ARR = dmx_delay - 1;
 | 
			
		||||
 | 
			
		||||
	/* Enable TIM14 interrupt on update */
 | 
			
		||||
	TIM14->DIER = TIM_DIER_UIE | TIM_DIER_CC1IE;
 | 
			
		||||
	NVIC_EnableIRQ(TIM14_IRQn);
 | 
			
		||||
 | 
			
		||||
	
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dmx_stream_start(void)
 | 
			
		||||
{
 | 
			
		||||
	tx_state = DMX_TX_IDLE;
 | 
			
		||||
	TIM14->CR1 |= TIM_CR1_CEN;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dmx_stream_stop(void)
 | 
			
		||||
{
 | 
			
		||||
	tx_state = DMX_TX_OFF;
 | 
			
		||||
	TIM14->CR1 &= ~TIM_CR1_CEN;
 | 
			
		||||
	DMA1_Channel2->CCR = 0ul;
 | 
			
		||||
	__DSB();
 | 
			
		||||
	USART1->CR3 = 0ul;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void TIM14_IRQHandler(void)
 | 
			
		||||
{
 | 
			
		||||
	/* Clear interrupt sources */
 | 
			
		||||
	TIM14->SR = 0;
 | 
			
		||||
 | 
			
		||||
	/* Start the break sequence if idle */
 | 
			
		||||
	switch (tx_state) {
 | 
			
		||||
	case DMX_TX_IDLE:
 | 
			
		||||
		tx_state = DMX_TX_BREAK;
 | 
			
		||||
		/* Disable the DMA transfer */
 | 
			
		||||
		USART1->CR3 = 0ul;
 | 
			
		||||
 | 
			
		||||
		TIM14->CCR1 = dmx_tx_break_len;
 | 
			
		||||
 | 
			
		||||
		/* Send break */
 | 
			
		||||
		dmx_break(true);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case DMX_TX_BREAK:
 | 
			
		||||
		/* Stop break pulse */
 | 
			
		||||
		dmx_break(false);
 | 
			
		||||
		TIM14->CCR1 = dmx_tx_break_len + dmx_tx_break_pause;
 | 
			
		||||
		tx_state = DMX_TX_BREAK_PAUSE;
 | 
			
		||||
		break;
 | 
			
		||||
	case DMX_TX_BREAK_PAUSE:
 | 
			
		||||
		tx_state = DMX_TX_IDLE;
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										138
									
								
								i2c.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								i2c.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,138 @@
 | 
			
		||||
#include "stm32f030x6.h"
 | 
			
		||||
#include <i2c.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
void i2c_init(void)
 | 
			
		||||
{
 | 
			
		||||
	RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
 | 
			
		||||
 | 
			
		||||
	/* Use SYSCLK for I2C, because HSI (default) is disabled */
 | 
			
		||||
	RCC->CFGR3 |= RCC_CFGR3_I2C1SW;
 | 
			
		||||
 | 
			
		||||
	i2c_reset();
 | 
			
		||||
 | 
			
		||||
	/* Setup clocks */
 | 
			
		||||
	I2C1->TIMINGR = ((6 << 28) & I2C_TIMINGR_PRESC) | ((8 << 20) & I2C_TIMINGR_SCLDEL) |
 | 
			
		||||
			((8 << 16) & I2C_TIMINGR_SDADEL) | ((0x20 << 8) & I2C_TIMINGR_SCLH) |
 | 
			
		||||
			((0x20 << 0) & I2C_TIMINGR_SCLL);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	/* Peripheral enable */
 | 
			
		||||
	I2C1->CR1 = I2C_CR1_PE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int i2c_write(uint8_t i2c_addr, const uint8_t *data, uint8_t len)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t isr;
 | 
			
		||||
 | 
			
		||||
	/* Clear stop flag */
 | 
			
		||||
	I2C1->ICR |= I2C_ICR_STOPCF;
 | 
			
		||||
 | 
			
		||||
	/* Setup len bytes for write transfer */
 | 
			
		||||
	I2C1->CR2 = I2C_CR2_AUTOEND | ((len << 16 ) & I2C_CR2_NBYTES) | (i2c_addr & 0xFE) | I2C_CR2_START;
 | 
			
		||||
	
 | 
			
		||||
	do {
 | 
			
		||||
		isr = I2C1->ISR;
 | 
			
		||||
		if (isr & I2C_ISR_NACKF) {
 | 
			
		||||
			/* NACK received */
 | 
			
		||||
			return -1;
 | 
			
		||||
		} else if (isr & I2C_ISR_TXIS) {
 | 
			
		||||
			/* I2C ready to get data to send */
 | 
			
		||||
			I2C1->TXDR = (uint32_t)*data;
 | 
			
		||||
			data++;
 | 
			
		||||
			len--;
 | 
			
		||||
		}
 | 
			
		||||
	} while (len > 0);
 | 
			
		||||
 | 
			
		||||
	/* All data transferred. Wait for automatically generated stop */
 | 
			
		||||
	while (!(I2C1->ISR & I2C_ISR_STOPF)) {
 | 
			
		||||
		if (I2C1->ISR & I2C_ISR_NACKF) {
 | 
			
		||||
			return -1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Clear stop flag */
 | 
			
		||||
	I2C1->ICR |= I2C_ICR_STOPCF;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int i2c_read(uint8_t i2c_addr, uint8_t command, uint8_t *data, uint8_t len)
 | 
			
		||||
{
 | 
			
		||||
	int run;
 | 
			
		||||
	int err;
 | 
			
		||||
	uint32_t isr;
 | 
			
		||||
 | 
			
		||||
	if (!data || !len) {
 | 
			
		||||
		return -1000;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Clear stop flag */
 | 
			
		||||
	I2C1->ICR |= I2C_ICR_STOPCF;
 | 
			
		||||
 | 
			
		||||
	/* Setup len bytes for write transfer  of command */
 | 
			
		||||
	I2C1->CR2 = ((1 << 16 ) & I2C_CR2_NBYTES) | (i2c_addr & 0xFE) | I2C_CR2_START;
 | 
			
		||||
 | 
			
		||||
	err = 0;
 | 
			
		||||
	run = 1;
 | 
			
		||||
	do {
 | 
			
		||||
		isr = I2C1->ISR;
 | 
			
		||||
 | 
			
		||||
		if (isr & I2C_ISR_NACKF) {
 | 
			
		||||
			err = 1;
 | 
			
		||||
			run = 0;
 | 
			
		||||
		} else if (isr & I2C_ISR_TXIS) {
 | 
			
		||||
			I2C1->TXDR = (uint32_t)command;
 | 
			
		||||
			run = 0;
 | 
			
		||||
		}
 | 
			
		||||
	} while (run);
 | 
			
		||||
 | 
			
		||||
	if (err) {
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Wait for command to be transmitted */
 | 
			
		||||
	run = 1;
 | 
			
		||||
	err = 0;
 | 
			
		||||
	do {
 | 
			
		||||
		isr = I2C1->ISR;
 | 
			
		||||
 | 
			
		||||
		if (isr & I2C_ISR_NACKF) {
 | 
			
		||||
			err = 1;
 | 
			
		||||
			run = 0;
 | 
			
		||||
		} else if (isr & I2C_ISR_TC) {
 | 
			
		||||
			run = 0;
 | 
			
		||||
		}
 | 
			
		||||
	} while (run);
 | 
			
		||||
 | 
			
		||||
	if (err) {
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Setup read request */
 | 
			
		||||
	I2C1->CR2 = I2C_CR2_AUTOEND | I2C_CR2_RD_WRN | ((len << 16 ) & I2C_CR2_NBYTES) | (i2c_addr & 0xFE) | I2C_CR2_START;
 | 
			
		||||
	while (len) {
 | 
			
		||||
		if (I2C1->ISR & I2C_ISR_RXNE) {
 | 
			
		||||
			*data = I2C1->RXDR;
 | 
			
		||||
			data++;
 | 
			
		||||
			len--;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	while (!(I2C1->ISR & I2C_ISR_STOPF)) {
 | 
			
		||||
		if (I2C1->ISR & I2C_ISR_NACKF) {
 | 
			
		||||
			return -1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Clear stop flag */
 | 
			
		||||
	I2C1->ICR |= I2C_ICR_STOPCF;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void i2c_reset(void)
 | 
			
		||||
{
 | 
			
		||||
	I2C1->CR1 = 0;
 | 
			
		||||
	I2C1->CR2 = 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										14
									
								
								include/dmx.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								include/dmx.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
#ifndef _DMX_H_
 | 
			
		||||
#define _DMX_H_
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void dmx_init(uint8_t *data, uint32_t universe_length, GPIO_TypeDef *tx_port, uint8_t tx_pin,
 | 
			
		||||
		uint16_t dmx_delay, uint16_t dmx_break_len, uint16_t break_pause);
 | 
			
		||||
		
 | 
			
		||||
void dmx_stream_start(void);
 | 
			
		||||
 | 
			
		||||
void dmx_stream_stop(void);
 | 
			
		||||
 | 
			
		||||
#endif /* _DMX_H_ */
 | 
			
		||||
							
								
								
									
										14
									
								
								include/i2c.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								include/i2c.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
#ifndef _I2C_H_
 | 
			
		||||
#define _I2C_H_
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
void i2c_init(void);
 | 
			
		||||
 | 
			
		||||
void i2c_reset(void);
 | 
			
		||||
 | 
			
		||||
int i2c_write(uint8_t i2c_addr, const uint8_t *data, uint8_t len);
 | 
			
		||||
 | 
			
		||||
int i2c_read(uint8_t i2c_addr, uint8_t command, uint8_t *data, uint8_t len);
 | 
			
		||||
 | 
			
		||||
#endif /* _I2C_H_ */
 | 
			
		||||
							
								
								
									
										55
									
								
								main.c
									
									
									
									
									
								
							
							
						
						
									
										55
									
								
								main.c
									
									
									
									
									
								
							@@ -1,6 +1,21 @@
 | 
			
		||||
#include <i2c.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stm32f0xx.h>
 | 
			
		||||
#include <stm-periph/stm32-gpio-macros.h>
 | 
			
		||||
#include <systick.h>
 | 
			
		||||
#include <dmx.h>
 | 
			
		||||
 | 
			
		||||
#define PCA9555_ADDR (0x40)
 | 
			
		||||
#define PCA9555_REG_IN_PORT0 (0x0)
 | 
			
		||||
#define PCA9555_REG_IN_PORT1 (0x1)
 | 
			
		||||
#define PCA9555_REG_OUT_PORT0 (0x2)
 | 
			
		||||
#define PCA9555_REG_OUT_PORT1 (0x3)
 | 
			
		||||
#define PCA9555_REG_POLARITY0 (0x4)
 | 
			
		||||
#define PCA9555_REG_POLARITY1 (0x5)
 | 
			
		||||
#define PCA9555_REG_CONFIG0 (0x6)
 | 
			
		||||
#define PCA9555_REG_CONFIG1 (0x7)
 | 
			
		||||
 | 
			
		||||
static uint8_t dmx_universe[129];
 | 
			
		||||
 | 
			
		||||
static void setup_pins(void)
 | 
			
		||||
{
 | 
			
		||||
@@ -45,14 +60,50 @@ static void setup_pins(void)
 | 
			
		||||
 | 
			
		||||
int main(void)
 | 
			
		||||
{
 | 
			
		||||
	uint8_t i2c_command[2];
 | 
			
		||||
	uint8_t port;
 | 
			
		||||
	uint32_t odr;
 | 
			
		||||
 | 
			
		||||
	setup_pins();
 | 
			
		||||
	i2c_init();
 | 
			
		||||
	dmx_init(dmx_universe, sizeof(dmx_universe), GPIOA, 2u, 2300u, 10u, 5u);
 | 
			
		||||
 | 
			
		||||
	/* Setup Systick for 1ms ticks */
 | 
			
		||||
	SysTick_Config(48000000UL/1000);
 | 
			
		||||
	
 | 
			
		||||
	GPIOA->ODR |= (1<<5) | (1<<7);
 | 
			
		||||
 | 
			
		||||
	/* Setup PCA */
 | 
			
		||||
	i2c_command[0] = PCA9555_REG_CONFIG1;
 | 
			
		||||
	i2c_command[1] = 0x00;
 | 
			
		||||
	i2c_write(PCA9555_ADDR, i2c_command, 2u);
 | 
			
		||||
 | 
			
		||||
	i2c_command[0] = PCA9555_REG_CONFIG0;
 | 
			
		||||
	i2c_command[1] = 0xFF;
 | 
			
		||||
	i2c_write(PCA9555_ADDR, i2c_command, 2u);
 | 
			
		||||
 | 
			
		||||
	dmx_stream_start();
 | 
			
		||||
 | 
			
		||||
	/* Blink the LEDs */	
 | 
			
		||||
	while (1) {
 | 
			
		||||
		systick_wait_ms(250);
 | 
			
		||||
		GPIOA->ODR ^= (1 << 5) | (1 << 6) | (1 << 7);
 | 
			
		||||
		systick_wait_ms(3);
 | 
			
		||||
		i2c_read(PCA9555_ADDR, PCA9555_REG_IN_PORT0, &port, 1u);
 | 
			
		||||
		i2c_command[0] = PCA9555_REG_OUT_PORT1;
 | 
			
		||||
		i2c_command[1] = ~port;
 | 
			
		||||
		odr = GPIOA->ODR;
 | 
			
		||||
		odr &= ~((1<<5) | (1<<6) | (1<<7));
 | 
			
		||||
		if (port & (1<<0)) {
 | 
			
		||||
			odr |= (1<<5);
 | 
			
		||||
		}
 | 
			
		||||
		if (port & (1<<1)) {
 | 
			
		||||
			odr |= (1<<6);
 | 
			
		||||
		}
 | 
			
		||||
		if (port & (1<<2)) {
 | 
			
		||||
			odr |= (1<<7);
 | 
			
		||||
		}
 | 
			
		||||
		GPIOA->ODR = odr;
 | 
			
		||||
 | 
			
		||||
		i2c_write(PCA9555_ADDR, i2c_command, 2u);
 | 
			
		||||
		
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user