Convert Spi and GFX to C++.
parent
0db16bd827
commit
6fbb6c8f70
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -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);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
@ -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,18 +1,21 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
namespace Pinetime {
|
namespace Pinetime {
|
||||||
namespace Drivers {
|
namespace Drivers {
|
||||||
class st7789 {
|
class SpiMaster;
|
||||||
|
class St7789 {
|
||||||
public:
|
public:
|
||||||
ret_code_t Init();
|
explicit St7789(SpiMaster& spiMaster, uint8_t pinDataCommand);
|
||||||
|
void Init();
|
||||||
void Uninit();
|
void Uninit();
|
||||||
void DrawPixel(uint16_t x, uint16_t y, uint32_t color);
|
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);
|
void FillRectangle(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ret_code_t InitHw() const;
|
SpiMaster& spi;
|
||||||
void InitCommands();
|
uint8_t pinDataCommand;
|
||||||
|
|
||||||
void SoftwareReset();
|
void SoftwareReset();
|
||||||
void SleepOut();
|
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
|
|
Loading…
Reference in New Issue