aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/apa102/apa102.c151
-rw-r--r--drivers/apa102/apa102.h (renamed from drivers/avr/apa102.h)32
-rw-r--r--drivers/avr/apa102.c96
-rw-r--r--drivers/avr/serial.c6
-rw-r--r--drivers/avr/spi_master.c2
-rw-r--r--drivers/avr/spi_master.h2
-rw-r--r--drivers/avr/uart.c170
-rw-r--r--drivers/avr/uart.h35
-rw-r--r--drivers/chibios/serial_usart.c13
-rw-r--r--drivers/chibios/uart.c59
-rw-r--r--drivers/chibios/uart.h77
-rw-r--r--drivers/qwiic/qwiic.mk9
12 files changed, 524 insertions, 128 deletions
diff --git a/drivers/apa102/apa102.c b/drivers/apa102/apa102.c
new file mode 100644
index 000000000..7396dc3c5
--- /dev/null
+++ b/drivers/apa102/apa102.c
@@ -0,0 +1,151 @@
1/* Copyright 2020 Aldehir Rojas
2 * Copyright 2017 Mikkel (Duckle29)
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "apa102.h"
19#include "quantum.h"
20
21#ifndef APA102_NOPS
22# if defined(__AVR__)
23# define APA102_NOPS 0 // AVR at 16 MHz already spends 62.5 ns per clock, so no extra delay is needed
24# elif defined(PROTOCOL_CHIBIOS)
25
26# include "hal.h"
27# if defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F3XX) || defined(STM32F4XX) || defined(STM32L0XX)
28# define APA102_NOPS (100 / (1000000000L / (STM32_SYSCLK / 4))) // This calculates how many loops of 4 nops to run to delay 100 ns
29# else
30# error("APA102_NOPS configuration required")
31# define APA102_NOPS 0 // this just pleases the compile so the above error is easier to spot
32# endif
33# endif
34#endif
35
36#define io_wait \
37 do { \
38 for (int i = 0; i < APA102_NOPS; i++) { \
39 __asm__ volatile("nop\n\t" \
40 "nop\n\t" \
41 "nop\n\t" \
42 "nop\n\t"); \
43 } \
44 } while (0)
45
46#define APA102_SEND_BIT(byte, bit) \
47 do { \
48 writePin(RGB_DI_PIN, (byte >> bit) & 1); \
49 io_wait; \
50 writePinHigh(RGB_CI_PIN); \
51 io_wait; \
52 writePinLow(RGB_CI_PIN); \
53 io_wait; \
54 } while (0)
55
56uint8_t apa102_led_brightness = APA102_DEFAULT_BRIGHTNESS;
57
58void static apa102_start_frame(void);
59void static apa102_end_frame(uint16_t num_leds);
60
61void static apa102_send_frame(uint8_t red, uint8_t green, uint8_t blue, uint8_t brightness);
62void static apa102_send_byte(uint8_t byte);
63
64void apa102_setleds(LED_TYPE *start_led, uint16_t num_leds) {
65 LED_TYPE *end = start_led + num_leds;
66
67 apa102_start_frame();
68 for (LED_TYPE *led = start_led; led < end; led++) {
69 apa102_send_frame(led->r, led->g, led->b, apa102_led_brightness);
70 }
71 apa102_end_frame(num_leds);
72}
73
74// Overwrite the default rgblight_call_driver to use apa102 driver
75void rgblight_call_driver(LED_TYPE *start_led, uint8_t num_leds) { apa102_setleds(start_led, num_leds); }
76
77void static apa102_init(void) {
78 setPinOutput(RGB_DI_PIN);
79 setPinOutput(RGB_CI_PIN);
80
81 writePinLow(RGB_DI_PIN);
82 writePinLow(RGB_CI_PIN);
83}
84
85void apa102_set_brightness(uint8_t brightness) {
86 if (brightness > APA102_MAX_BRIGHTNESS) {
87 apa102_led_brightness = APA102_MAX_BRIGHTNESS;
88 } else if (brightness < 0) {
89 apa102_led_brightness = 0;
90 } else {
91 apa102_led_brightness = brightness;
92 }
93}
94
95void static apa102_send_frame(uint8_t red, uint8_t green, uint8_t blue, uint8_t brightness) {
96 apa102_send_byte(0b11100000 | brightness);
97 apa102_send_byte(blue);
98 apa102_send_byte(green);
99 apa102_send_byte(red);
100}
101
102void static apa102_start_frame(void) {
103 apa102_init();
104 for (uint16_t i = 0; i < 4; i++) {
105 apa102_send_byte(0);
106 }
107}
108
109void static apa102_end_frame(uint16_t num_leds) {
110 // This function has been taken from: https://github.com/pololu/apa102-arduino/blob/master/APA102.h
111 // and adapted. The code is MIT licensed. I think thats compatible?
112 //
113 // The data stream seen by the last LED in the chain will be delayed by
114 // (count - 1) clock edges, because each LED before it inverts the clock
115 // line and delays the data by one clock edge. Therefore, to make sure
116 // the last LED actually receives the data we wrote, the number of extra
117 // edges we send at the end of the frame must be at least (count - 1).
118 //
119 // Assuming we only want to send these edges in groups of size K, the
120 // C/C++ expression for the minimum number of groups to send is:
121 //
122 // ((count - 1) + (K - 1)) / K
123 //
124 // The C/C++ expression above is just (count - 1) divided by K,
125 // rounded up to the nearest whole number if there is a remainder.
126 //
127 // We set K to 16 and use the formula above as the number of frame-end
128 // bytes to transfer. Each byte has 16 clock edges.
129 //
130 // We are ignoring the specification for the end frame in the APA102
131 // datasheet, which says to send 0xFF four times, because it does not work
132 // when you have 66 LEDs or more, and also it results in unwanted white
133 // pixels if you try to update fewer LEDs than are on your LED strip.
134 uint16_t iterations = (num_leds + 14) / 16;
135 for (uint16_t i = 0; i < iterations; i++) {
136 apa102_send_byte(0);
137 }
138
139 apa102_init();
140}
141
142void static apa102_send_byte(uint8_t byte) {
143 APA102_SEND_BIT(byte, 7);
144 APA102_SEND_BIT(byte, 6);
145 APA102_SEND_BIT(byte, 5);
146 APA102_SEND_BIT(byte, 4);
147 APA102_SEND_BIT(byte, 3);
148 APA102_SEND_BIT(byte, 2);
149 APA102_SEND_BIT(byte, 1);
150 APA102_SEND_BIT(byte, 0);
151}
diff --git a/drivers/avr/apa102.h b/drivers/apa102/apa102.h
index d4c1e18ee..58cf020c1 100644
--- a/drivers/avr/apa102.h
+++ b/drivers/apa102/apa102.h
@@ -1,10 +1,5 @@
1/* 1/* Copyright 2020 Aldehir Rojas
2 * light weight WS2812 lib include 2 * Copyright 2017 Mikkel (Duckle29)
3 *
4 * Version 2.3 - Nev 29th 2015
5 * Author: Tim (cpldcpu@gmail.com)
6 *
7 * Please do not change this file! All configuration is handled in "ws2812_config.h"
8 * 3 *
9 * This program is free software: you can redistribute it and/or modify 4 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by 5 * it under the terms of the GNU General Public License as published by
@@ -22,24 +17,25 @@
22 17
23#pragma once 18#pragma once
24 19
25#include <avr/io.h>
26#include <avr/interrupt.h>
27
28#include "color.h" 20#include "color.h"
29 21
22#ifndef APA102_DEFAULT_BRIGHTNESS
23# define APA102_DEFAULT_BRIGHTNESS 31
24#endif
25
26#define APA102_MAX_BRIGHTNESS 31
27
28extern uint8_t apa102_led_brightness;
29
30/* User Interface 30/* User Interface
31 * 31 *
32 * Input: 32 * Input:
33 * ledarray: An array of GRB data describing the LED colors 33 * start_led: An array of GRB data describing the LED colors
34 * number_of_leds: The number of LEDs to write 34 * num_leds: The number of LEDs to write
35 * pinmask (optional): Bitmask describing the output bin. e.g. _BV(PB0)
36 * 35 *
37 * The functions will perform the following actions: 36 * The functions will perform the following actions:
38 * - Set the data-out pin as output 37 * - Set the data-out pin as output
39 * - Send out the LED data 38 * - Send out the LED data
40 * - Wait 50�s to reset the LEDs
41 */ 39 */
42 40void apa102_setleds(LED_TYPE *start_led, uint16_t num_leds);
43void apa102_setleds(LED_TYPE *ledarray, uint16_t number_of_leds); 41void apa102_set_brightness(uint8_t brightness);
44void apa102_setleds_pin(LED_TYPE *ledarray, uint16_t number_of_leds, uint8_t pinmask);
45void apa102_setleds_rgbw(LED_TYPE *ledarray, uint16_t number_of_leds);
diff --git a/drivers/avr/apa102.c b/drivers/avr/apa102.c
deleted file mode 100644
index 740acb573..000000000
--- a/drivers/avr/apa102.c
+++ /dev/null
@@ -1,96 +0,0 @@
1/*
2 * APA102 lib V1.0a
3 *
4 * Controls APA102 RGB-LEDs
5 * Author: Mikkel (Duckle29 on GitHub)
6 *
7 * Dec 22th, 2017 v1.0a Initial Version
8 *
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#include "apa102.h"
24#include <avr/interrupt.h>
25#include <avr/io.h>
26#include <util/delay.h>
27#include "debug.h"
28
29// Setleds for standard RGB
30void inline apa102_setleds(LED_TYPE *ledarray, uint16_t leds) { apa102_setleds_pin(ledarray, leds, _BV(RGB_DI_PIN & 0xF), _BV(RGB_CLK_PIN & 0xF)); }
31
32void static inline apa102_setleds_pin(LED_TYPE *ledarray, uint16_t leds, uint8_t pinmask_DI, uint8_t pinmask_CLK) {
33 setPinOutput(RGB_DI_PIN);
34 setPinOutput(RGB_CLK_PIN);
35
36 apa102_send_array((uint8_t *)ledarray, leds)
37}
38
39void apa102_send_array(uint8_t *data, uint16_t leds) { // Data is struct of 3 bytes. RGB - leds is number of leds in data
40 apa102_start_frame();
41 while (leds--) {
42 apa102_send_frame(0xFF000000 | (data->b << 16) | (data->g << 8) | data->r);
43 data++;
44 }
45 apa102_end_frame(leds);
46}
47
48void apa102_send_frame(uint32_t frame) {
49 for (uint32_t i = 0xFF; i > 0;) {
50 apa102_send_byte(frame & i);
51 i = i << 8;
52 }
53}
54
55void apa102_start_frame() { apa102_send_frame(0); }
56
57void apa102_end_frame(uint16_t leds) {
58 // This function has been taken from: https://github.com/pololu/apa102-arduino/blob/master/APA102.h
59 // and adapted. The code is MIT licensed. I think thats compatible?
60
61 // We need to send some more bytes to ensure that all the LEDs in the
62 // chain see their new color and start displaying it.
63 //
64 // The data stream seen by the last LED in the chain will be delayed by
65 // (count - 1) clock edges, because each LED before it inverts the clock
66 // line and delays the data by one clock edge. Therefore, to make sure
67 // the last LED actually receives the data we wrote, the number of extra
68 // edges we send at the end of the frame must be at least (count - 1).
69 // For the APA102C, that is sufficient.
70 //
71 // The SK9822 only updates after it sees 32 zero bits followed by one more
72 // rising edge. To avoid having the update time depend on the color of
73 // the last LED, we send a dummy 0xFF byte. (Unfortunately, this means
74 // that partial updates of the beginning of an LED strip are not possible;
75 // the LED after the last one you are trying to update will be black.)
76 // After that, to ensure that the last LED in the chain sees 32 zero bits
77 // and a rising edge, we need to send at least 65 + (count - 1) edges. It
78 // is sufficent and simpler to just send (5 + count/16) bytes of zeros.
79 //
80 // We are ignoring the specification for the end frame in the APA102/SK9822
81 // datasheets because it does not actually ensure that all the LEDs will
82 // start displaying their new colors right away.
83
84 apa102_send_byte(0xFF);
85 for (uint16_t i = 0; i < 5 + leds / 16; i++) {
86 apa102_send_byte(0);
87 }
88}
89
90void apa102_send_byte(uint8_t byte) {
91 uint8_t i;
92 for (i = 0; i < 8; i++) {
93 writePin(RGB_DI_PIN, !!(byte & (1 << (7 - i))));
94 writePinHigh(RGB_CLK_PIN);
95 }
96}
diff --git a/drivers/avr/serial.c b/drivers/avr/serial.c
index 526a0946b..3647bee0d 100644
--- a/drivers/avr/serial.c
+++ b/drivers/avr/serial.c
@@ -20,7 +20,7 @@
20 20
21#ifdef SOFT_SERIAL_PIN 21#ifdef SOFT_SERIAL_PIN
22 22
23# if !(defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__)) 23# if !(defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__))
24# error serial.c is not supported for the currently selected MCU 24# error serial.c is not supported for the currently selected MCU
25# endif 25# endif
26// if using ATmega32U4/2, AT90USBxxx I2C, can not use PD0 and PD1 in soft serial. 26// if using ATmega32U4/2, AT90USBxxx I2C, can not use PD0 and PD1 in soft serial.
@@ -52,8 +52,8 @@
52# define EICRx EICRA 52# define EICRx EICRA
53# endif 53# endif
54 54
55// ATmegaxxU2 specific config 55// ATmegaxxU2/AT90USB162 specific config
56# if defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) 56# if defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || defined(__AVR_AT90USB162__)
57// PD4(INT5), PD6(INT6), PD7(INT7), PC7(INT4) 57// PD4(INT5), PD6(INT6), PD7(INT7), PC7(INT4)
58# if SOFT_SERIAL_PIN == D4 58# if SOFT_SERIAL_PIN == D4
59# define EIMSK_BIT _BV(INT5) 59# define EIMSK_BIT _BV(INT5)
diff --git a/drivers/avr/spi_master.c b/drivers/avr/spi_master.c
index cbec9f36e..19ca0ced4 100644
--- a/drivers/avr/spi_master.c
+++ b/drivers/avr/spi_master.c
@@ -20,7 +20,7 @@
20#include "quantum.h" 20#include "quantum.h"
21#include "timer.h" 21#include "timer.h"
22 22
23#if defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) 23#if defined(__AVR_AT90USB162__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__)
24# define SPI_SCK_PIN B1 24# define SPI_SCK_PIN B1
25# define SPI_MOSI_PIN B2 25# define SPI_MOSI_PIN B2
26# define SPI_MISO_PIN B3 26# define SPI_MISO_PIN B3
diff --git a/drivers/avr/spi_master.h b/drivers/avr/spi_master.h
index e36a7c21c..9203698dd 100644
--- a/drivers/avr/spi_master.h
+++ b/drivers/avr/spi_master.h
@@ -21,7 +21,7 @@
21typedef int16_t spi_status_t; 21typedef int16_t spi_status_t;
22 22
23// Hardware SS pin is defined in the header so that user code can refer to it 23// Hardware SS pin is defined in the header so that user code can refer to it
24#if defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) 24#if defined(__AVR_AT90USB162__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__)
25# define SPI_SS_PIN B0 25# define SPI_SS_PIN B0
26#elif defined(__AVR_ATmega32A__) 26#elif defined(__AVR_ATmega32A__)
27# define SPI_SS_PIN B4 27# define SPI_SS_PIN B4
diff --git a/drivers/avr/uart.c b/drivers/avr/uart.c
new file mode 100644
index 000000000..c6abcb6fe
--- /dev/null
+++ b/drivers/avr/uart.c
@@ -0,0 +1,170 @@
1/* UART Example for Teensy USB Development Board
2 * http://www.pjrc.com/teensy/
3 * Copyright (c) 2009 PJRC.COM, LLC
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 * THE SOFTWARE.
22 */
23
24// Version 1.0: Initial Release
25// Version 1.1: Add support for Teensy 2.0, minor optimizations
26
27#include <avr/io.h>
28#include <avr/interrupt.h>
29
30#include "uart.h"
31
32#if defined(__AVR_AT90USB162__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__)
33# define UDRn UDR1
34# define UBRRnL UBRR1L
35# define UCSRnA UCSR1A
36# define UCSRnB UCSR1B
37# define UCSRnC UCSR1C
38# define U2Xn U2X1
39# define RXENn RXEN1
40# define TXENn TXEN1
41# define RXCIEn RXCIE1
42# define UCSZn1 UCSZ11
43# define UCSZn0 UCSZ10
44# define UDRIEn UDRIE1
45# define USARTn_UDRE_vect USART1_UDRE_vect
46# define USARTn_RX_vect USART1_RX_vect
47#elif defined(__AVR_ATmega32A__)
48# define UDRn UDR
49# define UBRRnL UBRRL
50# define UCSRnA UCSRA
51# define UCSRnB UCSRB
52# define UCSRnC UCSRC
53# define U2Xn U2X
54# define RXENn RXEN
55# define TXENn TXEN
56# define RXCIEn RXCIE
57# define UCSZn1 UCSZ1
58# define UCSZn0 UCSZ0
59# define UDRIEn UDRIE
60# define USARTn_UDRE_vect USART_UDRE_vect
61# define USARTn_RX_vect USART_RX_vect
62#elif defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__)
63# define UDRn UDR0
64# define UBRRnL UBRR0L
65# define UCSRnA UCSR0A
66# define UCSRnB UCSR0B
67# define UCSRnC UCSR0C
68# define U2Xn U2X0
69# define RXENn RXEN0
70# define TXENn TXEN0
71# define RXCIEn RXCIE0
72# define UCSZn1 UCSZ01
73# define UCSZn0 UCSZ00
74# define UDRIEn UDRIE0
75# define USARTn_UDRE_vect USART_UDRE_vect
76# define USARTn_RX_vect USART_RX_vect
77#endif
78
79// These buffers may be any size from 2 to 256 bytes.
80#define RX_BUFFER_SIZE 64
81#define TX_BUFFER_SIZE 256
82
83static volatile uint8_t tx_buffer[TX_BUFFER_SIZE];
84static volatile uint8_t tx_buffer_head;
85static volatile uint8_t tx_buffer_tail;
86static volatile uint8_t rx_buffer[RX_BUFFER_SIZE];
87static volatile uint8_t rx_buffer_head;
88static volatile uint8_t rx_buffer_tail;
89
90// Initialize the UART
91void uart_init(uint32_t baud) {
92 cli();
93 UBRRnL = (F_CPU / 4 / baud - 1) / 2;
94 UCSRnA = (1 << U2Xn);
95 UCSRnB = (1 << RXENn) | (1 << TXENn) | (1 << RXCIEn);
96 UCSRnC = (1 << UCSZn1) | (1 << UCSZn0);
97 tx_buffer_head = tx_buffer_tail = 0;
98 rx_buffer_head = rx_buffer_tail = 0;
99 sei();
100}
101
102// Transmit a byte
103void uart_putchar(uint8_t c) {
104 uint8_t i;
105
106 i = tx_buffer_head + 1;
107 if (i >= TX_BUFFER_SIZE) i = 0;
108 // return immediately to avoid deadlock when interrupt is disabled(called from ISR)
109 if (tx_buffer_tail == i && (SREG & (1 << SREG_I)) == 0) return;
110 while (tx_buffer_tail == i)
111 ; // wait until space in buffer
112 // cli();
113 tx_buffer[i] = c;
114 tx_buffer_head = i;
115 UCSRnB = (1 << RXENn) | (1 << TXENn) | (1 << RXCIEn) | (1 << UDRIEn);
116 // sei();
117}
118
119// Receive a byte
120uint8_t uart_getchar(void) {
121 uint8_t c, i;
122
123 while (rx_buffer_head == rx_buffer_tail)
124 ; // wait for character
125 i = rx_buffer_tail + 1;
126 if (i >= RX_BUFFER_SIZE) i = 0;
127 c = rx_buffer[i];
128 rx_buffer_tail = i;
129 return c;
130}
131
132// Return whether the number of bytes waiting in the receive buffer is nonzero.
133// Call this before uart_getchar() to check if it will need
134// to wait for a byte to arrive.
135bool uart_available(void) {
136 uint8_t head, tail;
137
138 head = rx_buffer_head;
139 tail = rx_buffer_tail;
140 if (head >= tail) return (head - tail) > 0;
141 return (RX_BUFFER_SIZE + head - tail) > 0;
142}
143
144// Transmit Interrupt
145ISR(USARTn_UDRE_vect) {
146 uint8_t i;
147
148 if (tx_buffer_head == tx_buffer_tail) {
149 // buffer is empty, disable transmit interrupt
150 UCSRnB = (1 << RXENn) | (1 << TXENn) | (1 << RXCIEn);
151 } else {
152 i = tx_buffer_tail + 1;
153 if (i >= TX_BUFFER_SIZE) i = 0;
154 UDRn = tx_buffer[i];
155 tx_buffer_tail = i;
156 }
157}
158
159// Receive Interrupt
160ISR(USARTn_RX_vect) {
161 uint8_t c, i;
162
163 c = UDRn;
164 i = rx_buffer_head + 1;
165 if (i >= RX_BUFFER_SIZE) i = 0;
166 if (i != rx_buffer_tail) {
167 rx_buffer[i] = c;
168 rx_buffer_head = i;
169 }
170}
diff --git a/drivers/avr/uart.h b/drivers/avr/uart.h
new file mode 100644
index 000000000..602eb3d8b
--- /dev/null
+++ b/drivers/avr/uart.h
@@ -0,0 +1,35 @@
1/* UART Example for Teensy USB Development Board
2 * http://www.pjrc.com/teensy/
3 * Copyright (c) 2009 PJRC.COM, LLC
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 * THE SOFTWARE.
22 */
23
24#pragma once
25
26#include <stdint.h>
27#include <stdbool.h>
28
29void uart_init(uint32_t baud);
30
31void uart_putchar(uint8_t c);
32
33uint8_t uart_getchar(void);
34
35bool uart_available(void);
diff --git a/drivers/chibios/serial_usart.c b/drivers/chibios/serial_usart.c
index a3e21f90b..7c81b1646 100644
--- a/drivers/chibios/serial_usart.c
+++ b/drivers/chibios/serial_usart.c
@@ -58,7 +58,10 @@
58# error invalid SELECT_SOFT_SERIAL_SPEED value 58# error invalid SELECT_SOFT_SERIAL_SPEED value
59#endif 59#endif
60 60
61#define TIMEOUT 100 61#ifndef SERIAL_USART_TIMEOUT
62# define SERIAL_USART_TIMEOUT 100
63#endif
64
62#define HANDSHAKE_MAGIC 7 65#define HANDSHAKE_MAGIC 7
63 66
64static inline msg_t sdWriteHalfDuplex(SerialDriver* driver, uint8_t* data, uint8_t size) { 67static inline msg_t sdWriteHalfDuplex(SerialDriver* driver, uint8_t* data, uint8_t size) {
@@ -201,21 +204,21 @@ int soft_serial_transaction(int index) {
201 sdClear(&SERIAL_USART_DRIVER); 204 sdClear(&SERIAL_USART_DRIVER);
202 205
203 // First chunk is always transaction id 206 // First chunk is always transaction id
204 sdWriteTimeout(&SERIAL_USART_DRIVER, &sstd_index, sizeof(sstd_index), TIME_MS2I(TIMEOUT)); 207 sdWriteTimeout(&SERIAL_USART_DRIVER, &sstd_index, sizeof(sstd_index), TIME_MS2I(SERIAL_USART_TIMEOUT));
205 208
206 uint8_t sstd_index_shake = 0xFF; 209 uint8_t sstd_index_shake = 0xFF;
207 210
208 // Which we always read back first so that we can error out correctly 211 // Which we always read back first so that we can error out correctly
209 // - due to the half duplex limitations on return codes, we always have to read *something* 212 // - due to the half duplex limitations on return codes, we always have to read *something*
210 // - without the read, write only transactions *always* succeed, even during the boot process where the slave is not ready 213 // - without the read, write only transactions *always* succeed, even during the boot process where the slave is not ready
211 res = sdReadTimeout(&SERIAL_USART_DRIVER, &sstd_index_shake, sizeof(sstd_index_shake), TIME_MS2I(TIMEOUT)); 214 res = sdReadTimeout(&SERIAL_USART_DRIVER, &sstd_index_shake, sizeof(sstd_index_shake), TIME_MS2I(SERIAL_USART_TIMEOUT));
212 if (res < 0 || (sstd_index_shake != (sstd_index ^ HANDSHAKE_MAGIC))) { 215 if (res < 0 || (sstd_index_shake != (sstd_index ^ HANDSHAKE_MAGIC))) {
213 dprintf("serial::usart_shake NO_RESPONSE\n"); 216 dprintf("serial::usart_shake NO_RESPONSE\n");
214 return TRANSACTION_NO_RESPONSE; 217 return TRANSACTION_NO_RESPONSE;
215 } 218 }
216 219
217 if (trans->initiator2target_buffer_size) { 220 if (trans->initiator2target_buffer_size) {
218 res = sdWriteTimeout(&SERIAL_USART_DRIVER, trans->initiator2target_buffer, trans->initiator2target_buffer_size, TIME_MS2I(TIMEOUT)); 221 res = sdWriteTimeout(&SERIAL_USART_DRIVER, trans->initiator2target_buffer, trans->initiator2target_buffer_size, TIME_MS2I(SERIAL_USART_TIMEOUT));
219 if (res < 0) { 222 if (res < 0) {
220 dprintf("serial::usart_transmit NO_RESPONSE\n"); 223 dprintf("serial::usart_transmit NO_RESPONSE\n");
221 return TRANSACTION_NO_RESPONSE; 224 return TRANSACTION_NO_RESPONSE;
@@ -223,7 +226,7 @@ int soft_serial_transaction(int index) {
223 } 226 }
224 227
225 if (trans->target2initiator_buffer_size) { 228 if (trans->target2initiator_buffer_size) {
226 res = sdReadTimeout(&SERIAL_USART_DRIVER, trans->target2initiator_buffer, trans->target2initiator_buffer_size, TIME_MS2I(TIMEOUT)); 229 res = sdReadTimeout(&SERIAL_USART_DRIVER, trans->target2initiator_buffer, trans->target2initiator_buffer_size, TIME_MS2I(SERIAL_USART_TIMEOUT));
227 if (res < 0) { 230 if (res < 0) {
228 dprintf("serial::usart_receive NO_RESPONSE\n"); 231 dprintf("serial::usart_receive NO_RESPONSE\n");
229 return TRANSACTION_NO_RESPONSE; 232 return TRANSACTION_NO_RESPONSE;
diff --git a/drivers/chibios/uart.c b/drivers/chibios/uart.c
new file mode 100644
index 000000000..6e94899b9
--- /dev/null
+++ b/drivers/chibios/uart.c
@@ -0,0 +1,59 @@
1/* Copyright 2021
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <https://www.gnu.org/licenses/>.
15 */
16
17#include "uart.h"
18
19#include "quantum.h"
20
21static SerialConfig serialConfig = {
22 SERIAL_DEFAULT_BITRATE,
23 SD1_CR1,
24 SD1_CR2,
25 SD1_CR3
26};
27
28void uart_init(uint32_t baud) {
29 static bool is_initialised = false;
30
31 if (!is_initialised) {
32 is_initialised = true;
33
34 serialConfig.speed = baud;
35
36#if defined(USE_GPIOV1)
37 palSetLineMode(SD1_TX_PIN, PAL_MODE_STM32_ALTERNATE_OPENDRAIN);
38 palSetLineMode(SD1_RX_PIN, PAL_MODE_STM32_ALTERNATE_OPENDRAIN);
39#else
40 palSetLineMode(SD1_TX_PIN, PAL_MODE_ALTERNATE(SD1_TX_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN);
41 palSetLineMode(SD1_RX_PIN, PAL_MODE_ALTERNATE(SD1_RX_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN);
42#endif
43 sdStart(&SERIAL_DRIVER, &serialConfig);
44 }
45}
46
47void uart_putchar(uint8_t c) {
48 sdPut(&SERIAL_DRIVER, c);
49}
50
51uint8_t uart_getchar(void) {
52 msg_t res = sdGet(&SERIAL_DRIVER);
53
54 return (uint8_t)res;
55}
56
57bool uart_available(void) {
58 return !sdGetWouldBlock(&SERIAL_DRIVER);
59}
diff --git a/drivers/chibios/uart.h b/drivers/chibios/uart.h
new file mode 100644
index 000000000..b4e20e9fd
--- /dev/null
+++ b/drivers/chibios/uart.h
@@ -0,0 +1,77 @@
1/* Copyright 2021
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <https://www.gnu.org/licenses/>.
15 */
16
17#pragma once
18
19#include <stdint.h>
20
21#include <hal.h>
22
23#ifndef SERIAL_DRIVER
24# define SERIAL_DRIVER SD1
25#endif
26
27#ifndef SD1_TX_PIN
28# define SD1_TX_PIN A9
29#endif
30
31#ifndef SD1_TX_PAL_MODE
32# define SD1_TX_PAL_MODE 7
33#endif
34
35#ifndef SD1_RX_PIN
36# define SD1_RX_PIN A10
37#endif
38
39#ifndef SD1_RX_PAL_MODE
40# define SD1_RX_PAL_MODE 7
41#endif
42
43#ifndef SD1_CTS_PIN
44# define SD1_CTS_PIN A11
45#endif
46
47#ifndef SD1_CTS_PAL_MODE
48# define SD1_CTS_PAL_MODE 7
49#endif
50
51#ifndef SD1_RTS_PIN
52# define SD1_RTS_PIN A12
53#endif
54
55#ifndef SD1_RTS_PAL_MODE
56# define SD1_RTS_PAL_MODE 7
57#endif
58
59#ifndef SD1_CR1
60# define SD1_CR1 0
61#endif
62
63#ifndef SD1_CR2
64# define SD1_CR2 0
65#endif
66
67#ifndef SD1_CR3
68# define SD1_CR3 0
69#endif
70
71void uart_init(uint32_t baud);
72
73void uart_putchar(uint8_t c);
74
75uint8_t uart_getchar(void);
76
77bool uart_available(void);
diff --git a/drivers/qwiic/qwiic.mk b/drivers/qwiic/qwiic.mk
index b23c25657..164bd7210 100644
--- a/drivers/qwiic/qwiic.mk
+++ b/drivers/qwiic/qwiic.mk
@@ -1,16 +1,17 @@
1ifneq ($(strip $(QWIIC_ENABLE)),) 1ifeq ($(strip $(QWIIC_ENABLE)),yes)
2 COMMON_VPATH += $(DRIVER_PATH)/qwiic 2 COMMON_VPATH += $(DRIVER_PATH)/qwiic
3 OPT_DEFS += -DQWIIC_ENABLE 3 OPT_DEFS += -DQWIIC_ENABLE
4 SRC += qwiic.c 4 SRC += qwiic.c
5 QUANTUM_LIB_SRC += i2c_master.c 5 QUANTUM_LIB_SRC += i2c_master.c
6endif
7 6
8ifneq ($(filter JOYSTIIC, $(QWIIC_ENABLE)),) 7ifneq ($(filter JOYSTIIC, $(QWIIC_DRIVERS)),)
9 OPT_DEFS += -DQWIIC_JOYSTIIC_ENABLE 8 OPT_DEFS += -DQWIIC_JOYSTIIC_ENABLE
10 SRC += joystiic.c 9 SRC += joystiic.c
11endif 10endif
12 11
13ifneq ($(filter MICRO_OLED, $(QWIIC_ENABLE)),) 12ifneq ($(filter MICRO_OLED, $(QWIIC_DRIVERS)),)
14 OPT_DEFS += -DQWIIC_MICRO_OLED_ENABLE 13 OPT_DEFS += -DQWIIC_MICRO_OLED_ENABLE
15 SRC += micro_oled.c 14 SRC += micro_oled.c
16endif 15endif
16
17endif