Convert Spi and GFX to C++.
This commit is contained in:
		
							parent
							
								
									0db16bd827
								
							
						
					
					
						commit
						6fbb6c8f70
					
				@ -263,12 +263,6 @@ macro(nRF5x_setup)
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    list(APPEND SDK_SOURCE_FILES
 | 
			
		||||
      "${NRF5_SDK_PATH}/components/libraries/gfx/nrf_gfx.c"
 | 
			
		||||
#      "${NRF5_SDK_PATH}/integration/nrfx/legacy/nrf_drv_spi.c"
 | 
			
		||||
#      "${NRF5_SDK_PATH}/modules/nrfx/drivers/src/nrfx_spim.c"
 | 
			
		||||
#      "${NRF5_SDK_PATH}/modules/nrfx/drivers/src/prs/nrfx_prs.c"
 | 
			
		||||
 | 
			
		||||
#      "${NRF5_SDK_PATH}/components/drivers_ext/st7735/st7735.c"
 | 
			
		||||
      "${NRF5_SDK_PATH}/external/thedotfactory_fonts/orkney24pts.c"
 | 
			
		||||
      )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -33,8 +33,9 @@ list(APPEND SOURCE_FILES
 | 
			
		||||
  DisplayApp/DisplayApp.cpp
 | 
			
		||||
  DisplayApp/lcdfont.c
 | 
			
		||||
  main.cpp
 | 
			
		||||
  drivers/st7789.cpp
 | 
			
		||||
  drivers/spi_master_fast.cpp
 | 
			
		||||
  drivers/St7789.cpp
 | 
			
		||||
  drivers/SpiMaster.cpp
 | 
			
		||||
  Components/Gfx/Gfx.cpp
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
set(INCLUDE_FILES
 | 
			
		||||
@ -43,8 +44,9 @@ set(INCLUDE_FILES
 | 
			
		||||
  BlinkApp/BlinkApp.h
 | 
			
		||||
  DisplayApp/DisplayApp.h
 | 
			
		||||
  DisplayApp/lcdfont.h
 | 
			
		||||
  drivers/st7789.h
 | 
			
		||||
  drivers/spi_master_fast.h
 | 
			
		||||
  drivers/St7789.h
 | 
			
		||||
  drivers/SpiMaster.h
 | 
			
		||||
  Components/Gfx/Gfx.h
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
nRF5x_addExecutable(pinetime-app "${SOURCE_FILES}")
 | 
			
		||||
							
								
								
									
										76
									
								
								src/Components/Gfx/Gfx.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								src/Components/Gfx/Gfx.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,76 @@
 | 
			
		||||
#include <libraries/svc/nrf_svci.h>
 | 
			
		||||
#include "Gfx.h"
 | 
			
		||||
#include "../../drivers/St7789.h"
 | 
			
		||||
using namespace Pinetime::Components;
 | 
			
		||||
 | 
			
		||||
Gfx::Gfx(Pinetime::Drivers::St7789 &lcd) : lcd{lcd} {
 | 
			
		||||
  lcd.Init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Gfx::ClearScreen() {
 | 
			
		||||
  lcd.FillRectangle(0, 0, width, height, 0xffff);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Gfx::DrawString(uint8_t x, uint8_t y, uint16_t color, const char *text, const FONT_INFO *p_font, bool wrap) {
 | 
			
		||||
  if (y > (height - p_font->height)) {
 | 
			
		||||
    // Not enough space to write even single char.
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  uint8_t current_x = x;
 | 
			
		||||
  uint8_t current_y = y;
 | 
			
		||||
 | 
			
		||||
  for (size_t i = 0; text[i] != '\0'; i++) {
 | 
			
		||||
    if (text[i] == '\n') {
 | 
			
		||||
      current_x = x;
 | 
			
		||||
      current_y += p_font->height + p_font->height / 10;
 | 
			
		||||
    } else {
 | 
			
		||||
      DrawChar(p_font, (uint8_t) text[i], ¤t_x, current_y, color);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint8_t char_idx = text[i] - p_font->startChar;
 | 
			
		||||
    uint16_t char_width = text[i] == ' ' ? (p_font->height / 2) : p_font->charInfo[char_idx].widthBits;
 | 
			
		||||
 | 
			
		||||
    if (current_x > (width - char_width)) {
 | 
			
		||||
      if (wrap) {
 | 
			
		||||
        current_x = x;
 | 
			
		||||
        current_y += p_font->height + p_font->height / 10;
 | 
			
		||||
      } else {
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (y > (height - p_font->height)) {
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Gfx::DrawChar(const FONT_INFO *font, uint8_t c, uint8_t *x, uint8_t y, uint16_t color) {
 | 
			
		||||
  uint8_t char_idx = c - font->startChar;
 | 
			
		||||
  uint16_t bytes_in_line = CEIL_DIV(font->charInfo[char_idx].widthBits, 8);
 | 
			
		||||
 | 
			
		||||
  if (c == ' ') {
 | 
			
		||||
    *x += font->height / 2;
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for (uint16_t i = 0; i < font->height; i++) {
 | 
			
		||||
    for (uint16_t j = 0; j < bytes_in_line; j++) {
 | 
			
		||||
      for (uint8_t k = 0; k < 8; k++) {
 | 
			
		||||
        if ((1 << (7 - k)) &
 | 
			
		||||
            font->data[font->charInfo[char_idx].offset + i * bytes_in_line + j]) {
 | 
			
		||||
          pixel_draw(*x + j * 8 + k, y + i, color);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  *x += font->charInfo[char_idx].widthBits + font->spacePixels;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Gfx::pixel_draw(uint8_t x, uint8_t y, uint16_t color) {
 | 
			
		||||
  lcd.DrawPixel(x, y, color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										26
									
								
								src/Components/Gfx/Gfx.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/Components/Gfx/Gfx.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,26 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
#include <cstdint>
 | 
			
		||||
#include <nrf_font.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace Pinetime {
 | 
			
		||||
  namespace Drivers {
 | 
			
		||||
    class St7789;
 | 
			
		||||
  }
 | 
			
		||||
  namespace Components {
 | 
			
		||||
    class Gfx {
 | 
			
		||||
      public:
 | 
			
		||||
        explicit Gfx(Drivers::St7789& lcd);
 | 
			
		||||
        void ClearScreen();
 | 
			
		||||
        void DrawString(uint8_t x, uint8_t y, uint16_t color, const char* text, const FONT_INFO *p_font, bool wrap);
 | 
			
		||||
        void DrawChar(const FONT_INFO *font, uint8_t c, uint8_t *x, uint8_t y, uint16_t color);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
      private:
 | 
			
		||||
        Drivers::St7789& lcd;
 | 
			
		||||
        const uint8_t width = 240;
 | 
			
		||||
        const uint8_t height = 240;
 | 
			
		||||
        void pixel_draw(uint8_t x, uint8_t y, uint16_t color);
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -3,57 +3,11 @@
 | 
			
		||||
#include <task.h>
 | 
			
		||||
#include <libraries/log/nrf_log.h>
 | 
			
		||||
#include <boards.h>
 | 
			
		||||
#include <libraries/gfx/nrf_gfx.h>
 | 
			
		||||
#include <nrf_font.h>
 | 
			
		||||
#include "Components/Gfx/Gfx.h"
 | 
			
		||||
 | 
			
		||||
using namespace Pinetime::Applications;
 | 
			
		||||
 | 
			
		||||
Pinetime::Drivers::st7789 lcd;
 | 
			
		||||
ret_code_t lcd_init() {
 | 
			
		||||
  return lcd.Init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void lcd_dummy() {
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void lcd_pixel_draw(uint16_t x, uint16_t y, uint32_t color) {
 | 
			
		||||
  lcd.DrawPixel(x, y, color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void lcd_rectangle_draw(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint32_t color) {
 | 
			
		||||
  lcd.FillRectangle(x, y, width, height, color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void lcd_rotation_set(nrf_lcd_rotation_t rotation) {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void lcd_display_invert(bool invert) {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static lcd_cb_t st7789_cb = {
 | 
			
		||||
        .height = 240,
 | 
			
		||||
        .width = 240
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const nrf_lcd_t nrf_lcd_st7789 = {
 | 
			
		||||
        .lcd_init = lcd_init,
 | 
			
		||||
        .lcd_uninit = lcd_dummy,
 | 
			
		||||
        .lcd_pixel_draw = lcd_pixel_draw,
 | 
			
		||||
        .lcd_rect_draw = lcd_rectangle_draw,
 | 
			
		||||
        .lcd_display = lcd_dummy,
 | 
			
		||||
        .lcd_rotation_set = lcd_rotation_set,
 | 
			
		||||
        .lcd_display_invert = lcd_display_invert,
 | 
			
		||||
        .p_lcd_cb = &st7789_cb
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//extern const FONT_INFO orkney_24ptFontInfo;
 | 
			
		||||
//extern const uint_8 lCD_30ptBitmaps[];
 | 
			
		||||
extern const FONT_INFO lCD_70ptFontInfo;
 | 
			
		||||
//extern const FONT_CHAR_INFO lCD_30ptDescriptors[];
 | 
			
		||||
 | 
			
		||||
void DisplayApp::Start() {
 | 
			
		||||
  if (pdPASS != xTaskCreate(DisplayApp::Process, "DisplayApp", 256, this, 0, &taskHandle))
 | 
			
		||||
    APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
 | 
			
		||||
@ -62,123 +16,49 @@ void DisplayApp::Start() {
 | 
			
		||||
 | 
			
		||||
void DisplayApp::Process(void *instance) {
 | 
			
		||||
  auto* app = static_cast<DisplayApp*>(instance);
 | 
			
		||||
 | 
			
		||||
  NRF_LOG_INFO("DisplayApp task started!");
 | 
			
		||||
  app->gfx_initialization();
 | 
			
		||||
  uint8_t hour = 0;
 | 
			
		||||
  uint8_t minute = 1;
 | 
			
		||||
  app->InitHw();
 | 
			
		||||
 | 
			
		||||
  while (1) {
 | 
			
		||||
    NRF_LOG_INFO("BlinkApp task running!");
 | 
			
		||||
 | 
			
		||||
    nrf_gfx_rect_t rect;
 | 
			
		||||
    rect.height = 74;
 | 
			
		||||
    rect.width = 52;
 | 
			
		||||
    rect.x = 7;
 | 
			
		||||
    rect.y = 78;
 | 
			
		||||
    nrf_gfx_rect_draw(&nrf_lcd_st7789, &rect, 2, 0x00000000, true);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    nrf_gfx_font_desc_t font;
 | 
			
		||||
    font.charInfo = lCD_70ptFontInfo.charInfo;
 | 
			
		||||
    font.data = lCD_70ptFontInfo.data;
 | 
			
		||||
    font.endChar = lCD_70ptFontInfo.endChar;
 | 
			
		||||
    font.height = lCD_70ptFontInfo.height;
 | 
			
		||||
    font.spacePixels = lCD_70ptFontInfo.spacePixels;
 | 
			
		||||
    font.startChar = lCD_70ptFontInfo.startChar;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    char t[2];
 | 
			
		||||
    sprintf(t, "%1d", hour);
 | 
			
		||||
 | 
			
		||||
    nrf_gfx_point_t point;
 | 
			
		||||
    point.x = 7;
 | 
			
		||||
    point.y = 78;
 | 
			
		||||
    nrf_gfx_print(&nrf_lcd_st7789,
 | 
			
		||||
                  &point,
 | 
			
		||||
                  0xffff,
 | 
			
		||||
                  t,
 | 
			
		||||
                  &font,
 | 
			
		||||
                  true);
 | 
			
		||||
 | 
			
		||||
//    point.x = 61;
 | 
			
		||||
//    point.y = 78;
 | 
			
		||||
//    nrf_gfx_print(&nrf_lcd_st7789,
 | 
			
		||||
//                  &point,
 | 
			
		||||
//                  0xffff,
 | 
			
		||||
//                  "2",
 | 
			
		||||
//                  &font,
 | 
			
		||||
//                  true);
 | 
			
		||||
//
 | 
			
		||||
//    point.x = 115;
 | 
			
		||||
//    point.y = 78;
 | 
			
		||||
//    nrf_gfx_print(&nrf_lcd_st7789,
 | 
			
		||||
//                  &point,
 | 
			
		||||
//                  0xffff,
 | 
			
		||||
//                  ":",
 | 
			
		||||
//                  &font,
 | 
			
		||||
//                  true);
 | 
			
		||||
//
 | 
			
		||||
//    point.x = 127;
 | 
			
		||||
//    point.y = 78;
 | 
			
		||||
//    nrf_gfx_print(&nrf_lcd_st7789,
 | 
			
		||||
//                  &point,
 | 
			
		||||
//                  0xffff,
 | 
			
		||||
//                  "3",
 | 
			
		||||
//                  &font,
 | 
			
		||||
//                  true);
 | 
			
		||||
//
 | 
			
		||||
//    point.x = 181;
 | 
			
		||||
//    point.y = 78;
 | 
			
		||||
//    nrf_gfx_print(&nrf_lcd_st7789,
 | 
			
		||||
//                  &point,
 | 
			
		||||
//                  0xffff,
 | 
			
		||||
//                  "4",
 | 
			
		||||
//                  &font,
 | 
			
		||||
//                  true);
 | 
			
		||||
 | 
			
		||||
    if(hour < 9)
 | 
			
		||||
      hour++;
 | 
			
		||||
    else hour = 0;
 | 
			
		||||
    vTaskDelay(1000);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DisplayApp::gfx_initialization(void)
 | 
			
		||||
{
 | 
			
		||||
void DisplayApp::InitHw() {
 | 
			
		||||
  nrf_gpio_cfg_output(14);
 | 
			
		||||
  nrf_gpio_cfg_output(22);
 | 
			
		||||
  nrf_gpio_cfg_output(23);
 | 
			
		||||
  nrf_gpio_pin_clear(14);
 | 
			
		||||
  nrf_gpio_pin_set(22);
 | 
			
		||||
  nrf_gpio_pin_set(23);
 | 
			
		||||
  nrf_gpio_pin_clear(22);
 | 
			
		||||
  nrf_gpio_pin_clear(23);
 | 
			
		||||
 | 
			
		||||
  APP_ERROR_CHECK(nrf_gfx_init(&nrf_lcd_st7789));
 | 
			
		||||
  nrf_gfx_rect_t rect;
 | 
			
		||||
  rect.height = 240;
 | 
			
		||||
  rect.width = 240;
 | 
			
		||||
  rect.x = 0;
 | 
			
		||||
  rect.y = 0;
 | 
			
		||||
  nrf_gfx_rect_draw(&nrf_lcd_st7789, &rect, 2, 0x00000000, true);
 | 
			
		||||
  Drivers::SpiMaster::Parameters params;
 | 
			
		||||
  params.bitOrder = Drivers::SpiMaster::BitOrder::Msb_Lsb;
 | 
			
		||||
  params.mode = Drivers::SpiMaster::Modes::Mode3;
 | 
			
		||||
  params.Frequency = Drivers::SpiMaster::Frequencies::Freq8Mhz;
 | 
			
		||||
  params.pinCSN = 25;
 | 
			
		||||
  params.pinMISO = 4;
 | 
			
		||||
  params.pinMOSI = 3;
 | 
			
		||||
  params.pinSCK = 2;
 | 
			
		||||
  spi.Init(Drivers::SpiMaster::SpiModule::SPI0, params);
 | 
			
		||||
 | 
			
		||||
  nrf_gfx_point_t point;
 | 
			
		||||
  point.x = 7;
 | 
			
		||||
  point.y = 78;
 | 
			
		||||
  lcd.reset(new Drivers::St7789(spi, 18));
 | 
			
		||||
  gfx.reset(new Components::Gfx(*lcd.get()));
 | 
			
		||||
  gfx->ClearScreen();
 | 
			
		||||
 | 
			
		||||
  nrf_gfx_font_desc_t font;
 | 
			
		||||
  font.charInfo = lCD_70ptFontInfo.charInfo;
 | 
			
		||||
  font.data = lCD_70ptFontInfo.data;
 | 
			
		||||
  font.endChar = lCD_70ptFontInfo.endChar;
 | 
			
		||||
  font.height = lCD_70ptFontInfo.height;
 | 
			
		||||
  font.spacePixels = lCD_70ptFontInfo.spacePixels;
 | 
			
		||||
  font.startChar = lCD_70ptFontInfo.startChar;
 | 
			
		||||
  uint8_t x = 7;
 | 
			
		||||
  gfx->DrawChar(&largeFont , '0', &x, 78, 0x0);
 | 
			
		||||
 | 
			
		||||
  x = 61;
 | 
			
		||||
  gfx->DrawChar(&largeFont, '1', &x, 78, 0x0);
 | 
			
		||||
 | 
			
		||||
  nrf_gfx_print(&nrf_lcd_st7789,
 | 
			
		||||
                &point,
 | 
			
		||||
                0xffff,
 | 
			
		||||
                "20:45",
 | 
			
		||||
                &font,
 | 
			
		||||
                true);
 | 
			
		||||
  x = 115;
 | 
			
		||||
  gfx->DrawChar(&largeFont, ':', &x, 78, 0x0);
 | 
			
		||||
 | 
			
		||||
  x = 127;
 | 
			
		||||
  gfx->DrawChar(&largeFont, '2', &x, 78, 0x0);
 | 
			
		||||
 | 
			
		||||
  x = 181;
 | 
			
		||||
  gfx->DrawChar(&largeFont, '3', &x, 78, 0x0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,18 +1,27 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
#include <FreeRTOS.h>
 | 
			
		||||
#include <task.h>
 | 
			
		||||
#include <drivers/st7789.h>
 | 
			
		||||
#include <drivers/St7789.h>
 | 
			
		||||
#include <drivers/SpiMaster.h>
 | 
			
		||||
#include <Components/Gfx/Gfx.h>
 | 
			
		||||
#include <bits/unique_ptr.h>
 | 
			
		||||
 | 
			
		||||
extern const FONT_INFO lCD_70ptFontInfo;
 | 
			
		||||
 | 
			
		||||
namespace Pinetime {
 | 
			
		||||
  namespace Applications {
 | 
			
		||||
    class DisplayApp {
 | 
			
		||||
      public:
 | 
			
		||||
        void Start();
 | 
			
		||||
 | 
			
		||||
      private:
 | 
			
		||||
        TaskHandle_t taskHandle;
 | 
			
		||||
        static void Process(void* instance);
 | 
			
		||||
        void gfx_initialization();
 | 
			
		||||
 | 
			
		||||
        void InitHw();
 | 
			
		||||
        Pinetime::Drivers::SpiMaster spi;
 | 
			
		||||
        std::unique_ptr<Drivers::St7789> lcd;
 | 
			
		||||
        std::unique_ptr<Components::Gfx> gfx;
 | 
			
		||||
        const FONT_INFO largeFont {lCD_70ptFontInfo.height, lCD_70ptFontInfo.startChar, lCD_70ptFontInfo.endChar, lCD_70ptFontInfo.spacePixels, lCD_70ptFontInfo.charInfo, lCD_70ptFontInfo.data};
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										88
									
								
								src/drivers/SpiMaster.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								src/drivers/SpiMaster.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,88 @@
 | 
			
		||||
#include <hal/nrf_gpio.h>
 | 
			
		||||
#include "SpiMaster.h"
 | 
			
		||||
 | 
			
		||||
using namespace Pinetime::Drivers;
 | 
			
		||||
 | 
			
		||||
bool SpiMaster::Init(const SpiMaster::SpiModule spi, const SpiMaster::Parameters ¶ms) {
 | 
			
		||||
  /* Configure GPIO pins used for pselsck, pselmosi, pselmiso and pselss for SPI0 */
 | 
			
		||||
  nrf_gpio_cfg_output(params.pinSCK);
 | 
			
		||||
  nrf_gpio_cfg_output(params.pinMOSI);
 | 
			
		||||
  nrf_gpio_cfg_input(params.pinMISO, NRF_GPIO_PIN_NOPULL);
 | 
			
		||||
  nrf_gpio_cfg_output(params.pinCSN);
 | 
			
		||||
  pinCsn = params.pinCSN;
 | 
			
		||||
 | 
			
		||||
  switch(spi) {
 | 
			
		||||
    case SpiModule::SPI0: spiBaseAddress = NRF_SPI0; break;
 | 
			
		||||
    case SpiModule::SPI1: spiBaseAddress = NRF_SPI1; break;
 | 
			
		||||
    default: return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* Configure pins, frequency and mode */
 | 
			
		||||
  spiBaseAddress->PSELSCK  = params.pinSCK;
 | 
			
		||||
  spiBaseAddress->PSELMOSI = params.pinMOSI;
 | 
			
		||||
  spiBaseAddress->PSELMISO = params.pinMISO;
 | 
			
		||||
  nrf_gpio_pin_set(pinCsn); /* disable Set slave select (inactive high) */
 | 
			
		||||
 | 
			
		||||
  uint32_t frequency;
 | 
			
		||||
  switch(params.Frequency) {
 | 
			
		||||
    case Frequencies::Freq8Mhz: frequency = 0x80000000; break;
 | 
			
		||||
    default: return false;
 | 
			
		||||
  }
 | 
			
		||||
  spiBaseAddress->FREQUENCY = frequency;
 | 
			
		||||
 | 
			
		||||
  uint32_t regConfig = 0;
 | 
			
		||||
  switch(params.bitOrder) {
 | 
			
		||||
    case BitOrder::Msb_Lsb: break;
 | 
			
		||||
    case BitOrder::Lsb_Msb: regConfig = 1;
 | 
			
		||||
    default: return false;
 | 
			
		||||
  }
 | 
			
		||||
  switch(params.mode) {
 | 
			
		||||
    case Modes::Mode0: break;
 | 
			
		||||
    case Modes::Mode1: regConfig |= (0x01 << 1); break;
 | 
			
		||||
    case Modes::Mode2: regConfig |= (0x02 << 1); break;
 | 
			
		||||
    case Modes::Mode3: regConfig |= (0x03 << 1); break;
 | 
			
		||||
    default: return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  spiBaseAddress->CONFIG = regConfig;
 | 
			
		||||
  spiBaseAddress->EVENTS_READY = 0;
 | 
			
		||||
  spiBaseAddress->ENABLE = (SPI_ENABLE_ENABLE_Enabled << SPI_ENABLE_ENABLE_Pos);
 | 
			
		||||
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool SpiMaster::Write(const uint8_t *data, size_t size) {
 | 
			
		||||
  volatile uint32_t dummyread;
 | 
			
		||||
 | 
			
		||||
  if(data == nullptr) return false;
 | 
			
		||||
 | 
			
		||||
  /* enable slave (slave select active low) */
 | 
			
		||||
  nrf_gpio_pin_clear(pinCsn);
 | 
			
		||||
 | 
			
		||||
  spiBaseAddress->EVENTS_READY = 0;
 | 
			
		||||
 | 
			
		||||
  spiBaseAddress->TXD = (uint32_t)*data++;
 | 
			
		||||
 | 
			
		||||
  while(--size)
 | 
			
		||||
  {
 | 
			
		||||
    spiBaseAddress->TXD =  (uint32_t)*data++;
 | 
			
		||||
 | 
			
		||||
    /* Wait for the transaction complete or timeout (about 10ms - 20 ms) */
 | 
			
		||||
    while (spiBaseAddress->EVENTS_READY == 0);
 | 
			
		||||
 | 
			
		||||
    /* clear the event to be ready to receive next messages */
 | 
			
		||||
    spiBaseAddress->EVENTS_READY = 0;
 | 
			
		||||
 | 
			
		||||
    dummyread = spiBaseAddress->RXD;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* Wait for the transaction complete or timeout (about 10ms - 20 ms) */
 | 
			
		||||
  while (spiBaseAddress->EVENTS_READY == 0);
 | 
			
		||||
 | 
			
		||||
  dummyread = spiBaseAddress->RXD;
 | 
			
		||||
 | 
			
		||||
  /* disable slave (slave select active low) */
 | 
			
		||||
  nrf_gpio_pin_set(pinCsn);
 | 
			
		||||
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										32
									
								
								src/drivers/SpiMaster.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/drivers/SpiMaster.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,32 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
#include <cstdint>
 | 
			
		||||
#include <cstddef>
 | 
			
		||||
#include <array>
 | 
			
		||||
 | 
			
		||||
namespace Pinetime {
 | 
			
		||||
  namespace Drivers {
 | 
			
		||||
    class SpiMaster {
 | 
			
		||||
      public:;
 | 
			
		||||
        enum class SpiModule : uint8_t {SPI0, SPI1};
 | 
			
		||||
        enum class BitOrder : uint8_t {Msb_Lsb, Lsb_Msb};
 | 
			
		||||
        enum class Modes : uint8_t {Mode0, Mode1, Mode2, Mode3};
 | 
			
		||||
        enum class Frequencies : uint8_t {Freq8Mhz};
 | 
			
		||||
        struct Parameters {
 | 
			
		||||
          BitOrder bitOrder;
 | 
			
		||||
          Modes mode;
 | 
			
		||||
          Frequencies Frequency;
 | 
			
		||||
          uint8_t pinSCK;
 | 
			
		||||
          uint8_t pinMOSI;
 | 
			
		||||
          uint8_t pinMISO;
 | 
			
		||||
          uint8_t pinCSN;
 | 
			
		||||
        };
 | 
			
		||||
        bool Init(const SpiModule spi, const Parameters& params);
 | 
			
		||||
 | 
			
		||||
        bool Write(const uint8_t* data, size_t size);
 | 
			
		||||
 | 
			
		||||
      private:
 | 
			
		||||
        NRF_SPI_Type *  spiBaseAddress;
 | 
			
		||||
        uint8_t pinCsn;
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -1,35 +1,17 @@
 | 
			
		||||
#include <hal/nrf_gpio.h>
 | 
			
		||||
#include <libraries/delay/nrf_delay.h>
 | 
			
		||||
#include "st7789.h"
 | 
			
		||||
#include "spi_master_fast.h"
 | 
			
		||||
#include "St7789.h"
 | 
			
		||||
#include "SpiMaster.h"
 | 
			
		||||
 | 
			
		||||
using namespace Pinetime::Drivers;
 | 
			
		||||
 | 
			
		||||
ret_code_t st7789::Init() {
 | 
			
		||||
  InitHw();
 | 
			
		||||
  InitCommands();
 | 
			
		||||
  return 0;
 | 
			
		||||
St7789::St7789(SpiMaster &spiMaster, uint8_t pinDataCommand) : spi{spiMaster}, pinDataCommand{pinDataCommand} {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ret_code_t st7789::InitHw() const {
 | 
			
		||||
  nrf_gpio_cfg_output(ST7735_DC_PIN);
 | 
			
		||||
  SPI_config_t spi_config;
 | 
			
		||||
 | 
			
		||||
  spi_config.pin_SCK                 = ST7735_SCK_PIN;
 | 
			
		||||
  spi_config.pin_MOSI                 = ST7735_MOSI_PIN;
 | 
			
		||||
  spi_config.pin_MISO                 = ST7735_MISO_PIN;
 | 
			
		||||
  spi_config.pin_CSN                 = ST7735_SS_PIN;
 | 
			
		||||
  spi_config.frequency                 = SPI_FREQ_8MBPS;
 | 
			
		||||
  spi_config.config.fields.mode                 = SPI_MODE3;
 | 
			
		||||
  spi_config.config.fields.bit_order                 = SPI_BITORDER_MSB_LSB;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  spi_master_init(SPI0, &spi_config);
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void st7789::InitCommands() {
 | 
			
		||||
void St7789::Init() {
 | 
			
		||||
  nrf_gpio_cfg_output(pinDataCommand);
 | 
			
		||||
  SoftwareReset();
 | 
			
		||||
  SleepOut();
 | 
			
		||||
  ColMod();
 | 
			
		||||
@ -39,47 +21,45 @@ void st7789::InitCommands() {
 | 
			
		||||
  DisplayInversionOn();
 | 
			
		||||
  NormalModeOn();
 | 
			
		||||
  DisplayOn();
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void st7789::WriteCommand(uint8_t cmd) {
 | 
			
		||||
  nrf_gpio_pin_clear(ST7735_DC_PIN);
 | 
			
		||||
void St7789::WriteCommand(uint8_t cmd) {
 | 
			
		||||
  nrf_gpio_pin_clear(pinDataCommand);
 | 
			
		||||
  WriteSpi(&cmd, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void st7789::WriteData(uint8_t data) {
 | 
			
		||||
  nrf_gpio_pin_set(ST7735_DC_PIN);
 | 
			
		||||
void St7789::WriteData(uint8_t data) {
 | 
			
		||||
  nrf_gpio_pin_set(pinDataCommand);
 | 
			
		||||
  WriteSpi(&data, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void st7789::WriteSpi(const uint8_t* data, size_t size) {
 | 
			
		||||
//  APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, data, size, nullptr, 0));
 | 
			
		||||
  spi_master_tx(SPI0, size, data);
 | 
			
		||||
void St7789::WriteSpi(const uint8_t* data, size_t size) {
 | 
			
		||||
  spi.Write(data, size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void st7789::SoftwareReset() {
 | 
			
		||||
void St7789::SoftwareReset() {
 | 
			
		||||
  WriteCommand(static_cast<uint8_t>(Commands::SoftwareReset));
 | 
			
		||||
  nrf_delay_ms(150);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void st7789::SleepOut() {
 | 
			
		||||
void St7789::SleepOut() {
 | 
			
		||||
  WriteCommand(static_cast<uint8_t>(Commands::SleepOut));
 | 
			
		||||
  nrf_delay_ms(500);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void st7789::ColMod() {
 | 
			
		||||
void St7789::ColMod() {
 | 
			
		||||
  WriteCommand(static_cast<uint8_t>(Commands::ColMod));
 | 
			
		||||
  WriteData(0x55);
 | 
			
		||||
  nrf_delay_ms(10);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void st7789::MemoryDataAccessControl() {
 | 
			
		||||
void St7789::MemoryDataAccessControl() {
 | 
			
		||||
  WriteCommand(static_cast<uint8_t>(Commands::MemoryDataAccessControl));
 | 
			
		||||
  WriteData(0x00);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void st7789::ColumnAddressSet() {
 | 
			
		||||
void St7789::ColumnAddressSet() {
 | 
			
		||||
  WriteCommand(static_cast<uint8_t>(Commands::ColumnAddressSet));
 | 
			
		||||
  WriteData(0x00);
 | 
			
		||||
  WriteData(0x00);
 | 
			
		||||
@ -87,7 +67,7 @@ void st7789::ColumnAddressSet() {
 | 
			
		||||
  WriteData(Height & 0xff);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void st7789::RowAddressSet() {
 | 
			
		||||
void St7789::RowAddressSet() {
 | 
			
		||||
  WriteCommand(static_cast<uint8_t>(Commands::RowAddressSet));
 | 
			
		||||
  WriteData(0x00);
 | 
			
		||||
  WriteData(0x00);
 | 
			
		||||
@ -95,22 +75,22 @@ void st7789::RowAddressSet() {
 | 
			
		||||
  WriteData(Width & 0xff);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void st7789::DisplayInversionOn() {
 | 
			
		||||
void St7789::DisplayInversionOn() {
 | 
			
		||||
  WriteCommand(static_cast<uint8_t>(Commands::DisplayInversionOn));
 | 
			
		||||
  nrf_delay_ms(10);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void st7789::NormalModeOn() {
 | 
			
		||||
void St7789::NormalModeOn() {
 | 
			
		||||
  WriteCommand(static_cast<uint8_t>(Commands::NormalModeOn));
 | 
			
		||||
  nrf_delay_ms(10);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void st7789::DisplayOn() {
 | 
			
		||||
void St7789::DisplayOn() {
 | 
			
		||||
  WriteCommand(static_cast<uint8_t>(Commands::DisplayOn));
 | 
			
		||||
  nrf_delay_ms(500);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void st7789::FillRectangle(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color) {
 | 
			
		||||
void St7789::FillRectangle(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color) {
 | 
			
		||||
  // rudimentary clipping (drawChar w/big text requires this)
 | 
			
		||||
  if((x >= Width) || (y >= Height)) return;
 | 
			
		||||
  if((x + width - 1) >= Width)  width = Width  - x;
 | 
			
		||||
@ -121,7 +101,7 @@ void st7789::FillRectangle(uint16_t x, uint16_t y, uint16_t width, uint16_t heig
 | 
			
		||||
  uint8_t hi = color >> 8, lo = color;
 | 
			
		||||
  uint32_t c = color + (color << 16);
 | 
			
		||||
 | 
			
		||||
  nrf_gpio_pin_set(ST7735_DC_PIN);
 | 
			
		||||
  nrf_gpio_pin_set(pinDataCommand);
 | 
			
		||||
  for(y=height+ST7789_ROW_OFFSET; y>ST7789_ROW_OFFSET; y--) {
 | 
			
		||||
    for(x=width; x>0; x--) {
 | 
			
		||||
      WriteSpi(reinterpret_cast<const uint8_t *>(&c), 4);
 | 
			
		||||
@ -129,7 +109,7 @@ void st7789::FillRectangle(uint16_t x, uint16_t y, uint16_t width, uint16_t heig
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void st7789::SetAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
 | 
			
		||||
void St7789::SetAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
 | 
			
		||||
  WriteCommand(static_cast<uint8_t>(Commands::ColumnAddressSet));
 | 
			
		||||
  WriteData(x0 >> 8);
 | 
			
		||||
  WriteData(x0 & 0xff);
 | 
			
		||||
@ -145,24 +125,25 @@ void st7789::SetAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
 | 
			
		||||
  WriteToRam();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void st7789::WriteToRam() {
 | 
			
		||||
void St7789::WriteToRam() {
 | 
			
		||||
  WriteCommand(static_cast<uint8_t>(Commands::WriteToRam));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void st7789::DisplayOff() {
 | 
			
		||||
void St7789::DisplayOff() {
 | 
			
		||||
  WriteCommand(static_cast<uint8_t>(Commands::DisplayOff));
 | 
			
		||||
  nrf_delay_ms(500);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void st7789::Uninit() {
 | 
			
		||||
void St7789::Uninit() {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void st7789::DrawPixel(uint16_t x, uint16_t y, uint32_t color) {
 | 
			
		||||
void St7789::DrawPixel(uint16_t x, uint16_t y, uint32_t color) {
 | 
			
		||||
  if((x < 0) ||(x >= Width) || (y < 0) || (y >= Height)) return;
 | 
			
		||||
 | 
			
		||||
  SetAddrWindow(x, y, x+1, y+1);
 | 
			
		||||
 | 
			
		||||
  nrf_gpio_pin_set(ST7735_DC_PIN);
 | 
			
		||||
  nrf_gpio_pin_set(pinDataCommand);
 | 
			
		||||
  WriteSpi(reinterpret_cast<const uint8_t *>(&color), 2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,18 +1,21 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
#include <cstddef>
 | 
			
		||||
 | 
			
		||||
namespace Pinetime {
 | 
			
		||||
  namespace Drivers {
 | 
			
		||||
    class st7789 {
 | 
			
		||||
    class SpiMaster;
 | 
			
		||||
    class St7789 {
 | 
			
		||||
      public:
 | 
			
		||||
        ret_code_t Init();
 | 
			
		||||
        explicit St7789(SpiMaster& spiMaster, uint8_t pinDataCommand);
 | 
			
		||||
        void Init();
 | 
			
		||||
        void Uninit();
 | 
			
		||||
        void DrawPixel(uint16_t x, uint16_t y, uint32_t color);
 | 
			
		||||
        void DrawRectangle(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint32_t color);
 | 
			
		||||
        void FillRectangle(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
      private:
 | 
			
		||||
        ret_code_t InitHw() const;
 | 
			
		||||
        void InitCommands();
 | 
			
		||||
        SpiMaster& spi;
 | 
			
		||||
        uint8_t pinDataCommand;
 | 
			
		||||
 | 
			
		||||
        void SoftwareReset();
 | 
			
		||||
        void SleepOut();
 | 
			
		||||
@ -1,176 +0,0 @@
 | 
			
		||||
 /* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * The information contained herein is confidential property of Nordic
 | 
			
		||||
 * Semiconductor ASA.Terms and conditions of usage are described in detail
 | 
			
		||||
 * in NORDIC SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensees are granted free, non-transferable use of the information. NO
 | 
			
		||||
 * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
 | 
			
		||||
 * the file.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "spi_master_fast.h"
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "nrf_gpio.h"
 | 
			
		||||
#include "nrf_delay.h"
 | 
			
		||||
 | 
			
		||||
static SPI_config_t spi_config_table[2];
 | 
			
		||||
static NRF_SPI_Type *spi_base[2] = {NRF_SPI0, NRF_SPI1};
 | 
			
		||||
static NRF_SPI_Type *SPI;
 | 
			
		||||
 | 
			
		||||
uint32_t* spi_master_init(SPI_module_number_t spi_num, SPI_config_t *spi_config)
 | 
			
		||||
{
 | 
			
		||||
    if(spi_num > 1)
 | 
			
		||||
    {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    memcpy(&spi_config_table[spi_num], spi_config, sizeof(SPI_config_t));
 | 
			
		||||
 | 
			
		||||
    /* Configure GPIO pins used for pselsck, pselmosi, pselmiso and pselss for SPI0 */
 | 
			
		||||
    nrf_gpio_cfg_output(spi_config->pin_SCK);
 | 
			
		||||
    nrf_gpio_cfg_output(spi_config->pin_MOSI);
 | 
			
		||||
    nrf_gpio_cfg_input(spi_config->pin_MISO, NRF_GPIO_PIN_NOPULL);
 | 
			
		||||
    nrf_gpio_cfg_output(spi_config->pin_CSN);
 | 
			
		||||
 | 
			
		||||
    /* Configure pins, frequency and mode */
 | 
			
		||||
    spi_base[spi_num]->PSELSCK  = spi_config->pin_SCK;
 | 
			
		||||
    spi_base[spi_num]->PSELMOSI = spi_config->pin_MOSI;
 | 
			
		||||
    spi_base[spi_num]->PSELMISO = spi_config->pin_MISO;
 | 
			
		||||
    nrf_gpio_pin_set(spi_config->pin_CSN); /* disable Set slave select (inactive high) */
 | 
			
		||||
 | 
			
		||||
    spi_base[spi_num]->FREQUENCY = (uint32_t)spi_config->frequency << 24;
 | 
			
		||||
 | 
			
		||||
    spi_base[spi_num]->CONFIG = spi_config->config.SPI_cfg;
 | 
			
		||||
 | 
			
		||||
    spi_base[spi_num]->EVENTS_READY = 0;
 | 
			
		||||
    /* Enable */
 | 
			
		||||
    spi_base[spi_num]->ENABLE = (SPI_ENABLE_ENABLE_Enabled << SPI_ENABLE_ENABLE_Pos);
 | 
			
		||||
 | 
			
		||||
    return (uint32_t *)spi_base[spi_num];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool spi_master_tx_rx(SPI_module_number_t spi_num, uint16_t transfer_size, const uint8_t *tx_data, uint8_t *rx_data)
 | 
			
		||||
{
 | 
			
		||||
    volatile uint32_t *SPI_DATA_READY;
 | 
			
		||||
    uint32_t tmp; 
 | 
			
		||||
    if(tx_data == 0 || rx_data == 0)
 | 
			
		||||
    {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    SPI = spi_base[spi_num];
 | 
			
		||||
    SPI_DATA_READY = &SPI->EVENTS_READY;
 | 
			
		||||
    /* enable slave (slave select active low) */
 | 
			
		||||
    nrf_gpio_pin_clear(spi_config_table[spi_num].pin_CSN);
 | 
			
		||||
    
 | 
			
		||||
    *SPI_DATA_READY = 0; 
 | 
			
		||||
    
 | 
			
		||||
    SPI->TXD = (uint32_t)*tx_data++;
 | 
			
		||||
    tmp = (uint32_t)*tx_data++;
 | 
			
		||||
    while(--transfer_size)
 | 
			
		||||
    {
 | 
			
		||||
        SPI->TXD =  tmp;
 | 
			
		||||
        tmp = (uint32_t)*tx_data++;
 | 
			
		||||
        
 | 
			
		||||
        /* Wait for the transaction complete or timeout (about 10ms - 20 ms) */
 | 
			
		||||
        while (*SPI_DATA_READY == 0);
 | 
			
		||||
 | 
			
		||||
        /* clear the event to be ready to receive next messages */
 | 
			
		||||
        *SPI_DATA_READY = 0;
 | 
			
		||||
        
 | 
			
		||||
        *rx_data++ = SPI->RXD; 
 | 
			
		||||
    }
 | 
			
		||||
      
 | 
			
		||||
    /* Wait for the transaction complete or timeout (about 10ms - 20 ms) */
 | 
			
		||||
    while (*SPI_DATA_READY == 0);
 | 
			
		||||
 | 
			
		||||
    *rx_data = SPI->RXD;
 | 
			
		||||
 | 
			
		||||
    /* disable slave (slave select active low) */
 | 
			
		||||
    nrf_gpio_pin_set(spi_config_table[spi_num].pin_CSN);
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool spi_master_tx(SPI_module_number_t spi_num, uint16_t transfer_size, const uint8_t *tx_data)
 | 
			
		||||
{
 | 
			
		||||
    volatile uint32_t dummyread;
 | 
			
		||||
    
 | 
			
		||||
    if(tx_data == 0)
 | 
			
		||||
    {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    SPI = spi_base[spi_num];
 | 
			
		||||
    
 | 
			
		||||
    /* enable slave (slave select active low) */
 | 
			
		||||
    nrf_gpio_pin_clear(spi_config_table[spi_num].pin_CSN);
 | 
			
		||||
    
 | 
			
		||||
    SPI->EVENTS_READY = 0; 
 | 
			
		||||
    
 | 
			
		||||
    SPI->TXD = (uint32_t)*tx_data++;
 | 
			
		||||
    
 | 
			
		||||
    while(--transfer_size)
 | 
			
		||||
    {
 | 
			
		||||
        SPI->TXD =  (uint32_t)*tx_data++;
 | 
			
		||||
 | 
			
		||||
        /* Wait for the transaction complete or timeout (about 10ms - 20 ms) */
 | 
			
		||||
        while (SPI->EVENTS_READY == 0);
 | 
			
		||||
        
 | 
			
		||||
        /* clear the event to be ready to receive next messages */
 | 
			
		||||
        SPI->EVENTS_READY = 0;
 | 
			
		||||
        
 | 
			
		||||
        dummyread = SPI->RXD;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /* Wait for the transaction complete or timeout (about 10ms - 20 ms) */
 | 
			
		||||
    while (SPI->EVENTS_READY == 0);
 | 
			
		||||
 | 
			
		||||
    dummyread = SPI->RXD;
 | 
			
		||||
 | 
			
		||||
    /* disable slave (slave select active low) */
 | 
			
		||||
    nrf_gpio_pin_set(spi_config_table[spi_num].pin_CSN);
 | 
			
		||||
    
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool spi_master_rx(SPI_module_number_t spi_num, uint16_t transfer_size, uint8_t *rx_data)
 | 
			
		||||
{
 | 
			
		||||
    if(rx_data == 0)
 | 
			
		||||
    {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    SPI = spi_base[spi_num];
 | 
			
		||||
    
 | 
			
		||||
    /* enable slave (slave select active low) */
 | 
			
		||||
    nrf_gpio_pin_clear(spi_config_table[spi_num].pin_CSN);
 | 
			
		||||
 | 
			
		||||
    SPI->EVENTS_READY = 0; 
 | 
			
		||||
    
 | 
			
		||||
    SPI->TXD = 0;
 | 
			
		||||
    
 | 
			
		||||
    while(--transfer_size)
 | 
			
		||||
    {
 | 
			
		||||
        SPI->TXD = 0;
 | 
			
		||||
 | 
			
		||||
        /* Wait for the transaction complete or timeout (about 10ms - 20 ms) */
 | 
			
		||||
        while (SPI->EVENTS_READY == 0);
 | 
			
		||||
        
 | 
			
		||||
        /* clear the event to be ready to receive next messages */
 | 
			
		||||
        SPI->EVENTS_READY = 0;
 | 
			
		||||
        
 | 
			
		||||
        *rx_data++ = SPI->RXD;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /* Wait for the transaction complete or timeout (about 10ms - 20 ms) */
 | 
			
		||||
    while (SPI->EVENTS_READY == 0);
 | 
			
		||||
 | 
			
		||||
    *rx_data = SPI->RXD;
 | 
			
		||||
 | 
			
		||||
    /* disable slave (slave select active low) */
 | 
			
		||||
    nrf_gpio_pin_set(spi_config_table[spi_num].pin_CSN);
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
@ -1,147 +0,0 @@
 | 
			
		||||
 /* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * The information contained herein is confidential property of Nordic
 | 
			
		||||
 * Semiconductor ASA.Terms and conditions of usage are described in detail
 | 
			
		||||
 * in NORDIC SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensees are granted free, non-transferable use of the information. NO
 | 
			
		||||
 * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
 | 
			
		||||
 * the file.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __SPI_MASTER_FAST_H
 | 
			
		||||
#define __SPI_MASTER_FAST_H
 | 
			
		||||
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#define SPI_FAST_DEFAULT_CONFIG {.pin_SCK = 1, .pin_MOSI = 2, .pin_MISO = 3, .pin_CSN = 4,  \
 | 
			
		||||
                                 .frequency = SPI_FREQ_1MBPS, .config.fields.mode = 0, .config.fields.bit_order = SPI_BITORDER_MSB_LSB}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  SPI master operating frequency
 | 
			
		||||
 */
 | 
			
		||||
typedef enum
 | 
			
		||||
{
 | 
			
		||||
    SPI_FREQ_125KBPS = 0x02,           /*!< drive SClk with frequency 125Kbps */
 | 
			
		||||
    SPI_FREQ_250KBPS = 0x04,           /*!< drive SClk with frequency 250Kbps */
 | 
			
		||||
    SPI_FREQ_500KBPS = 0x08,           /*!< drive SClk with frequency 500Kbps */
 | 
			
		||||
    SPI_FREQ_1MBPS = 0x10,             /*!< drive SClk with frequency 1Mbps */
 | 
			
		||||
    SPI_FREQ_2MBPS = 0x20,             /*!< drive SClk with frequency 2Mbps */
 | 
			
		||||
    SPI_FREQ_4MBPS = 0x40,             /*!< drive SClk with frequency 4Mbps */
 | 
			
		||||
    SPI_FREQ_8MBPS = 0x80              /*!< drive SClk with frequency 8Mbps */
 | 
			
		||||
} SPI_frequency_t;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  SPI master module number
 | 
			
		||||
 */
 | 
			
		||||
typedef enum
 | 
			
		||||
{
 | 
			
		||||
    SPI0 = 0,               /*!< SPI module 0 */
 | 
			
		||||
    SPI1                    /*!< SPI module 1 */
 | 
			
		||||
} SPI_module_number_t;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  SPI mode
 | 
			
		||||
 */
 | 
			
		||||
typedef enum
 | 
			
		||||
{
 | 
			
		||||
    //------------------------Clock polarity 0, Clock starts with level 0-------------------------------------------
 | 
			
		||||
    SPI_MODE0 = 0,          /*!< Sample data at rising edge of clock and shift serial data at falling edge */
 | 
			
		||||
    SPI_MODE1,              /*!< sample data at falling edge of clock and shift serial data at rising edge */
 | 
			
		||||
    //------------------------Clock polarity 1, Clock starts with level 1-------------------------------------------
 | 
			
		||||
    SPI_MODE2,              /*!< sample data at falling edge of clock and shift serial data at rising edge */
 | 
			
		||||
    SPI_MODE3               /*!< Sample data at rising edge of clock and shift serial data at falling edge */
 | 
			
		||||
} SPI_mode_t;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  SPI master bit ordering
 | 
			
		||||
 */
 | 
			
		||||
typedef enum
 | 
			
		||||
{
 | 
			
		||||
    SPI_BITORDER_MSB_LSB = 0, /*!< Most significant to least significant bit */
 | 
			
		||||
    SPI_BITORDER_LSB_MSB      /*!< Least significant to most significant bit */
 | 
			
		||||
} SPI_bit_order_t;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Struct containing all parameters necessary to configure the SPI interface
 | 
			
		||||
 */
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
    union
 | 
			
		||||
    {
 | 
			
		||||
        uint8_t SPI_cfg;            /*!< Bit mode and bit order merged, as in the SPI CONFIG register */
 | 
			
		||||
        struct
 | 
			
		||||
        {
 | 
			
		||||
            uint8_t bit_order : 1;  /*!< SPI master bit order */
 | 
			
		||||
            uint8_t mode : 2;       /*!< SPI master mode */
 | 
			
		||||
            uint8_t : 5;            /*!< Padding */
 | 
			
		||||
        }fields;
 | 
			
		||||
    }config;
 | 
			
		||||
    uint8_t frequency;              /*!< SPI master frequency */
 | 
			
		||||
    uint8_t pin_SCK;                /*!< SPI master SCK pin */
 | 
			
		||||
    uint8_t pin_MOSI;               /*!< SPI master MOSI pin */
 | 
			
		||||
    uint8_t pin_MISO;               /*!< SPI master MISO pin */
 | 
			
		||||
    uint8_t pin_CSN;                /*!< SPI master chip select pin */
 | 
			
		||||
} SPI_config_t;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Initializes given SPI master with given configuration.
 | 
			
		||||
 *
 | 
			
		||||
 * After initializing the given SPI master with given configuration, this function also test if the
 | 
			
		||||
 * SPI slave is responding with the configurations by transmitting few test bytes. If the slave did not
 | 
			
		||||
 * respond then error is returned and contents of the rx_data are invalid.
 | 
			
		||||
 *
 | 
			
		||||
 * @param module_number SPI master number (SPIModuleNumber) to initialize.
 | 
			
		||||
 * @param pointer to a struct of type @ref SPIConfig_t containing the SPI configuration parameters.
 | 
			
		||||
 * @return
 | 
			
		||||
 * @retval pointer to direct physical address of the requested SPI module if init was successful
 | 
			
		||||
 * @retval 0, if either init failed or slave did not respond to the test transfer
 | 
			
		||||
 */
 | 
			
		||||
uint32_t* spi_master_init(SPI_module_number_t spi_num, SPI_config_t *spi_config);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Transmit/receive data over SPI bus.
 | 
			
		||||
 *
 | 
			
		||||
 * @note Make sure at least transfer_size number of bytes is allocated in tx_data/rx_data.
 | 
			
		||||
 *
 | 
			
		||||
 * @param spi_num SPI master number (SPIModuleNumber)
 | 
			
		||||
 * @param transfer_size  number of bytes to transmit/receive over SPI master
 | 
			
		||||
 * @param tx_data pointer to the data that needs to be transmitted
 | 
			
		||||
 * @param rx_data pointer to the data that needs to be received
 | 
			
		||||
 * @return
 | 
			
		||||
 * @retval true if transmit/reveive of transfer_size were completed.
 | 
			
		||||
 * @retval false if transmit/reveive of transfer_size were not complete and tx_data/rx_data points to invalid data.
 | 
			
		||||
 */
 | 
			
		||||
bool spi_master_tx_rx(SPI_module_number_t spi_num, uint16_t transfer_size, const uint8_t *tx_data, uint8_t *rx_data);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Transmit data over SPI bus.
 | 
			
		||||
 *
 | 
			
		||||
 * @note Make sure at least transfer_size number of bytes is allocated in tx_data.
 | 
			
		||||
 *
 | 
			
		||||
 * @param spi_num SPI master number (SPIModuleNumber)
 | 
			
		||||
 * @param transfer_size  number of bytes to transmit/receive over SPI master
 | 
			
		||||
 * @param tx_data pointer to the data that needs to be transmitted
 | 
			
		||||
 * @return
 | 
			
		||||
 * @retval true if transmit/reveive of transfer_size were completed.
 | 
			
		||||
 * @retval false if transmit/reveive of transfer_size were not complete and tx_data/rx_data points to invalid data.
 | 
			
		||||
 */
 | 
			
		||||
bool spi_master_tx(SPI_module_number_t spi_num, uint16_t transfer_size, const uint8_t *tx_data);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Receive data over SPI bus.
 | 
			
		||||
 *
 | 
			
		||||
 * @note Make sure at least transfer_size number of bytes is allocated in rx_data.
 | 
			
		||||
 *
 | 
			
		||||
 * @param spi_num SPI master number (SPIModuleNumber)
 | 
			
		||||
 * @param transfer_size  number of bytes to transmit/receive over SPI master
 | 
			
		||||
 * @param rx_data pointer to the data that needs to be received
 | 
			
		||||
 * @return
 | 
			
		||||
 * @retval true if transmit/reveive of transfer_size were completed.
 | 
			
		||||
 * @retval false if transmit/reveive of transfer_size were not complete and tx_data/rx_data points to invalid data.
 | 
			
		||||
 */
 | 
			
		||||
bool spi_master_rx(SPI_module_number_t spi_num, uint16_t transfer_size, uint8_t *rx_data);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										24
									
								
								src/main.cpp
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								src/main.cpp
									
									
									
									
									
								
							@ -2,16 +2,11 @@
 | 
			
		||||
#include <task.h>
 | 
			
		||||
#include <libraries/log/nrf_log.h>
 | 
			
		||||
#include <BlinkApp/BlinkApp.h>
 | 
			
		||||
#include <boards.h>
 | 
			
		||||
#include <libraries/bsp/bsp.h>
 | 
			
		||||
#include <legacy/nrf_drv_clock.h>
 | 
			
		||||
#include <libraries/timer/app_timer.h>
 | 
			
		||||
#include <libraries/gpiote/app_gpiote.h>
 | 
			
		||||
#include <libraries/gfx/nrf_lcd.h>
 | 
			
		||||
#include <drivers/st7789.h>
 | 
			
		||||
#include <DisplayApp/DisplayApp.h>
 | 
			
		||||
#include "nrf_gfx.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if NRF_LOG_ENABLED
 | 
			
		||||
#include "Logging/NrfLogger.h"
 | 
			
		||||
@ -24,7 +19,6 @@ Pinetime::Logging::DummyLogger logger;
 | 
			
		||||
Pinetime::Applications::BlinkApp blinkApp;
 | 
			
		||||
Pinetime::Applications::DisplayApp displayApp;
 | 
			
		||||
TaskHandle_t systemThread;
 | 
			
		||||
//Pinetime::Drivers::st7789 lcd;
 | 
			
		||||
 | 
			
		||||
extern "C" {
 | 
			
		||||
  void vApplicationIdleHook() {
 | 
			
		||||
@ -48,26 +42,10 @@ static void bsp_event_handler(bsp_event_t event)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void SystemTask(void *) {
 | 
			
		||||
  APP_GPIOTE_INIT(2);
 | 
			
		||||
  app_timer_init();
 | 
			
		||||
 | 
			
		||||
  nrf_gpio_cfg_output(14);
 | 
			
		||||
  nrf_gpio_cfg_output(22);
 | 
			
		||||
  nrf_gpio_cfg_output(23);
 | 
			
		||||
  nrf_gpio_pin_clear(14);
 | 
			
		||||
  nrf_gpio_pin_clear(22);
 | 
			
		||||
  nrf_gpio_pin_clear(23);
 | 
			
		||||
//  lcd.Init();
 | 
			
		||||
//  lcd.FillRectangle(0,0,240,240,0xffaa);
 | 
			
		||||
//  lcd.FillRectangle(10,10,50,50,0x011bb);
 | 
			
		||||
//
 | 
			
		||||
//  lcd.FillRectangle(120,120,120,120,0x1212);
 | 
			
		||||
 | 
			
		||||
  blinkApp.Start();
 | 
			
		||||
  displayApp.Start();
 | 
			
		||||
 | 
			
		||||
@ -76,8 +54,6 @@ void SystemTask(void *) {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int main(void) {
 | 
			
		||||
  logger.Init();
 | 
			
		||||
  nrf_drv_clock_init();
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user