mirror of
https://github.com/RobTillaart/Arduino.git
synced 2024-10-03 18:09:02 -04:00
0.1.4 Fletcher
This commit is contained in:
parent
196397b8ca
commit
7aa3c626ab
@ -2,13 +2,13 @@ compile:
|
||||
# Choosing to run compilation tests on 2 different Arduino platforms
|
||||
platforms:
|
||||
- uno
|
||||
# - due
|
||||
# - zero
|
||||
# - leonardo
|
||||
- due
|
||||
- zero
|
||||
- leonardo
|
||||
- m4
|
||||
- esp32
|
||||
# - esp8266
|
||||
# - mega2560
|
||||
- esp8266
|
||||
- mega2560
|
||||
|
||||
libraries:
|
||||
- "printHelpers"
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// FILE: Fletcher.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.3
|
||||
// VERSION: 0.1.4
|
||||
// DATE: 2022-01-25
|
||||
// PURPOSE: Arduino Library for calculating Fletcher's checksum
|
||||
// URL: https://github.com/RobTillaart/Fletcher
|
||||
@ -12,16 +12,12 @@
|
||||
// 0.1.1 2022-01-26 optimize % math variation based upon to Anastase Nakassis (wikipedia)
|
||||
// 0.1.2 2022-01-26 add class implementation e.g. for streaming
|
||||
// 0.1.3 2022-04-15 fix #4 split .h in .h and .cpp
|
||||
// 0.1.4 2022-09-08 performance optimization (Kudos to Daniel Mohr).
|
||||
// affects SAMD, ESP32 and ESP8266
|
||||
// fix FLETCHER_LIB_VERSION
|
||||
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
|
||||
#define FLETCHER_LIB_VERSION (F("0.1.2"))
|
||||
|
||||
#define FLETCHER_16 255
|
||||
#define FLETCHER_32 65535UL
|
||||
#define FLETCHER_64 4294967295ULL
|
||||
#include "Fletcher.h"
|
||||
|
||||
|
||||
//
|
||||
@ -42,7 +38,10 @@ uint16_t fletcher16(uint8_t *data, uint16_t length)
|
||||
s2 += s1;
|
||||
}
|
||||
s1 %= FLETCHER_16;
|
||||
// does not work due to the above "32-bit" loop.
|
||||
// s1 = (s1 & 255) + (s1 >> 8);
|
||||
s2 %= FLETCHER_16;
|
||||
// s2 = (s2 & 255) + (s2 >> 8);
|
||||
}
|
||||
return (s2 << 8) | s1;
|
||||
}
|
||||
@ -60,8 +59,11 @@ uint32_t fletcher32(uint16_t *data, uint16_t length)
|
||||
s1 += data[i++];
|
||||
s2 += s1;
|
||||
}
|
||||
s1 %= FLETCHER_32;
|
||||
s2 %= FLETCHER_32;
|
||||
// s1 %= FLETCHER_32;
|
||||
s1 = (s1 & 65535UL) + (s1 >> 16);
|
||||
|
||||
// s2 %= FLETCHER_32;
|
||||
s2 = (s2 & 65535UL) + (s2 >> 16);
|
||||
}
|
||||
return (s2 << 16) | s1;
|
||||
}
|
||||
@ -79,8 +81,10 @@ uint64_t fletcher64(uint32_t *data, uint16_t length)
|
||||
s1 += data[i++];
|
||||
s2 += s1;
|
||||
}
|
||||
s1 %= FLETCHER_64;
|
||||
s2 %= FLETCHER_64;
|
||||
// s1 %= FLETCHER_64;
|
||||
s1 = (s1 & ((((uint64_t) 1) << 32) - 1)) + (s1 >> 32);
|
||||
// s2 %= FLETCHER_64;
|
||||
s2 = (s2 & ((((uint64_t) 1) << 32) - 1)) + (s2 >> 32);
|
||||
}
|
||||
return (s2 << 32) | s1;
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
//
|
||||
// FILE: Fletcher.h
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.3
|
||||
// VERSION: 0.1.4
|
||||
// DATE: 2022-01-25
|
||||
// PURPOSE: Arduino Library for calculating Fletcher's checksum
|
||||
// URL: https://github.com/RobTillaart/Fletcher
|
||||
@ -12,7 +12,7 @@
|
||||
#include "Arduino.h"
|
||||
|
||||
|
||||
#define FLETCHER_LIB_VERSION (F("0.1.3"))
|
||||
#define FLETCHER_LIB_VERSION (F("0.1.4"))
|
||||
|
||||
#define FLETCHER_16 255
|
||||
#define FLETCHER_32 65535UL
|
||||
|
@ -28,9 +28,9 @@ void Fletcher16::add(uint8_t value)
|
||||
{
|
||||
_count++;
|
||||
_s1 += value;
|
||||
if (_s1 >= FLETCHER_16) _s1 -= FLETCHER_16;
|
||||
_s1 = (_s1 & 255) + (_s1 >> 8);
|
||||
_s2 += _s1;
|
||||
if (_s2 >= FLETCHER_16) _s2 -= FLETCHER_16;
|
||||
_s2 = (_s2 & 255) + (_s2 >> 8);
|
||||
}
|
||||
|
||||
|
||||
|
@ -29,9 +29,17 @@ void Fletcher32::add(uint16_t value)
|
||||
{
|
||||
_count++;
|
||||
_s1 += value;
|
||||
if (_s1 >= FLETCHER_32) _s1 -= FLETCHER_32;
|
||||
#if defined(ARDUINO_ARCH_SAMD) || defined(ESP32) || defined(ESP8266)
|
||||
_s1 = (_s1 & 65535UL) + (_s1 >> 16);
|
||||
#else
|
||||
if (_s1 >= FLETCHER_32) _s1 -= FLETCHER_32;
|
||||
#endif
|
||||
_s2 += _s1;
|
||||
if (_s2 >= FLETCHER_32) _s2 -= FLETCHER_32;
|
||||
#if defined(ARDUINO_ARCH_SAMD) || defined(ESP32) || defined(ESP8266)
|
||||
_s2 = (_s2 & 65535UL) + (_s2 >> 16);
|
||||
#else
|
||||
if (_s2 >= FLETCHER_32) _s2 -= FLETCHER_32;
|
||||
#endif
|
||||
}
|
||||
|
||||
// NOTE: padding with zero's error
|
||||
|
@ -29,9 +29,17 @@ void Fletcher64::add(uint32_t value)
|
||||
{
|
||||
_count++;
|
||||
_s1 += value;
|
||||
if (_s1 >= FLETCHER_64) _s1 -= FLETCHER_64;
|
||||
#if defined(ARDUINO_ARCH_SAMD) || defined(ESP32) || defined(ESP8266)
|
||||
_s1 = (_s1 & ((((uint64_t) 1) << 32) - 1)) + (_s1 >> 32);
|
||||
#else
|
||||
if (_s1 >= FLETCHER_64) _s1 -= FLETCHER_64;
|
||||
#endif
|
||||
_s2 += _s1;
|
||||
if (_s2 >= FLETCHER_64) _s2 -= FLETCHER_64;
|
||||
#if defined(ARDUINO_ARCH_SAMD) || defined(ESP32) || defined(ESP8266)
|
||||
_s2 = (_s2 & ((((uint64_t) 1) << 32) - 1)) + (_s2 >> 32);
|
||||
#else
|
||||
if (_s2 >= FLETCHER_64) _s2 -= FLETCHER_64;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -23,7 +23,7 @@ Relates to https://github.com/RobTillaart/CRC
|
||||
|
||||
Use https://github.com/RobTillaart/printHelpers to print the Fletcher64().
|
||||
|
||||
Tested on Arduino UNO only.
|
||||
Tested on Arduino UNO + ESP32 + SAMD (See PR #7).
|
||||
|
||||
|
||||
## Interface
|
||||
@ -47,19 +47,6 @@ The checksum from **getFletcher()** can be split into a high and a low part
|
||||
to be used to "feed" **begin()** again. See restart example.
|
||||
|
||||
|
||||
#### Performance
|
||||
|
||||
Not tested ESP32 (and many other platforms) yet.
|
||||
First numbers of **.add(value)** measured with test sketch shows the following timing.
|
||||
|
||||
| Checksum | UNO 16 MHz | ESP32 240 MHz |
|
||||
|:------------|:-----------:|:-------------:|
|
||||
| Fletcher16 | 3.8 us | 0.22 us |
|
||||
| Fletcher32 | 5.6 us | 0.23 us |
|
||||
| Fletcher64 | 10.1 us | 0.26 us |
|
||||
| Average | 6.5 us | 0.24 us |
|
||||
|
||||
|
||||
## Interface static functions
|
||||
|
||||
The functions are straightforward, however one should define **length**
|
||||
@ -74,14 +61,28 @@ Use **\#include "Fletcher.h"**
|
||||
- **uint64_t fletcher64(uint32_t \*data, uint16_t length)** length in units of 4 bytes = 32 bits.
|
||||
|
||||
|
||||
#### Performance
|
||||
#### Performance I
|
||||
|
||||
Not tested ESP32 (and many other platforms) yet.
|
||||
First numbers of **.add(value)** measured with test sketch shows the following timing.
|
||||
|
||||
| Checksum | UNO 16 MHz | ESP32 240 MHz |
|
||||
|:------------|:-----------:|:-------------:|
|
||||
| Fletcher16 | 3.8 us | 0.22 us |
|
||||
| Fletcher32 | 5.6 us | 0.23 us |
|
||||
| Fletcher64 | 10.1 us | 0.26 us |
|
||||
| Average | 6.5 us | 0.24 us |
|
||||
|
||||
|
||||
#### Performance II
|
||||
|
||||
Not tested extensively, first numbers of **.add(array, length)**
|
||||
measured with **Fletcher_performance.ino** sketch shows the following timing.
|
||||
|
||||
Lorem Ipsum text = 868 bytes.
|
||||
|
||||
Version 0.1.3.
|
||||
|
||||
| Checksum | UNO 16 MHz | ESP32 240 MHz | Notes |
|
||||
|:------------|:-----------:|:-------------:|:-------------------|
|
||||
| Fletcher16 | 1120 us | 62 us | first run slower ? |
|
||||
@ -91,6 +92,9 @@ Lorem Ipsum text = 868 bytes.
|
||||
| Avg / char | 1.46 us | 0.0495 us | 868 bytes |
|
||||
|
||||
|
||||
Note 0.1.4 has improved the performance. See PR #7 for some numbers.
|
||||
|
||||
|
||||
## Operation
|
||||
|
||||
See examples.
|
||||
@ -99,6 +103,7 @@ See examples.
|
||||
## Future ideas
|
||||
|
||||
- improve documentation
|
||||
- update performance figures.
|
||||
- test other platforms
|
||||
- others e.g. Fletcher24?
|
||||
- generic FletcherN(). for N = 1..32
|
||||
|
@ -24,7 +24,7 @@ void setup()
|
||||
start = micros();
|
||||
for (uint16_t x = 0; x < 10000; x++)
|
||||
{
|
||||
z = random(255);
|
||||
z = random(256);
|
||||
}
|
||||
stop = micros();
|
||||
randomtime = stop - start;
|
||||
@ -36,7 +36,7 @@ void setup()
|
||||
start = micros();
|
||||
for (uint16_t x = 0; x < 10000; x++)
|
||||
{
|
||||
z = random(255);
|
||||
z = random(256);
|
||||
fl.add(z);
|
||||
}
|
||||
stop = micros();
|
||||
|
@ -24,7 +24,7 @@ void setup()
|
||||
start = micros();
|
||||
for (uint16_t x = 0; x < 10000; x++)
|
||||
{
|
||||
z = random(255);
|
||||
z = random(256);
|
||||
}
|
||||
stop = micros();
|
||||
randomtime = stop - start;
|
||||
@ -36,7 +36,7 @@ void setup()
|
||||
start = micros();
|
||||
for (uint16_t x = 0; x < 10000; x++)
|
||||
{
|
||||
z = random(255);
|
||||
z = random(256);
|
||||
fl.add(z);
|
||||
}
|
||||
stop = micros();
|
||||
|
@ -0,0 +1,11 @@
|
||||
|
||||
Tested on ESP32 (240 MHz)
|
||||
IDE 1.18
|
||||
|
||||
FLETCHER_LIB_VERSION: 0.1.3
|
||||
|
||||
Fletcher32_performance
|
||||
randomtime: 6945
|
||||
total: 9275
|
||||
1e4 x add: 2330
|
||||
checksum: 430995902
|
@ -0,0 +1,26 @@
|
||||
|
||||
Tested on ESP32 (240 MHz)
|
||||
IDE 1.18
|
||||
|
||||
FLETCHER_LIB_VERSION: 0.1.3
|
||||
|
||||
Fletcher32_performance
|
||||
randomtime: 6945
|
||||
total: 9275
|
||||
1e4 x add: 2330
|
||||
checksum: 430995902
|
||||
|
||||
|
||||
FLETCHER_LIB_VERSION: 0.1.4
|
||||
|
||||
Fletcher32_performance (old method)
|
||||
randomtime: 6945
|
||||
total: 9274
|
||||
1e4 x add: 2329
|
||||
checksum: 886350356 (as we add random values this happens).
|
||||
|
||||
Fletcher32_performance (optimized modulo)
|
||||
randomtime: 6947
|
||||
total: 8577
|
||||
1e4 x add: 1630
|
||||
checksum: 233217780
|
@ -24,7 +24,7 @@ void setup()
|
||||
start = micros();
|
||||
for (uint16_t x = 0; x < 10000; x++)
|
||||
{
|
||||
z = random(255);
|
||||
z = random(256);
|
||||
}
|
||||
stop = micros();
|
||||
randomtime = stop - start;
|
||||
@ -36,7 +36,7 @@ void setup()
|
||||
start = micros();
|
||||
for (uint16_t x = 0; x < 10000; x++)
|
||||
{
|
||||
z = random(255);
|
||||
z = random(256);
|
||||
fl.add(z);
|
||||
}
|
||||
stop = micros();
|
||||
|
@ -0,0 +1,21 @@
|
||||
|
||||
Tested on ESP32 (240 MHz)
|
||||
IDE 1.18.19
|
||||
|
||||
(included for comparison Arduino UNO)
|
||||
FLETCHER_LIB_VERSION: 0.1.1
|
||||
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ae...
|
||||
LENGTH STR: 868
|
||||
FLETCHER16: 1120 53705
|
||||
FLETCHER32: 728 1196447857
|
||||
FLETCHER64: 1952 10053561395214921491
|
||||
|
||||
FLETCHER_LIB_VERSION: 0.1.3
|
||||
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ae...
|
||||
LENGTH STR: 868
|
||||
FLETCHER16: 61 53705
|
||||
FLETCHER32: 33 1196447857
|
||||
FLETCHER64: 34 10053561395214921491
|
||||
|
||||
|
||||
|
@ -0,0 +1,23 @@
|
||||
|
||||
Tested on Arduino UNO
|
||||
IDE 1.18.19
|
||||
|
||||
(included for comparison)
|
||||
FLETCHER_LIB_VERSION: 0.1.1
|
||||
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ae...
|
||||
LENGTH STR: 868
|
||||
FLETCHER16: 1120 53705
|
||||
FLETCHER32: 728 1196447857
|
||||
FLETCHER64: 1952 10053561395214921491
|
||||
|
||||
|
||||
FLETCHER_LIB_VERSION: 0.1.4
|
||||
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ae...
|
||||
LENGTH STR: 868
|
||||
FLETCHER16: 1120 53705
|
||||
FLETCHER32: 552 1196447857
|
||||
FLETCHER64: 1960 10053561395214921491
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,31 @@
|
||||
|
||||
Tested on ESP32 (240 MHz)
|
||||
IDE 1.18.19
|
||||
|
||||
(included for comparison Arduino UNO)
|
||||
FLETCHER_LIB_VERSION: 0.1.1
|
||||
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ae...
|
||||
LENGTH STR: 868
|
||||
FLETCHER16: 1120 53705
|
||||
FLETCHER32: 728 1196447857
|
||||
FLETCHER64: 1952 10053561395214921491
|
||||
|
||||
|
||||
FLETCHER_LIB_VERSION: 0.1.3
|
||||
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ae...
|
||||
LENGTH STR: 868
|
||||
FLETCHER16: 61 53705
|
||||
FLETCHER32: 33 1196447857
|
||||
FLETCHER64: 34 10053561395214921491
|
||||
|
||||
|
||||
FLETCHER_LIB_VERSION: 0.1.4
|
||||
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ae...
|
||||
LENGTH STR: 868
|
||||
FLETCHER16: 60 53705
|
||||
FLETCHER32: 34 1196447857
|
||||
FLETCHER64: 31 10053561395214921491
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,150 @@
|
||||
/*
|
||||
Author: Daniel Mohr
|
||||
Date: 2022-09-07
|
||||
Purpose: shows stream performance
|
||||
*/
|
||||
#include "Arduino.h"
|
||||
|
||||
#include "printHelpers.h" // needed for Arduino Nano
|
||||
#include <Fletcher16.h>
|
||||
#include <Fletcher32.h>
|
||||
#include <Fletcher64.h>
|
||||
|
||||
#ifdef ARDUINO_ARCH_AVR
|
||||
#define MAX_LEN 1024
|
||||
#else
|
||||
#define MAX_LEN 16384
|
||||
#endif
|
||||
|
||||
#define DO_N 23
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial);
|
||||
}
|
||||
|
||||
void test_fletcher16() {
|
||||
Serial.println("Fletcher16");
|
||||
const uint16_t max_len = MAX_LEN;
|
||||
uint8_t values[max_len];
|
||||
uint32_t t0, t1;
|
||||
delay(100);
|
||||
t0 = micros();
|
||||
for (uint16_t i = 0; i < max_len; i++) {
|
||||
values[i] = (uint8_t) random(0, 1 << 8);
|
||||
}
|
||||
t1 = micros();
|
||||
Serial.print("Created random list: ");
|
||||
Serial.print(1024.0 * (t1 - t0) / float(MAX_LEN));
|
||||
Serial.println(" us/kByte.");
|
||||
Fletcher16 checksum_instance;
|
||||
uint16_t checksum;
|
||||
uint32_t totaltime = 0;
|
||||
for (uint16_t j = 0; j < DO_N; j++) {
|
||||
t0 = micros();
|
||||
checksum_instance.begin();
|
||||
for (uint16_t i = 0; i < max_len; i++) {
|
||||
checksum_instance.add(values[i]);
|
||||
}
|
||||
checksum = checksum_instance.getFletcher();
|
||||
t1 = micros();
|
||||
totaltime += t1 - t0;
|
||||
}
|
||||
Serial.print("Checksum: ");
|
||||
Serial.println(checksum);
|
||||
Serial.print("Created checksum: ");
|
||||
Serial.print(1024.0 * totaltime / float(DO_N * MAX_LEN));
|
||||
Serial.println(" us/kByte.");
|
||||
}
|
||||
|
||||
void test_fletcher32() {
|
||||
Serial.println("Fletcher32");
|
||||
const uint16_t max_len = MAX_LEN / 2;
|
||||
uint16_t values[max_len];
|
||||
uint32_t t0, t1;
|
||||
delay(100);
|
||||
t0 = micros();
|
||||
for (uint16_t i = 0; i < max_len; i++) {
|
||||
values[i] = (uint16_t) random(0, ((uint32_t) 1) << 16);
|
||||
}
|
||||
t1 = micros();
|
||||
Serial.print("Created random list: ");
|
||||
Serial.print(1024.0 * (t1 - t0) / float(MAX_LEN));
|
||||
Serial.println(" us/kByte.");
|
||||
Fletcher32 checksum_instance;
|
||||
uint32_t checksum;
|
||||
uint32_t totaltime = 0;
|
||||
for (uint16_t j = 0; j < DO_N; j++) {
|
||||
t0 = micros();
|
||||
checksum_instance.begin();
|
||||
for (uint16_t i = 0; i < max_len; i++) {
|
||||
checksum_instance.add(values[i]);
|
||||
}
|
||||
checksum = checksum_instance.getFletcher();
|
||||
t1 = micros();
|
||||
totaltime += t1 - t0;
|
||||
}
|
||||
Serial.print("Checksum: ");
|
||||
Serial.println(checksum);
|
||||
Serial.print("Created checksum: ");
|
||||
Serial.print(1024.0 * totaltime / float(DO_N * MAX_LEN));
|
||||
Serial.println(" us/kByte.");
|
||||
}
|
||||
|
||||
void test_fletcher64() {
|
||||
Serial.println("Fletcher64");
|
||||
const uint16_t max_len = MAX_LEN / 4;
|
||||
uint32_t values[max_len];
|
||||
uint32_t t0, t1;
|
||||
delay(100);
|
||||
t0 = micros();
|
||||
for (uint16_t i = 0; i < max_len; i++) {
|
||||
values[i] = ((uint32_t) random(0, ((uint32_t) 1) << 16)) + (((uint32_t) random(0, ((uint32_t) 1) << 16)) << 16);
|
||||
}
|
||||
t1 = micros();
|
||||
Serial.print("Created random list: ");
|
||||
Serial.print(1024.0 * (t1 - t0) / float(MAX_LEN));
|
||||
Serial.println(" us/kByte.");
|
||||
Fletcher64 checksum_instance;
|
||||
uint64_t checksum;
|
||||
uint32_t totaltime = 0;
|
||||
for (uint16_t j = 0; j < DO_N; j++) {
|
||||
t0 = micros();
|
||||
checksum_instance.begin();
|
||||
for (uint16_t i = 0; i < max_len; i++) {
|
||||
checksum_instance.add(values[i]);
|
||||
}
|
||||
checksum = checksum_instance.getFletcher();
|
||||
t1 = micros();
|
||||
totaltime += t1 - t0;
|
||||
}
|
||||
Serial.print("Checksum: ");
|
||||
Serial.println(print64(checksum));
|
||||
Serial.print("Created checksum: ");
|
||||
Serial.print(1024.0 * totaltime / float(DO_N * MAX_LEN));
|
||||
Serial.println(" us/kByte.");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
Serial.print("Using list of ");
|
||||
Serial.print(MAX_LEN);
|
||||
Serial.println(" elements for Fletcher16");
|
||||
Serial.print("Using list of ");
|
||||
Serial.print(MAX_LEN/2);
|
||||
Serial.println(" elements for Fletcher32");
|
||||
Serial.print("Using list of ");
|
||||
Serial.print(MAX_LEN/4);
|
||||
Serial.println(" elements for Fletcher64");
|
||||
Serial.println("");
|
||||
test_fletcher16();
|
||||
Serial.println("");
|
||||
delay(1000);
|
||||
test_fletcher32();
|
||||
Serial.println("");
|
||||
delay(1000);
|
||||
test_fletcher64();
|
||||
Serial.println("");
|
||||
delay(1000);
|
||||
Serial.println("");
|
||||
}
|
@ -15,7 +15,7 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/Fletcher.git"
|
||||
},
|
||||
"version": "0.1.3",
|
||||
"version": "0.1.4",
|
||||
"license": "MIT",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*",
|
||||
|
@ -1,5 +1,5 @@
|
||||
name=Fletcher
|
||||
version=0.1.3
|
||||
version=0.1.4
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence="Arduino Library for calculating Fletcher's checksum.
|
||||
|
Loading…
x
Reference in New Issue
Block a user