C++でraspberry pi pico UARTを動かす

# 記事を書くきっかけ
C言語でUARTの受信バッファやリングポインタ等をグローバル変数ベタで書いてみたのですが、どうにもしっくりこなくて、C++のクラスでまとまるか試してみました。

# コード
2つのUART間で送受信を転送する簡単なプログラム例です。picowで動きました。
受信バッファのオーバーランは考慮していません。実験目的なのでご容赦ください。

```c++:uart.h
#ifndef _CUART_H
#define _CUART_H

/*
 * クラスの定義
 */
template <int CH, int RX_BUF_SIZE>
class CUart
{
protected:
	static CUart<CH, RX_BUF_SIZE>* _this;
	volatile uint16_t wp;
	uint16_t rp;
	uint8_t rx_buffer[RX_BUF_SIZE];

protected:
	void on_recv()
	{
		auto uart_inst = (CH == 0) ? uart0 : uart1;

		auto wp_tmp = this->wp;
		while ( ::uart_is_readable( uart_inst )) {
			const char c = uart_getc( uart_inst );
			this->rx_buffer[wp_tmp] = c;
			wp_tmp++;
			wp_tmp %= RX_BUF_SIZE ;
		}
		this->wp = wp_tmp;
	}

	static void callback_on_recv()
	{
		_this->on_recv();
	}

public:
	inline void init( const uint baudrate, const uint8_t txPin, const uint8_t rxPin );
	inline void write( const char c ) const;
	inline void writes( const char text[] ) const;
	inline bool isReadable( void ) const;
	inline char read( void );
};

/*
 * 初期化
 */
template <int CH, int RX_BUF_SIZE>
inline void CUart<CH, RX_BUF_SIZE>::init( const uint baudrate, const uint8_t txPin, const uint8_t rxPin )
{
	this->_this = this;

	auto uart_inst = (CH == 0) ? uart0 : uart1;
	auto num = (CH == 0) ? UART0_IRQ : UART1_IRQ;

	uart_init( uart_inst, baudrate );
	uart_set_fifo_enabled( uart_inst, false );
	irq_set_exclusive_handler(num, callback_on_recv );
	uart_set_irq_enables( uart_inst, true, false );
	irq_set_enabled(UART0_IRQ, true);

    gpio_set_function( txPin, GPIO_FUNC_UART );
    gpio_set_function( rxPin, GPIO_FUNC_UART );
	uart_set_translate_crlf( uart_inst, false );
}

/*
 * 1文字送信
 */
template <int CH, int RX_BUF_SIZE>
inline void CUart<CH, RX_BUF_SIZE>::write( const char c ) const
{
	auto uart_inst = (CH == 0) ? uart0 : uart1;
	::uart_putc_raw(uart_inst, c);
}

/*
 * 文字列送信
 */
template <int CH, int RX_BUF_SIZE>
inline void CUart<CH, RX_BUF_SIZE>::writes( const char text[] ) const
{
	auto uart_inst = (CH == 0) ? uart0 : uart1;
	::uart_puts( uart_inst, text );
}

/*
 * 受信有無検査
 */
template <int CH, int RX_BUF_SIZE>
inline bool CUart<CH, RX_BUF_SIZE>::isReadable( void ) const
{
	return this->wp != this->rp ? true : false;
}

/*
 * 1文字受信
 */
template <int CH, int RX_BUF_SIZE>
inline char CUart<CH, RX_BUF_SIZE>::read( void )
{
	const char c = this->rx_buffer[this->rp];
	this->rp++;
	this->rp %= RX_BUF_SIZE ;
	return c;
}

using CUart0 = CUart<0, 8192>;
using CUart1 = CUart<1, 8192>;

extern CUart0 picoUart0;
extern CUart1 picoUart1;

#endif /* _CUART_H */
```

```c++:uart0.cpp

#include "uart.h"
CUart0 picoUart0;
template<> CUart0* CUart0::_this {};
```


```c++:uart1.cpp
#include "uart.h"

CUart1 picoUart1;
template<> CUart1* CUart1::_this {};
```

```c++:sample_main.cpp
#include "uart.h"

int main()
{
    {
        //115200bps
    	const uint baudrate = (115200);
        //GP0を送信に使用
    	const uint8_t txPin = (0);
        //GP1を受信に使用
    	const uint8_t rxPin = (1);
    	picoUart0.init( baudrate, txPin, rxPin );
    }

    {
        //115200bps
        const uint baudrate = (115200);
        //GP4を送信に使用
        const uint8_t txPin = (4);
        //GP5を受信に使用
    	const uint8_t rxPin = (5);
    	picoUart1.init( baudrate, txPin, rxPin );
    }

	while ( true ) {
        //チャンネル0の受信をチャンネル1に転送
        while ( picoUart0.isReadable() == true ) {
            const char c = picoUart0.read();
            picoUart1.write( c );
        }

        //チャンネル1の受信をチャンネル0に転送
        while ( picoUart1.isReadable() == true ) {
            const char c = picoUart1.read();
            picoUart0.write( c );
        }
    }
}
```