ready to alpha

подготовка к альфа-тестированию
This commit is contained in:
khristolyubov committed 2024-08-19 22:44:04 +07:00
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);
}
+37
View File
@@ -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
+10
View File
@@ -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
+339
View File
@@ -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;
}
+133
View File
@@ -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