diff options
Diffstat (limited to 'platforms/avr')
| -rw-r--r-- | platforms/avr/_wait.h | 38 | ||||
| -rw-r--r-- | platforms/avr/drivers/i2c_master.c | 12 | ||||
| -rw-r--r-- | platforms/avr/drivers/i2c_master.h | 2 | ||||
| -rw-r--r-- | platforms/avr/drivers/ps2/ps2_usart.c | 4 | ||||
| -rw-r--r-- | platforms/avr/drivers/ssd1306.c | 329 | ||||
| -rw-r--r-- | platforms/avr/drivers/ssd1306.h | 87 | ||||
| -rw-r--r-- | platforms/avr/platform.mk | 3 | 
7 files changed, 41 insertions, 434 deletions
| diff --git a/platforms/avr/_wait.h b/platforms/avr/_wait.h index 683db6ae57..c1a598a428 100644 --- a/platforms/avr/_wait.h +++ b/platforms/avr/_wait.h @@ -17,6 +17,26 @@  #include <util/delay.h> +// http://ww1.microchip.com/downloads/en/devicedoc/atmel-0856-avr-instruction-set-manual.pdf +// page 22: Table 4-2. Arithmetic and Logic Instructions +/* +    for (uint16_t i = times; i > 0; i--) { +        __builtin_avr_delay_cycles(1); +    } + +    .L3:  sbiw r24,0  // loop step 1 +          brne .L4    // loop step 2 +          ret +    .L4:  nop         // __builtin_avr_delay_cycles(1); +          sbiw r24,1  // loop step 3 +          rjmp .L3    // loop step 4 +*/ + +#define AVR_sbiw_clocks 2 +#define AVR_rjmp_clocks 2 +#define AVR_brne_clocks 2 +#define AVR_WAIT_LOOP_OVERHEAD (AVR_sbiw_clocks + AVR_brne_clocks + AVR_sbiw_clocks + AVR_rjmp_clocks) +  #define wait_ms(ms)                             \      do {                                        \          if (__builtin_constant_p(ms)) {         \ @@ -27,15 +47,15 @@              }                                   \          }                                       \      } while (0) -#define wait_us(us)                             \ -    do {                                        \ -        if (__builtin_constant_p(us)) {         \ -            _delay_us(us);                      \ -        } else {                                \ -            for (uint16_t i = us; i > 0; i--) { \ -                _delay_us(1);                   \ -            }                                   \ -        }                                       \ +#define wait_us(us)                                                                     \ +    do {                                                                                \ +        if (__builtin_constant_p(us)) {                                                 \ +            _delay_us(us);                                                              \ +        } else {                                                                        \ +            for (uint16_t i = us; i > 0; i--) {                                         \ +                __builtin_avr_delay_cycles((F_CPU / 1000000) - AVR_WAIT_LOOP_OVERHEAD); \ +            }                                                                           \ +        }                                                                               \      } while (0)  #define wait_cpuclock(n) __builtin_avr_delay_cycles(n)  #define CPU_CLOCK F_CPU diff --git a/platforms/avr/drivers/i2c_master.c b/platforms/avr/drivers/i2c_master.c index c1a7b5f72d..524494c99d 100644 --- a/platforms/avr/drivers/i2c_master.c +++ b/platforms/avr/drivers/i2c_master.c @@ -64,7 +64,7 @@ static i2c_status_t i2c_start_impl(uint8_t address, uint16_t timeout) {      uint16_t timeout_timer = timer_read();      while (!(TWCR & (1 << TWINT))) { -        if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { +        if ((timeout != I2C_TIMEOUT_INFINITE) && (timer_elapsed(timeout_timer) > timeout)) {              return I2C_STATUS_TIMEOUT;          }      } @@ -81,7 +81,7 @@ static i2c_status_t i2c_start_impl(uint8_t address, uint16_t timeout) {      timeout_timer = timer_read();      while (!(TWCR & (1 << TWINT))) { -        if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { +        if ((timeout != I2C_TIMEOUT_INFINITE) && (timer_elapsed(timeout_timer) > timeout)) {              return I2C_STATUS_TIMEOUT;          }      } @@ -102,7 +102,7 @@ i2c_status_t i2c_start(uint8_t address, uint16_t timeout) {      i2c_status_t status;      do {          status = i2c_start_impl(address, time_slice); -    } while ((status < 0) && ((timeout == I2C_TIMEOUT_INFINITE) || (timer_elapsed(timeout_timer) < timeout))); +    } while ((status < 0) && ((timeout == I2C_TIMEOUT_INFINITE) || (timer_elapsed(timeout_timer) <= timeout)));      return status;  } @@ -114,7 +114,7 @@ i2c_status_t i2c_write(uint8_t data, uint16_t timeout) {      uint16_t timeout_timer = timer_read();      while (!(TWCR & (1 << TWINT))) { -        if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { +        if ((timeout != I2C_TIMEOUT_INFINITE) && (timer_elapsed(timeout_timer) > timeout)) {              return I2C_STATUS_TIMEOUT;          }      } @@ -132,7 +132,7 @@ int16_t i2c_read_ack(uint16_t timeout) {      uint16_t timeout_timer = timer_read();      while (!(TWCR & (1 << TWINT))) { -        if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { +        if ((timeout != I2C_TIMEOUT_INFINITE) && (timer_elapsed(timeout_timer) > timeout)) {              return I2C_STATUS_TIMEOUT;          }      } @@ -147,7 +147,7 @@ int16_t i2c_read_nack(uint16_t timeout) {      uint16_t timeout_timer = timer_read();      while (!(TWCR & (1 << TWINT))) { -        if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { +        if ((timeout != I2C_TIMEOUT_INFINITE) && (timer_elapsed(timeout_timer) > timeout)) {              return I2C_STATUS_TIMEOUT;          }      } diff --git a/platforms/avr/drivers/i2c_master.h b/platforms/avr/drivers/i2c_master.h index 2d95846db5..04ef126c80 100644 --- a/platforms/avr/drivers/i2c_master.h +++ b/platforms/avr/drivers/i2c_master.h @@ -19,6 +19,8 @@  #pragma once +#include <stdint.h> +  #define I2C_READ 0x01  #define I2C_WRITE 0x00 diff --git a/platforms/avr/drivers/ps2/ps2_usart.c b/platforms/avr/drivers/ps2/ps2_usart.c index 39ec930d4a..581badac64 100644 --- a/platforms/avr/drivers/ps2/ps2_usart.c +++ b/platforms/avr/drivers/ps2/ps2_usart.c @@ -72,8 +72,8 @@ uint8_t ps2_error = PS2_ERR_NONE;  static inline uint8_t pbuf_dequeue(void);  static inline void    pbuf_enqueue(uint8_t data); -static inline bool    pbuf_has_data(void);  static inline void    pbuf_clear(void); +bool                  pbuf_has_data(void);  void ps2_host_init(void) {      idle(); // without this many USART errors occur when cable is disconnected @@ -212,7 +212,7 @@ static inline uint8_t pbuf_dequeue(void) {      return val;  } -static inline bool pbuf_has_data(void) { +bool pbuf_has_data(void) {      uint8_t sreg = SREG;      cli();      bool has_data = (pbuf_head != pbuf_tail); diff --git a/platforms/avr/drivers/ssd1306.c b/platforms/avr/drivers/ssd1306.c deleted file mode 100644 index 7afbc09f00..0000000000 --- a/platforms/avr/drivers/ssd1306.c +++ /dev/null @@ -1,329 +0,0 @@ -#ifdef SSD1306OLED - -#    include "ssd1306.h" -#    include "i2c.h" -#    include <string.h> -#    include "print.h" -#    include "glcdfont.c" -#    ifdef PROTOCOL_LUFA -#        include "lufa.h" -#    endif -#    include "sendchar.h" -#    include "timer.h" - -struct CharacterMatrix display; - -// Set this to 1 to help diagnose early startup problems -// when testing power-on with ble.  Turn it off otherwise, -// as the latency of printing most of the debug info messes -// with the matrix scan, causing keys to drop. -#    define DEBUG_TO_SCREEN 0 - -// static uint16_t last_battery_update; -// static uint32_t vbat; -//#define BatteryUpdateInterval 10000 /* milliseconds */ -#    define ScreenOffInterval 300000 /* milliseconds */ -#    if DEBUG_TO_SCREEN -static uint8_t displaying; -#    endif -static uint16_t last_flush; - -// Write command sequence. -// Returns true on success. -static inline bool _send_cmd1(uint8_t cmd) { -    bool res = false; - -    if (i2c_start_write(SSD1306_ADDRESS)) { -        xprintf("failed to start write to %d\n", SSD1306_ADDRESS); -        goto done; -    } - -    if (i2c_master_write(0x0 /* command byte follows */)) { -        print("failed to write control byte\n"); - -        goto done; -    } - -    if (i2c_master_write(cmd)) { -        xprintf("failed to write command %d\n", cmd); -        goto done; -    } -    res = true; -done: -    i2c_master_stop(); -    return res; -} - -// Write 2-byte command sequence. -// Returns true on success -static inline bool _send_cmd2(uint8_t cmd, uint8_t opr) { -    if (!_send_cmd1(cmd)) { -        return false; -    } -    return _send_cmd1(opr); -} - -// Write 3-byte command sequence. -// Returns true on success -static inline bool _send_cmd3(uint8_t cmd, uint8_t opr1, uint8_t opr2) { -    if (!_send_cmd1(cmd)) { -        return false; -    } -    if (!_send_cmd1(opr1)) { -        return false; -    } -    return _send_cmd1(opr2); -} - -#    define send_cmd1(c)      \ -        if (!_send_cmd1(c)) { \ -            goto done;        \ -        } -#    define send_cmd2(c, o)      \ -        if (!_send_cmd2(c, o)) { \ -            goto done;           \ -        } -#    define send_cmd3(c, o1, o2)      \ -        if (!_send_cmd3(c, o1, o2)) { \ -            goto done;                \ -        } - -static void clear_display(void) { -    matrix_clear(&display); - -    // Clear all of the display bits (there can be random noise -    // in the RAM on startup) -    send_cmd3(PageAddr, 0, (DisplayHeight / 8) - 1); -    send_cmd3(ColumnAddr, 0, DisplayWidth - 1); - -    if (i2c_start_write(SSD1306_ADDRESS)) { -        goto done; -    } -    if (i2c_master_write(0x40)) { -        // Data mode -        goto done; -    } -    for (uint8_t row = 0; row < MatrixRows; ++row) { -        for (uint8_t col = 0; col < DisplayWidth; ++col) { -            i2c_master_write(0); -        } -    } - -    display.dirty = false; - -done: -    i2c_master_stop(); -} - -#    if DEBUG_TO_SCREEN -#        undef sendchar -static int8_t capture_sendchar(uint8_t c) { -    sendchar(c); -    iota_gfx_write_char(c); - -    if (!displaying) { -        iota_gfx_flush(); -    } -    return 0; -} -#    endif - -bool iota_gfx_init(void) { -    bool success = false; - -    send_cmd1(DisplayOff); -    send_cmd2(SetDisplayClockDiv, 0x80); -    send_cmd2(SetMultiPlex, DisplayHeight - 1); - -    send_cmd2(SetDisplayOffset, 0); - -    send_cmd1(SetStartLine | 0x0); -    send_cmd2(SetChargePump, 0x14 /* Enable */); -    send_cmd2(SetMemoryMode, 0 /* horizontal addressing */); - -#    ifdef OLED_ROTATE180 -    // the following Flip the display orientation 180 degrees -    send_cmd1(SegRemap); -    send_cmd1(ComScanInc); -#    endif -#    ifndef OLED_ROTATE180 -    // Flips the display orientation 0 degrees -    send_cmd1(SegRemap | 0x1); -    send_cmd1(ComScanDec); -#    endif - -    send_cmd2(SetComPins, 0x2); -    send_cmd2(SetContrast, 0x8f); -    send_cmd2(SetPreCharge, 0xf1); -    send_cmd2(SetVComDetect, 0x40); -    send_cmd1(DisplayAllOnResume); -    send_cmd1(NormalDisplay); -    send_cmd1(DeActivateScroll); -    send_cmd1(DisplayOn); - -    send_cmd2(SetContrast, 0); // Dim - -    clear_display(); - -    success = true; - -    iota_gfx_flush(); - -#    if DEBUG_TO_SCREEN -    print_set_sendchar(capture_sendchar); -#    endif - -done: -    return success; -} - -bool iota_gfx_off(void) { -    bool success = false; - -    send_cmd1(DisplayOff); -    success = true; - -done: -    return success; -} - -bool iota_gfx_on(void) { -    bool success = false; - -    send_cmd1(DisplayOn); -    success = true; - -done: -    return success; -} - -void matrix_write_char_inner(struct CharacterMatrix *matrix, uint8_t c) { -    *matrix->cursor = c; -    ++matrix->cursor; - -    if (matrix->cursor - &matrix->display[0][0] == sizeof(matrix->display)) { -        // We went off the end; scroll the display upwards by one line -        memmove(&matrix->display[0], &matrix->display[1], MatrixCols * (MatrixRows - 1)); -        matrix->cursor = &matrix->display[MatrixRows - 1][0]; -        memset(matrix->cursor, ' ', MatrixCols); -    } -} - -void matrix_write_char(struct CharacterMatrix *matrix, uint8_t c) { -    matrix->dirty = true; - -    if (c == '\n') { -        // Clear to end of line from the cursor and then move to the -        // start of the next line -        uint8_t cursor_col = (matrix->cursor - &matrix->display[0][0]) % MatrixCols; - -        while (cursor_col++ < MatrixCols) { -            matrix_write_char_inner(matrix, ' '); -        } -        return; -    } - -    matrix_write_char_inner(matrix, c); -} - -void iota_gfx_write_char(uint8_t c) { -    matrix_write_char(&display, c); -} - -void matrix_write(struct CharacterMatrix *matrix, const char *data) { -    const char *end = data + strlen(data); -    while (data < end) { -        matrix_write_char(matrix, *data); -        ++data; -    } -} - -void iota_gfx_write(const char *data) { -    matrix_write(&display, data); -} - -void matrix_write_P(struct CharacterMatrix *matrix, const char *data) { -    while (true) { -        uint8_t c = pgm_read_byte(data); -        if (c == 0) { -            return; -        } -        matrix_write_char(matrix, c); -        ++data; -    } -} - -void iota_gfx_write_P(const char *data) { -    matrix_write_P(&display, data); -} - -void matrix_clear(struct CharacterMatrix *matrix) { -    memset(matrix->display, ' ', sizeof(matrix->display)); -    matrix->cursor = &matrix->display[0][0]; -    matrix->dirty  = true; -} - -void iota_gfx_clear_screen(void) { -    matrix_clear(&display); -} - -void matrix_render(struct CharacterMatrix *matrix) { -    last_flush = timer_read(); -    iota_gfx_on(); -#    if DEBUG_TO_SCREEN -    ++displaying; -#    endif - -    // Move to the home position -    send_cmd3(PageAddr, 0, MatrixRows - 1); -    send_cmd3(ColumnAddr, 0, (MatrixCols * FontWidth) - 1); - -    if (i2c_start_write(SSD1306_ADDRESS)) { -        goto done; -    } -    if (i2c_master_write(0x40)) { -        // Data mode -        goto done; -    } - -    for (uint8_t row = 0; row < MatrixRows; ++row) { -        for (uint8_t col = 0; col < MatrixCols; ++col) { -            const uint8_t *glyph = font + (matrix->display[row][col] * (FontWidth - 1)); - -            for (uint8_t glyphCol = 0; glyphCol < FontWidth - 1; ++glyphCol) { -                uint8_t colBits = pgm_read_byte(glyph + glyphCol); -                i2c_master_write(colBits); -            } - -            // 1 column of space between chars (it's not included in the glyph) -            i2c_master_write(0); -        } -    } - -    matrix->dirty = false; - -done: -    i2c_master_stop(); -#    if DEBUG_TO_SCREEN -    --displaying; -#    endif -} - -void iota_gfx_flush(void) { -    matrix_render(&display); -} - -__attribute__((weak)) void iota_gfx_task_user(void) {} - -void iota_gfx_task(void) { -    iota_gfx_task_user(); - -    if (display.dirty) { -        iota_gfx_flush(); -    } - -    if (timer_elapsed(last_flush) > ScreenOffInterval) { -        iota_gfx_off(); -    } -} -#endif diff --git a/platforms/avr/drivers/ssd1306.h b/platforms/avr/drivers/ssd1306.h deleted file mode 100644 index 6eecdcfaa4..0000000000 --- a/platforms/avr/drivers/ssd1306.h +++ /dev/null @@ -1,87 +0,0 @@ -#pragma once - -#include <stdbool.h> -#include <stdio.h> -#include "config.h" - -enum ssd1306_cmds { -    DisplayOff = 0xAE, -    DisplayOn  = 0xAF, - -    SetContrast        = 0x81, -    DisplayAllOnResume = 0xA4, - -    DisplayAllOn       = 0xA5, -    NormalDisplay      = 0xA6, -    InvertDisplay      = 0xA7, -    SetDisplayOffset   = 0xD3, -    SetComPins         = 0xda, -    SetVComDetect      = 0xdb, -    SetDisplayClockDiv = 0xD5, -    SetPreCharge       = 0xd9, -    SetMultiPlex       = 0xa8, -    SetLowColumn       = 0x00, -    SetHighColumn      = 0x10, -    SetStartLine       = 0x40, - -    SetMemoryMode = 0x20, -    ColumnAddr    = 0x21, -    PageAddr      = 0x22, - -    ComScanInc    = 0xc0, -    ComScanDec    = 0xc8, -    SegRemap      = 0xa0, -    SetChargePump = 0x8d, -    ExternalVcc   = 0x01, -    SwitchCapVcc  = 0x02, - -    ActivateScroll                   = 0x2f, -    DeActivateScroll                 = 0x2e, -    SetVerticalScrollArea            = 0xa3, -    RightHorizontalScroll            = 0x26, -    LeftHorizontalScroll             = 0x27, -    VerticalAndRightHorizontalScroll = 0x29, -    VerticalAndLeftHorizontalScroll  = 0x2a, -}; - -// Controls the SSD1306 128x32 OLED display via i2c - -#ifndef SSD1306_ADDRESS -#    define SSD1306_ADDRESS 0x3C -#endif - -#define DisplayHeight 32 -#define DisplayWidth 128 - -#define FontHeight 8 -#define FontWidth 6 - -#define MatrixRows (DisplayHeight / FontHeight) -#define MatrixCols (DisplayWidth / FontWidth) - -struct CharacterMatrix { -    uint8_t  display[MatrixRows][MatrixCols]; -    uint8_t *cursor; -    bool     dirty; -}; - -extern struct CharacterMatrix display; - -bool iota_gfx_init(void); -void iota_gfx_task(void); -bool iota_gfx_off(void); -bool iota_gfx_on(void); -void iota_gfx_flush(void); -void iota_gfx_write_char(uint8_t c); -void iota_gfx_write(const char *data); -void iota_gfx_write_P(const char *data); -void iota_gfx_clear_screen(void); - -void iota_gfx_task_user(void); - -void matrix_clear(struct CharacterMatrix *matrix); -void matrix_write_char_inner(struct CharacterMatrix *matrix, uint8_t c); -void matrix_write_char(struct CharacterMatrix *matrix, uint8_t c); -void matrix_write(struct CharacterMatrix *matrix, const char *data); -void matrix_write_P(struct CharacterMatrix *matrix, const char *data); -void matrix_render(struct CharacterMatrix *matrix); diff --git a/platforms/avr/platform.mk b/platforms/avr/platform.mk index 978199b385..39a11b28e4 100644 --- a/platforms/avr/platform.mk +++ b/platforms/avr/platform.mk @@ -24,6 +24,7 @@ COMPILEFLAGS += -fdata-sections  COMPILEFLAGS += -fpack-struct  COMPILEFLAGS += -fshort-enums  COMPILEFLAGS += -mcall-prologues +COMPILEFLAGS += -fno-builtin-printf  # Linker relaxation is only possible if  # link time optimizations are not enabled. @@ -38,7 +39,7 @@ CFLAGS += -fno-inline-small-functions  CFLAGS += -fno-strict-aliasing  CXXFLAGS += $(COMPILEFLAGS) -CXXFLAGS += -fno-exceptions -std=c++11 +CXXFLAGS += -fno-exceptions $(CXXSTANDARD)  LDFLAGS += -Wl,--gc-sections | 
