ready to alpha
подготовка к альфа-тестированию
This commit is contained in:
commit
e36b851783
164 files changed
+27352
No files matched your search
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
ADS1256 ADC is used for this test. Command for write
|
||||
and read is taken from the datasheet.
|
||||
*/
|
||||
|
||||
#include "SPI.h"
|
||||
|
||||
#define CS_PIN 9
|
||||
|
||||
// address of register to read and write
|
||||
const int reg_to_test = 0x03;
|
||||
uint8_t readVal = 0;
|
||||
uint8_t writeVal = 0;
|
||||
|
||||
// read one register value
|
||||
uint8_t ADC_read_register(uint8_t registerAddress)
|
||||
{
|
||||
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE1));
|
||||
digitalWrite(CS_PIN, LOW); // CS must stay LOW during the entire sequence
|
||||
SPI.transfer(0x10 | registerAddress); // 0x10 = 0001000 = RREG - OR together the two numbers (command + address)
|
||||
SPI.transfer(0x00); // 2nd empty command byte to read one byte
|
||||
delayMicroseconds(5); // see t6 in the datasheet
|
||||
uint8_t readVal = SPI.transfer(0xFF); // read out the register value
|
||||
digitalWrite(CS_PIN, HIGH);
|
||||
SPI.endTransaction();
|
||||
return readVal;
|
||||
}
|
||||
|
||||
// write one register value
|
||||
void ADC_write_register(uint8_t registerAddress, uint8_t registerValueToWrite)
|
||||
{
|
||||
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE1));
|
||||
digitalWrite(CS_PIN, LOW); // CS must stay LOW during the entire sequence
|
||||
delayMicroseconds(5); // see t6 in the datasheet
|
||||
SPI.transfer(0x50 | registerAddress); // 0x50 = 01010000 = WREG
|
||||
SPI.transfer(0x00); // 2nd empty command byte to write one byte
|
||||
SPI.transfer(registerValueToWrite); // pass the value to the register
|
||||
digitalWrite(CS_PIN, HIGH);
|
||||
SPI.endTransaction();
|
||||
}
|
||||
|
||||
// ----------------------------------------- //
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println("Start spi test");
|
||||
|
||||
// init chip select pin
|
||||
pinMode(CS_PIN, OUTPUT);
|
||||
digitalWrite(CS_PIN, HIGH);
|
||||
|
||||
// init spi
|
||||
SPI.begin();
|
||||
delay(100);
|
||||
|
||||
// read initial register value
|
||||
Serial.print("Initial register value: 0x");
|
||||
Serial.println(ADC_read_register(reg_to_test), HEX);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// write new reg value
|
||||
ADC_write_register(reg_to_test, writeVal);
|
||||
Serial.print("Write val: 0x");
|
||||
Serial.println(writeVal, HEX);
|
||||
|
||||
// read updated reg value
|
||||
readVal = ADC_read_register(reg_to_test);
|
||||
Serial.print("Read val: 0x");
|
||||
Serial.println(readVal, HEX);
|
||||
|
||||
// increase write value
|
||||
writeVal++;
|
||||
Serial.println("-------------");
|
||||
|
||||
// wait
|
||||
delay(2000);
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map For SPI
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
SPI KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
begin KEYWORD2
|
||||
beginTransaction KEYWORD2
|
||||
end KEYWORD2
|
||||
endTransaction KEYWORD2
|
||||
transfer KEYWORD2
|
||||
setBitOrder KEYWORD2
|
||||
setDataMode KEYWORD2
|
||||
setClockDivider KEYWORD2
|
||||
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
SPI_CLOCK_DIV4 LITERAL1
|
||||
SPI_CLOCK_DIV8 LITERAL1
|
||||
SPI_CLOCK_DIV16 LITERAL1
|
||||
SPI_CLOCK_DIV32 LITERAL1
|
||||
SPI_CLOCK_DIV64 LITERAL1
|
||||
SPI_CLOCK_DIV128 LITERAL1
|
||||
SPI_CLOCK_DIV256 LITERAL1
|
||||
SPI_MODE0 LITERAL1
|
||||
SPI_MODE1 LITERAL1
|
||||
SPI_MODE2 LITERAL1
|
||||
SPI_MODE3 LITERAL1
|
||||
@@ -0,0 +1,10 @@
|
||||
name=SPI
|
||||
version=0.0.0
|
||||
author=Arduino
|
||||
maintainer=Elron
|
||||
sentence=Enables the communication with devices that use the Serial Peripheral Interface (SPI) Bus.
|
||||
paragraph=SPI is a synchronous serial data protocol used by microcontrollers for communicating with one or more peripheral devices quickly over short distances. It uses three lines common to all devices (MISO, MOSI and SCK) and one specific for each device.
|
||||
category=Communication
|
||||
url=http://www.arduino.cc/en/Reference/SPI
|
||||
architectures=MIK32_Amur
|
||||
|
||||
@@ -0,0 +1,339 @@
|
||||
#include "SPI.h"
|
||||
#include "mik32_hal_spi.h"
|
||||
|
||||
SPI_HandleTypeDef hspi;
|
||||
bool newConfig = false;
|
||||
bool isInited = false;
|
||||
uint32_t currentSpeed = 0;
|
||||
int8_t currentDataOrder = -1;
|
||||
int8_t currentDataMode = -1;
|
||||
static uint8_t reverse_bits(uint8_t byte);
|
||||
|
||||
// ------------------------------------------------------------------ //
|
||||
|
||||
void SPISettings::spiUpdateSettings(uint32_t speedMaximum, uint8_t dataOrder, uint8_t dataMode)
|
||||
{
|
||||
// update config only if something has changed
|
||||
if ((currentSpeed != speedMaximum) || (currentDataOrder != dataOrder) ||
|
||||
(currentDataMode != dataMode))
|
||||
{
|
||||
// Find the fastest clock that is less than or equal to the
|
||||
// given clock rate. If nothing is slow enough - use the slowest.
|
||||
// mik32v2 has the set of deviders, that can be calculate as:
|
||||
// div = 2 << (1...7). Value in braсkets is a value for config register
|
||||
uint8_t divRegVal = 0; // start from minimal divider (maximum speed)
|
||||
while(divRegVal < 7)
|
||||
{
|
||||
divRegVal++; // values from 1 to 7
|
||||
if ((F_CPU/(2 << divRegVal)) <= speedMaximum)
|
||||
// find suitable divider
|
||||
break;
|
||||
}
|
||||
// if break didn't call in cycle, it will be the greatest divRegVal (and divider)
|
||||
|
||||
// update config
|
||||
hspi.Instance = SPI_1;
|
||||
hspi.Init.SPI_Mode = HAL_SPI_MODE_MASTER; // only master mode
|
||||
hspi.Init.CLKPhase = dataMode & 0b00000001;
|
||||
hspi.Init.CLKPolarity = (dataMode & 0b00000010)>>1;
|
||||
hspi.Init.ThresholdTX = 4;
|
||||
hspi.Init.BaudRateDiv = divRegVal;
|
||||
hspi.Init.Decoder = SPI_DECODER_NONE;
|
||||
hspi.Init.ManualCS = SPI_MANUALCS_ON;
|
||||
hspi.Init.ChipSelect = SPI_CS_NONE;
|
||||
|
||||
currentSpeed = speedMaximum;
|
||||
currentDataOrder = dataOrder;
|
||||
currentDataMode = dataMode;
|
||||
newConfig = true;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ //
|
||||
// pins shift in gpio register
|
||||
#define PIN_1_3_GPIO_S 3
|
||||
#define PIN_1_4_GPIO_S 4
|
||||
|
||||
SPIClass SPI;
|
||||
bool SPIClass::spiInUse = false;
|
||||
uint8_t SPIClass::interruptMode = 0;
|
||||
uint8_t SPIClass::interruptMask = 0;
|
||||
|
||||
void SPIClass::begin()
|
||||
{
|
||||
// there is a seller on pin 1.6 which replace D10 from spi NSS pin 1.3 to pin 1.4,
|
||||
// because spi needs pin 1.3 for correct work
|
||||
|
||||
// replace config from 1.3 to 1.4
|
||||
uint8_t config = ((PAD_CONFIG->PORT_1_CFG) & (0b11<<(2*PIN_1_3_GPIO_S))) >> (2*PIN_1_3_GPIO_S);
|
||||
if (config == 0) // common gpio
|
||||
{
|
||||
// pin direction
|
||||
uint8_t direction = ((GPIO_1->DIRECTION_IN) & (1<<PIN_1_3_GPIO_S)) >> PIN_1_3_GPIO_S;
|
||||
if (direction == 1) // input
|
||||
GPIO_1->DIRECTION_IN |= (1<<PIN_1_4_GPIO_S);
|
||||
else // output
|
||||
GPIO_1->DIRECTION_OUT |= (1<<PIN_1_4_GPIO_S);
|
||||
|
||||
// pull up/down
|
||||
uint8_t pupd_1_3 = ((PAD_CONFIG ->PORT_1_PUPD) & (0b11<<(2*PIN_1_3_GPIO_S))) >> (2*PIN_1_3_GPIO_S);
|
||||
PAD_CONFIG ->PORT_1_PUPD &= (~(0b11<<(2*PIN_1_4_GPIO_S))); // clear
|
||||
PAD_CONFIG ->PORT_1_PUPD |= ((pupd_1_3&0b11)<<(2*PIN_1_4_GPIO_S)); // set new
|
||||
|
||||
//current state
|
||||
uint8_t state1_3 = ((GPIO_1->OUTPUT_) & (1<<PIN_1_3_GPIO_S)) >> PIN_1_3_GPIO_S;
|
||||
GPIO_1->OUTPUT_ &= (~(0b1<<PIN_1_4_GPIO_S)); // clear
|
||||
GPIO_1->OUTPUT_ |= ((state1_3&0b1)<<PIN_1_4_GPIO_S); // set new
|
||||
}
|
||||
else if(config == 2) // timer for pwm
|
||||
{
|
||||
// if D10 (spi NSS pin) was used as pwm, we need to stop timer,
|
||||
// because 1.4 don't support timer
|
||||
analogWriteStop(10);
|
||||
ErrorMsgHandler("analogWrite(): D10 cannot be used as PWM pin while SPI is running");
|
||||
}
|
||||
|
||||
// switch seller to pin 1.4
|
||||
HAL_GPIO_PinConfig(GPIO_1, GPIO_PIN_6, HAL_GPIO_MODE_GPIO_OUTPUT, HAL_GPIO_PULL_NONE, HAL_GPIO_DS_2MA);
|
||||
HAL_GPIO_WritePin(GPIO_1, GPIO_PIN_6, GPIO_PIN_HIGH);
|
||||
blockSpiPin();
|
||||
|
||||
spiInUse = true;
|
||||
}
|
||||
|
||||
void SPIClass::end()
|
||||
{
|
||||
if (spiInUse && isInited)
|
||||
{
|
||||
// turn off spi
|
||||
HAL_SPI_Disable(&hspi);
|
||||
|
||||
// deinit spi gpio pins
|
||||
if (hspi.Instance == SPI_1) // only spi1 is using in currunt version
|
||||
{
|
||||
HAL_GPIO_PinConfig(GPIO_1, (HAL_PinsTypeDef)(GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2),
|
||||
HAL_GPIO_MODE_GPIO_INPUT, HAL_GPIO_PULL_NONE, HAL_GPIO_DS_2MA);
|
||||
}
|
||||
|
||||
// return D10 with common gpio config to pin 1.3
|
||||
PAD_CONFIG->PORT_1_CFG &= (~(0b11<<(2*PIN_1_3_GPIO_S))); // set config to 0 - common gpio mode
|
||||
|
||||
// pin direction
|
||||
uint8_t direction = ((GPIO_1->DIRECTION_IN) & (1<<PIN_1_4_GPIO_S)) >> PIN_1_4_GPIO_S;
|
||||
if (direction == 1) // input
|
||||
GPIO_1->DIRECTION_IN |= (1<<PIN_1_3_GPIO_S);
|
||||
else // output
|
||||
GPIO_1->DIRECTION_OUT |= (1<<PIN_1_3_GPIO_S);
|
||||
|
||||
// pull up/down
|
||||
uint8_t pupd_1_4 = ((PAD_CONFIG ->PORT_1_PUPD) & (0b11<<(2*PIN_1_4_GPIO_S))) >> (2*PIN_1_4_GPIO_S);
|
||||
PAD_CONFIG ->PORT_1_PUPD &= (~(0b11<<(2*PIN_1_3_GPIO_S))); // clear
|
||||
PAD_CONFIG ->PORT_1_PUPD |= ((pupd_1_4&0b11)<<(2*PIN_1_3_GPIO_S)); // set new
|
||||
|
||||
// current state
|
||||
uint8_t state1_4 = ((GPIO_1->OUTPUT_) & (1<<PIN_1_4_GPIO_S)) >> PIN_1_4_GPIO_S;
|
||||
GPIO_1->OUTPUT_ &= (~(0b1<<PIN_1_3_GPIO_S)); // clear
|
||||
GPIO_1->OUTPUT_ |= ((state1_4&0b1)<<PIN_1_3_GPIO_S); // set new
|
||||
|
||||
// switch seller back to pin 1.3
|
||||
HAL_GPIO_WritePin(GPIO_1, GPIO_PIN_6, GPIO_PIN_LOW);
|
||||
unblockSpiPin();
|
||||
|
||||
spiInUse = false;
|
||||
isInited = false;
|
||||
interruptMode = 0;
|
||||
interruptMask = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void SPIClass::usingInterrupt(uint8_t interruptNumber)
|
||||
{
|
||||
if(interruptNumber < EXTERNAL_NUM_INTERRUPTS)
|
||||
{
|
||||
noInterrupts(); // prevent transactionBegin
|
||||
interruptMask |= (1 << interruptNumber); // add new interrupt to mask
|
||||
if (!interruptMode)
|
||||
interruptMode = 1;
|
||||
interrupts();
|
||||
}
|
||||
}
|
||||
|
||||
void SPIClass::notUsingInterrupt(uint8_t interruptNumber)
|
||||
{
|
||||
if(interruptNumber < EXTERNAL_NUM_INTERRUPTS)
|
||||
{
|
||||
noInterrupts(); // prevent transactionBegin
|
||||
interruptMask &= ~(1<<interruptNumber); // delete interrupt from mask
|
||||
if (!interruptMask)
|
||||
interruptMode = 0;
|
||||
interrupts();
|
||||
}
|
||||
}
|
||||
|
||||
void SPIClass::beginTransaction(SPISettings settings)
|
||||
{
|
||||
// disable interrupts in use if necessary
|
||||
if (spiInUse && (interruptMode > 0))
|
||||
{
|
||||
for (uint8_t i = 0; i < EXTERNAL_NUM_INTERRUPTS; i++)
|
||||
{
|
||||
if (interruptMask & (1 << i))
|
||||
// disable every interrupt by it's number
|
||||
disableInterrupt(i);
|
||||
}
|
||||
}
|
||||
|
||||
// initialize spi bus or update config
|
||||
if(spiInUse && ((!isInited) || newConfig))
|
||||
{
|
||||
// initialize spi with given settings
|
||||
if (HAL_SPI_Init(&hspi) != HAL_OK)
|
||||
ErrorMsgHandler("SPI.beginTransaction(): initialization error");
|
||||
else
|
||||
isInited = true;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t SPIClass::transfer(uint8_t data)
|
||||
{
|
||||
uint8_t rxByte = 0;
|
||||
|
||||
if (isInited)
|
||||
{
|
||||
// reverse bits if LSB mode needed
|
||||
if (currentDataOrder == LSBFIRST)
|
||||
data = reverse_bits(data);
|
||||
|
||||
// send and recieve data
|
||||
HAL_StatusTypeDef SPI_Status = HAL_SPI_Exchange(&hspi, &data, &rxByte, 1, SPI_TIMEOUT_DEFAULT*2);
|
||||
if (SPI_Status != HAL_OK)
|
||||
HAL_SPI_ClearError(&hspi);
|
||||
|
||||
// reverse bits again if LSB mode needed
|
||||
if (currentDataOrder == LSBFIRST)
|
||||
rxByte = reverse_bits(rxByte);
|
||||
}
|
||||
return rxByte;
|
||||
}
|
||||
|
||||
uint16_t SPIClass::transfer16(uint16_t data)
|
||||
{
|
||||
uint8_t buf[2];
|
||||
uint16_t rxVal = 0;
|
||||
if (isInited)
|
||||
{
|
||||
// prepare data for send
|
||||
if (currentDataOrder == LSBFIRST)
|
||||
{
|
||||
// least significant byte is forward and reverse bits inside each byte
|
||||
buf[0] = reverse_bits(data&0xFF);
|
||||
buf[1] = reverse_bits((data>>8)&0xFF);
|
||||
}
|
||||
else
|
||||
{
|
||||
// most significant byte is forward
|
||||
buf[0] = (data>>8)&0xFF;
|
||||
buf[1] = data&0xFF;
|
||||
}
|
||||
|
||||
// send and recieve data
|
||||
HAL_StatusTypeDef SPI_Status = HAL_SPI_Exchange(&hspi, buf, buf, 2, SPI_TIMEOUT_DEFAULT*2);
|
||||
if (SPI_Status != HAL_OK)
|
||||
HAL_SPI_ClearError(&hspi);
|
||||
|
||||
// process the received data
|
||||
if (currentDataOrder == LSBFIRST)
|
||||
// reverse bits for LSB mode
|
||||
rxVal = ( ((uint16_t)reverse_bits(buf[1]) ) << 8) | reverse_bits(buf[0]);
|
||||
else
|
||||
rxVal = ( ((uint16_t)buf[0]) << 8) | buf[1];
|
||||
}
|
||||
return rxVal;
|
||||
}
|
||||
|
||||
void SPIClass::transfer(void *buf, size_t count)
|
||||
{
|
||||
if (count == 0)
|
||||
return;
|
||||
|
||||
if (isInited)
|
||||
{
|
||||
uint8_t *p = (uint8_t *)buf;
|
||||
|
||||
// reverse bits in buffer if LSB mode needed
|
||||
if (currentDataOrder == LSBFIRST)
|
||||
{
|
||||
for (uint32_t i = 0; i < count; i++)
|
||||
*(p+i) = reverse_bits(*(p+i));
|
||||
}
|
||||
|
||||
// send and recieve data using the same buffer
|
||||
HAL_StatusTypeDef SPI_Status = HAL_SPI_Exchange(&hspi, (uint8_t*)buf, (uint8_t*)buf, count, SPI_TIMEOUT_DEFAULT*2);
|
||||
if (SPI_Status != HAL_OK)
|
||||
HAL_SPI_ClearError(&hspi);
|
||||
|
||||
// reverse bits if LSB mode needed
|
||||
if (currentDataOrder == LSBFIRST)
|
||||
{
|
||||
p = (uint8_t *)buf; // return to buf beginning
|
||||
for (uint32_t i = 0; i < count; i++)
|
||||
*(p+i) = reverse_bits(*(p+i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SPIClass::endTransaction(void)
|
||||
{
|
||||
// enable interrupts in use
|
||||
if (spiInUse && (interruptMode > 0))
|
||||
{
|
||||
for (uint8_t i = 0; i < EXTERNAL_NUM_INTERRUPTS; i++)
|
||||
{
|
||||
if (interruptMask & (1 << i))
|
||||
// enable every interrupt in use by it's number
|
||||
enableInterrupt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------ //
|
||||
void SPIClass::setBitOrder(uint8_t bitOrder)
|
||||
{
|
||||
currentDataOrder = bitOrder;
|
||||
}
|
||||
|
||||
void SPIClass::setDataMode(uint8_t dataMode)
|
||||
{
|
||||
uint32_t config = hspi.Instance->CONFIG;
|
||||
HAL_SPI_Disable(&hspi);
|
||||
hspi.Init.CLKPhase = dataMode & 0b00000001;
|
||||
hspi.Init.CLKPolarity = (dataMode & 0b00000010)>>1;
|
||||
config &= ~((1 << SPI_CONFIG_CLK_PH_S) | (1 << SPI_CONFIG_CLK_POL_S)); // clear
|
||||
config |= ((hspi.Init.CLKPhase << SPI_CONFIG_CLK_PH_S) |
|
||||
(hspi.Init.CLKPolarity << SPI_CONFIG_CLK_POL_S)); // set new
|
||||
hspi.Instance->CONFIG = config;
|
||||
HAL_SPI_Enable(&hspi);
|
||||
}
|
||||
|
||||
void SPIClass::setClockDivider(uint8_t clockDiv)
|
||||
{
|
||||
// if divider is in valid range
|
||||
if ((clockDiv >= SPI_CLOCK_DIV4) && (clockDiv <= SPI_CLOCK_DIV256))
|
||||
{
|
||||
uint32_t config = hspi.Instance->CONFIG;
|
||||
HAL_SPI_Disable(&hspi);
|
||||
hspi.Init.BaudRateDiv = clockDiv;
|
||||
config &= ~(0b111 << SPI_CONFIG_BAUD_RATE_DIV_S); // clear
|
||||
config |= (hspi.Init.BaudRateDiv << SPI_CONFIG_BAUD_RATE_DIV_S); // set new
|
||||
hspi.Instance->CONFIG = config;
|
||||
HAL_SPI_Enable(&hspi);
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t reverse_bits(uint8_t byte)
|
||||
{
|
||||
byte = (byte & 0xF0) >> 4 | (byte & 0x0F) << 4;
|
||||
byte = (byte & 0xCC) >> 2 | (byte & 0x33) << 2;
|
||||
byte = (byte & 0xAA) >> 1 | (byte & 0x55) << 1;
|
||||
return byte;
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright (c) 2010 by Cristian Maglie <c.maglie@arduino.cc>
|
||||
* Copyright (c) 2014 by Paul Stoffregen <paul@pjrc.com> (Transaction API)
|
||||
* Copyright (c) 2014 by Matthijs Kooijman <matthijs@stdin.nl> (SPISettings AVR)
|
||||
* Copyright (c) 2014 by Andrew J. Kroll <xxxajk@gmail.com> (atomicity fixes)
|
||||
* SPI Master library for arduino.
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of either the GNU General Public License version 2
|
||||
* or the GNU Lesser General Public License version 2.1, both as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef _SPI_H_INCLUDED
|
||||
#define _SPI_H_INCLUDED
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
// SPI_HAS_TRANSACTION means SPI has beginTransaction(), endTransaction(),
|
||||
// usingInterrupt(), and SPISetting(clock, bitOrder, dataMode)
|
||||
#define SPI_HAS_TRANSACTION 1
|
||||
|
||||
// SPI_HAS_NOTUSINGINTERRUPT means that SPI has notUsingInterrupt() method
|
||||
#define SPI_HAS_NOTUSINGINTERRUPT 1
|
||||
|
||||
// SPI_ATOMIC_VERSION means that SPI has atomicity fixes and what version.
|
||||
// This way when there is a bug fix you can check this define to alert users
|
||||
// of your code if it uses better version of this library.
|
||||
// This also implies everything that SPI_HAS_TRANSACTION as documented above is
|
||||
// available too.
|
||||
#define SPI_ATOMIC_VERSION 1
|
||||
|
||||
#define SPI_DEFAULT_SPEED 4000000
|
||||
|
||||
#ifndef LSBFIRST
|
||||
#define LSBFIRST 0
|
||||
#endif
|
||||
#ifndef MSBFIRST
|
||||
#define MSBFIRST 1
|
||||
#endif
|
||||
|
||||
// dividers for setClockDivider()
|
||||
#define SPI_CLOCK_DIV4 0x01 // 8 MHz
|
||||
#define SPI_CLOCK_DIV8 0x02 // 4 MHz
|
||||
#define SPI_CLOCK_DIV16 0x03 // 2 MHz
|
||||
#define SPI_CLOCK_DIV32 0x04 // 1 MHz
|
||||
#define SPI_CLOCK_DIV64 0x05 // 500 kHz
|
||||
#define SPI_CLOCK_DIV128 0x06 // 250 kHz
|
||||
#define SPI_CLOCK_DIV256 0x07 // 125 kHz
|
||||
|
||||
// mode[1] - polarity, mode[0] - phase
|
||||
#define SPI_MODE0 0b00
|
||||
#define SPI_MODE1 0b01
|
||||
#define SPI_MODE2 0b10
|
||||
#define SPI_MODE3 0b11
|
||||
|
||||
|
||||
class SPISettings
|
||||
{
|
||||
public:
|
||||
SPISettings(uint32_t speedMaximum, uint8_t dataOrder, uint8_t dataMode)
|
||||
{
|
||||
spiUpdateSettings(speedMaximum, dataOrder, dataMode);
|
||||
}
|
||||
|
||||
SPISettings()
|
||||
{
|
||||
spiUpdateSettings(SPI_DEFAULT_SPEED, MSBFIRST, SPI_MODE0);
|
||||
}
|
||||
|
||||
private:
|
||||
void spiUpdateSettings(uint32_t speedMaximum, uint8_t dataOrder, uint8_t dataMode);
|
||||
|
||||
friend class SPIClass;
|
||||
};
|
||||
|
||||
|
||||
class SPIClass
|
||||
{
|
||||
private:
|
||||
static bool spiInUse;
|
||||
static uint8_t interruptMode; // 0=none, 1=mask
|
||||
static uint8_t interruptMask; // which interrupts to mask
|
||||
|
||||
public:
|
||||
// Initialize the SPI library
|
||||
static void begin();
|
||||
|
||||
// If SPI is used from within an interrupt, this function registers
|
||||
// that interrupt with the SPI library, so beginTransaction() can
|
||||
// prevent conflicts. The input interruptNumber is the number used
|
||||
// with attachInterrupt.
|
||||
static void usingInterrupt(uint8_t interruptNumber);
|
||||
// And this does the opposite.
|
||||
static void notUsingInterrupt(uint8_t interruptNumber);
|
||||
// Note: the usingInterrupt and notUsingInterrupt functions should
|
||||
// not to be called from ISR context or inside a transaction.
|
||||
// For details see:
|
||||
// https://github.com/arduino/Arduino/pull/2381
|
||||
// https://github.com/arduino/Arduino/pull/2449
|
||||
|
||||
// Before using SPI.transfer() or asserting chip select pins,
|
||||
// this function is used to gain exclusive access to the SPI bus
|
||||
// and configure the correct settings.
|
||||
void beginTransaction(SPISettings settings);
|
||||
|
||||
// Write to the SPI bus (MOSI pin) and also receive (MISO pin)
|
||||
uint8_t transfer(uint8_t data);
|
||||
uint16_t transfer16(uint16_t data);
|
||||
void transfer(void *buf, size_t count);
|
||||
|
||||
// After performing a group of transfers and releasing the chip select
|
||||
// signal, this function allows others to access the SPI bus
|
||||
void endTransaction(void);
|
||||
|
||||
// Disable the SPI bus
|
||||
static void end();
|
||||
|
||||
// This function is deprecated. New applications should use
|
||||
// beginTransaction() to configure SPI settings.
|
||||
void setBitOrder(uint8_t bitOrder);
|
||||
|
||||
// This function is deprecated. New applications should use
|
||||
// beginTransaction() to configure SPI settings.
|
||||
void setDataMode(uint8_t dataMode);
|
||||
// This function is deprecated. New applications should use
|
||||
// beginTransaction() to configure SPI settings.
|
||||
void setClockDivider(uint8_t clockDiv);
|
||||
};
|
||||
|
||||
extern SPIClass SPI;
|
||||
|
||||
#endif
|
||||
Reference in new issue
Block a user