Added ADC and rotary encoder functions
This commit is contained in:
parent
4173c08c95
commit
2e6026421e
@ -10,6 +10,8 @@
|
|||||||
#include "Taster.h"
|
#include "Taster.h"
|
||||||
#include "Timer.h"
|
#include "Timer.h"
|
||||||
#include "Led.h"
|
#include "Led.h"
|
||||||
|
#include "adc.h"
|
||||||
|
#include "rotaryEncoder.h"
|
||||||
|
|
||||||
|
|
||||||
//================================================================================================================================
|
//================================================================================================================================
|
||||||
@ -17,8 +19,6 @@
|
|||||||
//================================================================================================================================
|
//================================================================================================================================
|
||||||
#define COUNT_COMMANDS ( sizeof(command) / sizeof(command[0]) )
|
#define COUNT_COMMANDS ( sizeof(command) / sizeof(command[0]) )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define CHAR_DEL 0x7F
|
#define CHAR_DEL 0x7F
|
||||||
#define CHAR_BACKSPACE 0x08
|
#define CHAR_BACKSPACE 0x08
|
||||||
#define CHAR_CR 0x0D
|
#define CHAR_CR 0x0D
|
||||||
@ -52,6 +52,8 @@ static void cmd_taster(const char* _data);
|
|||||||
static void cmd_led_on(const char* _data);
|
static void cmd_led_on(const char* _data);
|
||||||
static void cmd_led_off(const char* _data);
|
static void cmd_led_off(const char* _data);
|
||||||
static void cmd_alert(const char* _data);
|
static void cmd_alert(const char* _data);
|
||||||
|
static void cmd_adc(const char* _data);
|
||||||
|
static void cmd_rotary(const char* _data);
|
||||||
|
|
||||||
//================================================================================================================================
|
//================================================================================================================================
|
||||||
// command-Tabelle
|
// command-Tabelle
|
||||||
@ -65,6 +67,8 @@ const struct {
|
|||||||
{"BUTTON", &cmd_taster, "Current State of the Buttons"},
|
{"BUTTON", &cmd_taster, "Current State of the Buttons"},
|
||||||
{"LED_ON $LED", &cmd_led_on, "Turn on the LED on position $LED"},
|
{"LED_ON $LED", &cmd_led_on, "Turn on the LED on position $LED"},
|
||||||
{"LED_OFF $LED", &cmd_led_off, "Turn off the LED on position $LED"},
|
{"LED_OFF $LED", &cmd_led_off, "Turn off the LED on position $LED"},
|
||||||
|
{"ADC", &cmd_adc, "Read the ADC output"},
|
||||||
|
{"ROTARY", &cmd_rotary, "Read the rotary encoder"},
|
||||||
{"ALERT", &cmd_alert, "RING THE ALTER!!!"},
|
{"ALERT", &cmd_alert, "RING THE ALTER!!!"},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -239,12 +243,16 @@ static void cmd_help(const char* _data){
|
|||||||
// Rückgabewert: keine
|
// Rückgabewert: keine
|
||||||
//================================================================================================================================
|
//================================================================================================================================
|
||||||
static void cmd_taster(const char* _data){
|
static void cmd_taster(const char* _data){
|
||||||
|
print_string("Taster 1: ");
|
||||||
print_string(Taster1_get() ? "1" : "0");
|
print_string(Taster1_get() ? "1" : "0");
|
||||||
print_string(NEXT_LINE);
|
print_string(NEXT_LINE);
|
||||||
|
print_string("Taster 2: ");
|
||||||
print_string(Taster2_get() ? "1" : "0");
|
print_string(Taster2_get() ? "1" : "0");
|
||||||
print_string(NEXT_LINE);
|
print_string(NEXT_LINE);
|
||||||
|
print_string("Taster 3: ");
|
||||||
print_string(Taster3_get() ? "1" : "0");
|
print_string(Taster3_get() ? "1" : "0");
|
||||||
print_string(NEXT_LINE);
|
print_string(NEXT_LINE);
|
||||||
|
print_string("Taster 4: ");
|
||||||
print_string(Taster4_get() ? "1" : "0");
|
print_string(Taster4_get() ? "1" : "0");
|
||||||
print_string(NEXT_LINE);
|
print_string(NEXT_LINE);
|
||||||
}
|
}
|
||||||
@ -329,3 +337,68 @@ static void cmd_alert(const char* _data){
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//================================================================================================================================
|
||||||
|
// Funktion: cmd_adc
|
||||||
|
// Wird verwendet um die Daten von Poti und LM35 zu lesen
|
||||||
|
// Parameter: _data: Zeichenkette mit Parametern des Befehls.
|
||||||
|
//
|
||||||
|
// Rückgabewert: keine
|
||||||
|
//================================================================================================================================
|
||||||
|
static void cmd_adc(const char* _data){
|
||||||
|
char potiData[50];
|
||||||
|
char lm35Data[50];
|
||||||
|
int loopInterval = 500;
|
||||||
|
|
||||||
|
int repeat = strcmp(_data, "R") == 0 ? 1 : 0; /* Check if repeat flag is set*/
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if(Timer_getTick() - g_startMS >= loopInterval){
|
||||||
|
g_startMS=Timer_getTick();
|
||||||
|
|
||||||
|
// Print Potentiometer info
|
||||||
|
sprintf(potiData, "Poti: %d", adc_get_poti());
|
||||||
|
//sprintf(potiData, "Poti: %f", (adc_get_poti() / 1023.0)); // uses floats - disabled for performance reasons.
|
||||||
|
print_string(potiData);
|
||||||
|
print_string(NEXT_LINE);
|
||||||
|
|
||||||
|
// Print LM35 temperature
|
||||||
|
sprintf(lm35Data, "LM35: %d\xC2\xB0 C", (int)(adc_get_LM35() * (5000 / 1024) / 10));
|
||||||
|
//sprintf(lm35Data, "LM35: %f\xC2\xB0 C", (adc_get_LM35() * (5000 / 1024.0) / 10)); // uses floats - disabled for performance reasons.
|
||||||
|
print_string(lm35Data);
|
||||||
|
print_string(NEXT_LINE);
|
||||||
|
|
||||||
|
|
||||||
|
print_string("----------");
|
||||||
|
print_string(NEXT_LINE);
|
||||||
|
}
|
||||||
|
} while (repeat); // repeat if repeat-flag is given
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//================================================================================================================================
|
||||||
|
// Funktion: cmd_rotary
|
||||||
|
// Wird verwendet um die Daten von Poti und LM35 zu lesen
|
||||||
|
// Parameter: _data: Zeichenkette mit Parametern des Befehls.
|
||||||
|
//
|
||||||
|
// Rückgabewert: keine
|
||||||
|
//================================================================================================================================
|
||||||
|
static void cmd_rotary(const char* _data){
|
||||||
|
char encoderText[50];
|
||||||
|
int16_t tmp=-32768, cnt=0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
cnt = drehgeber_get();
|
||||||
|
if(cnt != tmp)
|
||||||
|
{
|
||||||
|
sprintf(encoderText, "Rotary Encoder: %d", drehgeber_get());
|
||||||
|
print_string(encoderText);
|
||||||
|
print_string(NEXT_LINE);
|
||||||
|
|
||||||
|
tmp = cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (strcmp(_data, "R") == 0 ? 1 : 0); /* Check if repeat flag is set*/
|
||||||
|
}
|
@ -151,6 +151,12 @@
|
|||||||
</ToolchainSettings>
|
</ToolchainSettings>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="adc.c">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="adc.h">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
<Compile Include="cli.c">
|
<Compile Include="cli.c">
|
||||||
<SubType>compile</SubType>
|
<SubType>compile</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
@ -166,6 +172,12 @@
|
|||||||
<Compile Include="main.c">
|
<Compile Include="main.c">
|
||||||
<SubType>compile</SubType>
|
<SubType>compile</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="rotaryEncoder.c">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="rotaryEncoder.h">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
<Compile Include="StopLight.c">
|
<Compile Include="StopLight.c">
|
||||||
<SubType>compile</SubType>
|
<SubType>compile</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
@ -12,14 +12,14 @@ volatile uint16_t cntr = 0;
|
|||||||
|
|
||||||
void
|
void
|
||||||
Timer_init (void){
|
Timer_init (void){
|
||||||
TCCR0A |= (1<<1); /* Set WGM01 to high to enable CTC mode */
|
TCCR0A |= (1<<WGM01); /* Set WGM01 to high to enable CTC mode */
|
||||||
TCCR0B |= (11<<0); /* Set the clock select bit to pre-scaler 3
|
TCCR0B |= (3<<CS00); /* Set the clock select bit to pre-scaler 3
|
||||||
16MHz / 64 (pre-scaler 3) ==> 250KHz */
|
16MHz / 64 (pre-scaler 3) ==> 250KHz */
|
||||||
|
|
||||||
TIMSK0 |= (1<<1); /* Set OCIE0A to high to rise an interrupt when the counter matches OCR0A */
|
TIMSK0 |= (1<<OCIE0A); /* Set OCIE0A to high to rise an interrupt when the counter matches OCR0A */
|
||||||
|
|
||||||
OCR0A = 250 ; /* Set the Output Compare Register 0 A to 125 to trigger interrupt every 1ms
|
OCR0A = 250 - 1; /* Set the Output Compare Register 0 A to 125 to trigger interrupt every 1ms
|
||||||
16MHz / 64 (pre-scaler 3) / 250 ==> 1KHz (1ms) */
|
16MHz / 64 (pre-scaler 3) / (250 -1 ) ==> 1KHz (1ms) */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,7 +21,6 @@ volatile uint8_t TxActive;
|
|||||||
void
|
void
|
||||||
uart_init(void)
|
uart_init(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
UBRR0 = 103; /* set BAUD rate to 9600 */
|
UBRR0 = 103; /* set BAUD rate to 9600 */
|
||||||
|
|
||||||
UCSR0C |=
|
UCSR0C |=
|
||||||
|
74
EmbeddedSystemsTHM/adc.c
Normal file
74
EmbeddedSystemsTHM/adc.c
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* adc.c
|
||||||
|
*
|
||||||
|
* Created: 09/12/2021 16:31:16
|
||||||
|
* Author: n0x
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "adc.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
adc_init(void)
|
||||||
|
{
|
||||||
|
ADMUX = (1<<REFS1)|
|
||||||
|
(0<<REFS0)| /* Set Voltage reference to 2.56V */
|
||||||
|
(0<<ADLAR) /* Set ADLAR to 0 to not left adjust the presentation of the conversion result */
|
||||||
|
;
|
||||||
|
|
||||||
|
ADCSRA = (1<<ADEN)| /* Enable ADC */
|
||||||
|
(0<<ADATE)| /* Disable the ADC auto trigger */
|
||||||
|
(1<<ADIE)| /* Enable the ADC interrupt */
|
||||||
|
(1<<ADPS2)|
|
||||||
|
(1<<ADPS1)|
|
||||||
|
(1<<ADPS0) /* Set ADC Prescaler to 128 */
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
volatile int done = 1;
|
||||||
|
|
||||||
|
/* ADC 1 */
|
||||||
|
uint16_t
|
||||||
|
adc_get_poti(void)
|
||||||
|
{
|
||||||
|
uint16_t adc;
|
||||||
|
ADCSRA &= ~(1<<ADIE); /* Disable interrupt */
|
||||||
|
|
||||||
|
ADMUX |= (1<<MUX0); /* Set ADMUX to access ADC channel 1 */
|
||||||
|
ADCSRA |= (1<<ADSC); /* Start the conversion */
|
||||||
|
|
||||||
|
done = 0; /* reset the done flag to false */
|
||||||
|
|
||||||
|
while(done == 0); /* Wait till conversion completes */
|
||||||
|
|
||||||
|
adc = ADC;
|
||||||
|
|
||||||
|
ADCSRA |= (1<<ADIE); /* Enable the interrupt again */
|
||||||
|
|
||||||
|
return adc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ADC 0 */
|
||||||
|
uint16_t
|
||||||
|
adc_get_LM35(void)
|
||||||
|
{
|
||||||
|
uint16_t adc;
|
||||||
|
ADCSRA &= ~(1<<ADIE); /* Disable interrupt */
|
||||||
|
|
||||||
|
ADMUX &= (0<<MUX0); /* Set ADMUX to access ADC channel 0 */
|
||||||
|
ADCSRA |= (1<<ADSC); /* Start the conversion */
|
||||||
|
|
||||||
|
done = 0; /* reset the done flag to false */
|
||||||
|
|
||||||
|
while(done == 0); /* Wait till conversion completes */
|
||||||
|
|
||||||
|
adc = ADC;
|
||||||
|
|
||||||
|
ADCSRA |= (1<<ADIE); /* Enable the interrupt again */
|
||||||
|
|
||||||
|
return adc;
|
||||||
|
}
|
||||||
|
|
||||||
|
ISR(ADC_vect){
|
||||||
|
done = 1; /* set the done flag to true */
|
||||||
|
}
|
19
EmbeddedSystemsTHM/adc.h
Normal file
19
EmbeddedSystemsTHM/adc.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* adc.h
|
||||||
|
*
|
||||||
|
* Created: 09/12/2021 16:31:06
|
||||||
|
* Author: n0x
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
|
||||||
|
#ifndef ADC_H_
|
||||||
|
#define ADC_H_
|
||||||
|
|
||||||
|
void adc_init(void);
|
||||||
|
|
||||||
|
uint16_t adc_get_poti(void);
|
||||||
|
uint16_t adc_get_LM35(void);
|
||||||
|
|
||||||
|
#endif /* ADC_H_ */
|
@ -10,12 +10,16 @@
|
|||||||
#include "Timer.h"
|
#include "Timer.h"
|
||||||
#include "Tasks.h"
|
#include "Tasks.h"
|
||||||
#include "StopLight.h"
|
#include "StopLight.h"
|
||||||
#include "UART.h"
|
#include "uart.h"
|
||||||
#include "CLI.h"
|
#include "cli.h"
|
||||||
|
#include "adc.h"
|
||||||
|
#include "rotaryEncoder.h"
|
||||||
#include <avr/interrupt.h>
|
#include <avr/interrupt.h>
|
||||||
#define F_CPU 1000000
|
#define F_CPU 1000000
|
||||||
#include <util/delay.h>
|
#include <util/delay.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
/* function declarations */
|
/* function declarations */
|
||||||
void buttonTest (void);
|
void buttonTest (void);
|
||||||
|
|
||||||
@ -31,32 +35,18 @@ main (void)
|
|||||||
Taster_init();
|
Taster_init();
|
||||||
Led_init();
|
Led_init();
|
||||||
uart_init();
|
uart_init();
|
||||||
|
adc_init();
|
||||||
|
|
||||||
|
drehgeber_init();
|
||||||
|
|
||||||
line_interpreter_init(uart_send_byte);
|
line_interpreter_init(uart_send_byte);
|
||||||
uart_send_string("Welcome to the ATmega1284P CLI. Type HELP to display all options.\r\n");
|
uart_send_string("Welcome to the ATmega1284P CLI. Type HELP to display all options.\r\n");
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
/* UART Standalone Test */
|
|
||||||
/*
|
|
||||||
if(uart_data_available()){
|
|
||||||
char data[500];
|
|
||||||
data[0] = uart_get_data();
|
|
||||||
uart_send_isr(data);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
if(uart_data_available()){
|
if(uart_data_available()){
|
||||||
line_interpreter_get_data(uart_get_data());
|
line_interpreter_get_data(uart_get_data());
|
||||||
}
|
}
|
||||||
|
|
||||||
//buttonTest();
|
|
||||||
//runningLight();
|
|
||||||
//blinkLedWithTimer();
|
|
||||||
//runStopLightTask1();
|
|
||||||
//runStopLightTask2();
|
|
||||||
//uart_send ("uart_send: Hello World\n");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
148
EmbeddedSystemsTHM/rotaryEncoder.c
Normal file
148
EmbeddedSystemsTHM/rotaryEncoder.c
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
/*
|
||||||
|
* rotaryEncoder.c
|
||||||
|
*
|
||||||
|
* Created: 16/12/2021 16:34:05
|
||||||
|
* Author: n0x
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "rotaryEncoder.h"
|
||||||
|
|
||||||
|
#define ROTA PORTC7
|
||||||
|
#define ROTB PORTC6
|
||||||
|
#define ROTBUTTON PORTC5
|
||||||
|
|
||||||
|
/* enums */
|
||||||
|
enum{
|
||||||
|
S2, S3, S4, S5, S6, S7,
|
||||||
|
INIT, WAIT
|
||||||
|
} RotaryState = INIT; /* Emus for the stoplight task (task 3) */
|
||||||
|
|
||||||
|
int16_t count;
|
||||||
|
|
||||||
|
void
|
||||||
|
drehgeber_init(void)
|
||||||
|
{
|
||||||
|
DDRC &= ~(7<<DDC5); /* Set bit 5-7 of Data Direction Register C as input */
|
||||||
|
PORTC |= (7<<PORTC5); /* Initialize bit 5-7 of PORTC as for pull up resistor */
|
||||||
|
|
||||||
|
/* With Timer */
|
||||||
|
// TCCR2A |= (1<<WGM21);
|
||||||
|
// TCCR2B |= (3<<CS20);
|
||||||
|
// TIMSK2 |= (1<<OCIE2A);
|
||||||
|
// OCR2A = 250 - 1;
|
||||||
|
|
||||||
|
/* With external interrupt */
|
||||||
|
PCICR |= (1<<PCIE2);
|
||||||
|
PCMSK2 |= (1<<PCINT23)|(1<<PCINT22);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ISR(TIMER2_COMPA_vect)
|
||||||
|
// {
|
||||||
|
// drehgeber_process();
|
||||||
|
// }
|
||||||
|
|
||||||
|
ISR(PCINT2_vect)
|
||||||
|
{
|
||||||
|
drehgeber_process();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
drehgeber_process(void)
|
||||||
|
{
|
||||||
|
uint8_t a,b, enc;
|
||||||
|
a = ((PINC & (1<<ROTA)) == 0);
|
||||||
|
b = ((PINC & (1<<ROTB)) == 0)<<1;
|
||||||
|
enc=a+b;
|
||||||
|
|
||||||
|
switch(RotaryState)
|
||||||
|
{
|
||||||
|
case INIT:
|
||||||
|
RotaryState = WAIT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WAIT:
|
||||||
|
if(enc == 1)
|
||||||
|
{
|
||||||
|
RotaryState = S2;
|
||||||
|
}
|
||||||
|
if(enc == 2)
|
||||||
|
{
|
||||||
|
RotaryState = S5;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case S2:
|
||||||
|
if(enc == 3)
|
||||||
|
{
|
||||||
|
RotaryState = S3;
|
||||||
|
}
|
||||||
|
if(enc == 0)
|
||||||
|
{
|
||||||
|
RotaryState = WAIT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case S3:
|
||||||
|
if(enc == 2)
|
||||||
|
{
|
||||||
|
RotaryState = S4;
|
||||||
|
}
|
||||||
|
if(enc == 1)
|
||||||
|
{
|
||||||
|
RotaryState = S2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case S4:
|
||||||
|
if(enc == 0)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
RotaryState = WAIT;
|
||||||
|
}
|
||||||
|
if(enc == 3)
|
||||||
|
{
|
||||||
|
RotaryState = S3;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case S5:
|
||||||
|
if(enc == 3)
|
||||||
|
{
|
||||||
|
RotaryState = S6;
|
||||||
|
}
|
||||||
|
if(enc == 0)
|
||||||
|
{
|
||||||
|
RotaryState = WAIT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case S6:
|
||||||
|
if(enc == 1)
|
||||||
|
{
|
||||||
|
RotaryState = S7;
|
||||||
|
}
|
||||||
|
if(enc == 2)
|
||||||
|
{
|
||||||
|
RotaryState = S5;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case S7:
|
||||||
|
if(enc == 0)
|
||||||
|
{
|
||||||
|
count--;
|
||||||
|
RotaryState = WAIT;
|
||||||
|
}
|
||||||
|
if(enc == 3)
|
||||||
|
{
|
||||||
|
RotaryState = S6;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t drehgeber_get(void)
|
||||||
|
{
|
||||||
|
return count;
|
||||||
|
}
|
19
EmbeddedSystemsTHM/rotaryEncoder.h
Normal file
19
EmbeddedSystemsTHM/rotaryEncoder.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* rotaryEncoder.h
|
||||||
|
*
|
||||||
|
* Created: 16/12/2021 16:33:57
|
||||||
|
* Author: n0x
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
|
||||||
|
#ifndef ROTARYENCODER_H_
|
||||||
|
#define ROTARYENCODER_H_
|
||||||
|
|
||||||
|
void drehgeber_init(void);
|
||||||
|
void drehgeber_process(void);
|
||||||
|
int16_t drehgeber_get(void);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* ROTARYENCODER_H_ */
|
Loading…
Reference in New Issue
Block a user