Skip to content

zephyrSerial: Redesign to supporting hardware serial #64

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

Merged
merged 4 commits into from
Oct 29, 2022
Merged
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
5 changes: 5 additions & 0 deletions Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ config ARDUINO_API
imply NEWLIB_LIBC_FLOAT_PRINTF
imply CBPRINTF_FP_SUPPORT
imply RING_BUFFER
select UART_INTERRUPT_DRIVEN
default n

if ARDUINO_API
Expand All @@ -22,4 +23,8 @@ config QEMU_ICOUNT
default n
depends on QEMU_TARGET

config ARDUINO_API_SERIAL_BUFFER_SIZE
int "Buffer size for Arduino Serial API"
default 64

endif
1 change: 1 addition & 0 deletions cores/arduino/Arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@
#include <zephyr/kernel.h>

#include <variants.h>
#include <zephyrPrint.h>
#include <zephyrSerial.h>
3 changes: 2 additions & 1 deletion cores/arduino/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ int main(void) {

for (;;) {
loop();
if (arduino::serialEventRun) arduino::serialEventRun();
}

return 0;
}
}
82 changes: 82 additions & 0 deletions cores/arduino/zephyrPrint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,89 @@
* SPDX-License-Identifier: Apache-2.0
*/

#include <zephyr/sys/cbprintf.h>

#include <Arduino.h>
#include <api/Print.h>

namespace arduino
{
namespace zephyr
{

int cbprintf_callback(int c, void *ctx)
{
return reinterpret_cast<arduino::Print *>(ctx)->write((unsigned char)c);
}

size_t wrap_cbprintf(void *ctx, const char *format, ...)
{
va_list ap;
int rc;

va_start(ap, format);
rc = cbvprintf(reinterpret_cast<cbprintf_cb>(cbprintf_callback), ctx, format, ap);
va_end(ap);

return static_cast<size_t>(rc > 0 ? rc : 0);
}

size_t print_number_base_any(void *ctx, unsigned long long ull, int base)
{
arduino::Print &print = *reinterpret_cast<arduino::Print *>(ctx);
char string[sizeof(unsigned long long) * 8] = {0};
size_t digit = 0;
unsigned value;

if (base < 2 || base > ('~' - 'A' + 10)) {
base = 10;
}

while (ull != 0) {
value = ull % base;
if (value < 10) {
string[sizeof(string) - digit] = '0' + value;
} else {
string[sizeof(string) - digit] = 'A' + (value- 10);
}

digit++;
ull /= base;
}

return print.write(string + (sizeof(string) - digit), digit + 1);
}

size_t print_number_base_pow2(void *ctx, unsigned long long ull, unsigned bits)
{
arduino::Print &print = *reinterpret_cast<arduino::Print *>(ctx);
const unsigned long long mask = (1 << bits) - 1;
int digit = (((sizeof(unsigned long long) * 8) + bits) / bits);
int output_count = -1;
unsigned value;

while (digit >= 0) {
value = (ull & (mask << (digit * bits))) >> (digit * bits);
if (value != 0 && output_count < 0) {
output_count = 0;
}

if (output_count >= 0) {
if (value < 10) {
print.write('0' + value);
} else {
print.write('A' + (value- 10));
}
output_count++;
}
digit--;
}

return output_count;
}

} // namespace zephyr
} // namespace arduino

/*
* This is the default implementation.
Expand Down
190 changes: 190 additions & 0 deletions cores/arduino/zephyrPrint.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
/*
* Copyright (c) 2022 TOKITA Hiroshi <tokita.hiroshi@fujitsu.com>
*
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

#include <zephyr/sys/cbprintf.h>

#include <Arduino.h>
#include <api/Print.h>

namespace arduino
{
namespace zephyr
{

int cbprintf_callback(int c, void *ctx);
size_t wrap_cbprintf(void *ctx, const char *format, ...);
size_t print_number_base_any(void *ctx, unsigned long long ull, int base);
size_t print_number_base_pow2(void *ctx, unsigned long long ull, unsigned bits);

template <class Number> size_t print_number(void *ctx, Number n, const int base, const char *decfmt)
{
if (base == 0) {
return reinterpret_cast<arduino::Print *>(ctx)->write((char)n);
} else if (base == 2) {
return arduino::zephyr::print_number_base_pow2(ctx, n, 1);
} else if (base == 4) {
return arduino::zephyr::print_number_base_pow2(ctx, n, 2);
} else if (base == 8) {
return arduino::zephyr::print_number_base_pow2(ctx, n, 3);
} else if (base == 10) {
return arduino::zephyr::wrap_cbprintf(ctx, decfmt, n);
} else if (base == 16) {
return arduino::zephyr::print_number_base_pow2(ctx, n, 4);
} else if (base == 32) {
return arduino::zephyr::print_number_base_pow2(ctx, n, 5);
} else {
return arduino::zephyr::print_number_base_any(ctx, n, base);
}
}

} // namespace zephyr

} // namespace arduino

inline size_t arduino::Print::print(const __FlashStringHelper *fsh)
{
return write(reinterpret_cast<const char *>(fsh));
}

inline size_t arduino::Print::print(const String &s)
{
return write(s.c_str(), s.length());
}

inline size_t arduino::Print::print(const char str[])
{
return write(str);
}

inline size_t arduino::Print::print(char c)
{
return write(c);
}

inline size_t arduino::Print::print(unsigned char n, int base)
{
return arduino::zephyr::print_number(this, n, base, "%hhu");
}

inline size_t arduino::Print::print(int n, int base)
{
return arduino::zephyr::print_number(this, n, base, "%d");
}

inline size_t arduino::Print::print(unsigned int n, int base)
{
return arduino::zephyr::print_number(this, n, base, "%u");
}

inline size_t arduino::Print::print(long n, int base)
{
return arduino::zephyr::print_number(this, n, base, "%ld");
}

inline size_t arduino::Print::print(unsigned long n, int base)
{
return arduino::zephyr::print_number(this, n, base, "%lu");
}

inline size_t arduino::Print::print(long long n, int base)
{
return arduino::zephyr::print_number(this, n, base, "%lld");
}

inline size_t arduino::Print::print(unsigned long long n, int base)
{
return arduino::zephyr::print_number(this, n, base, "%llu");
}

inline size_t arduino::Print::print(double n, int perception)
{
if (perception < 10) {
const char ch_perception = static_cast<char>('0' + perception);
const char format[] = {'%', '.', ch_perception, 'f', '\0'};
return arduino::zephyr::wrap_cbprintf(this, format, n);
} else {
const char ch_perception = static_cast<char>('0' + (perception % 10));
const char format[] = {'%', '.', '1', ch_perception, 'f', '\0'};
return arduino::zephyr::wrap_cbprintf(this, format, n);
}
}

inline size_t arduino::Print::print(const Printable &printable)
{
return printable.printTo(*this);
}

inline size_t arduino::Print::println(const __FlashStringHelper *fsh)
{
return print(fsh) + println();
}

inline size_t arduino::Print::println(const String &s)
{
return print(s) + println();
}

inline size_t arduino::Print::println(const char str[])
{
return print(str) + println();
}

inline size_t arduino::Print::println(char c)
{
return print(c) + println();
}

inline size_t arduino::Print::println(unsigned char uc, int base)
{
return print(uc, base) + println();
}

inline size_t arduino::Print::println(int i, int base)
{
return print(i, base) + println();
}

inline size_t arduino::Print::println(unsigned int ui, int base)
{
return print(ui, base) + println();
}

inline size_t arduino::Print::println(long l, int base)
{
return print(l, base) + println();
}

inline size_t arduino::Print::println(unsigned long ul, int base)
{
return print(ul, base) + println();
}

inline size_t arduino::Print::println(long long ll, int base)
{
return print(ll, base) + println();
}

inline size_t arduino::Print::println(unsigned long long ull, int base)
{
return print(ull, base) + println();
}

inline size_t arduino::Print::println(double d, int perception)
{
return print(d, perception) + println();
}

inline size_t arduino::Print::println(const Printable &printable)
{
return print(printable) + println();
}

inline size_t arduino::Print::println(void)
{
return write("\r\n", 2);
}
Loading