Skip to content

Commit

Permalink
Add support for SoftwareSerial library
Browse files Browse the repository at this point in the history
Add support for SoftwareSerial library, from
sandeepmistry#205
  • Loading branch information
ct6502 committed Dec 27, 2017
1 parent 871447f commit d29cea0
Show file tree
Hide file tree
Showing 10 changed files with 752 additions and 40 deletions.
12 changes: 6 additions & 6 deletions cores/nRF5/Arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ extern "C"{
#define clockCyclesToMicroseconds(a) ( ((a) * 1000L) / (SystemCoreClock / 1000L) )
#define microsecondsToClockCycles(a) ( (a) * (SystemCoreClock / 1000000L) )

void yield( void ) ;
void yield( void );

/* sketch */
void setup( void ) ;
void loop( void ) ;
void setup( void );
void loop( void );

#include "WVariant.h"

Expand Down Expand Up @@ -92,12 +92,12 @@ void loop( void ) ;

#define bit(b) (1UL << (b))

#define digitalPinToPort(P) ( &(NRF_GPIO[P]) )
#define digitalPinToPort(P) ( NRF_GPIO ) // NRF_P0 = P0.00 - P0.31, NRF_P1 = P1.00 - P1.15 (e.g. nRF52840)
#define digitalPinToBitMask(P) ( 1 << g_ADigitalPinMap[P] )
//#define analogInPinToBit(P) ( )
#define portOutputRegister(port) ( &(port->OUTSET) )
#define portOutputRegister(port) ( &(port->OUT) )
#define portInputRegister(port) ( &(port->IN) )
#define portModeRegister(port) ( &(port->DIRSET) )
#define portModeRegister(port) ( &(port->DIR) )
#define digitalPinHasPWM(P) ( true )

/*
Expand Down
92 changes: 59 additions & 33 deletions cores/nRF5/WInterrupts.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,42 +30,46 @@
#define NUMBER_OF_GPIO_TE 4
#endif

static voidFuncPtr callbacksInt[NUMBER_OF_GPIO_TE];
static int8_t channelMap[NUMBER_OF_GPIO_TE];
static voidFuncPtr callbacksInt[NUMBER_OF_GPIO_TE] = { NULL };
static int8_t channelMap[NUMBER_OF_GPIO_TE] = { -1 };
static int enabled = 0;

/* Configure I/O interrupt sources */
static void __initialize()
{
memset(callbacksInt, 0, sizeof(callbacksInt));
memset(channelMap, -1, sizeof(channelMap));

NVIC_DisableIRQ(GPIOTE_IRQn);
NVIC_ClearPendingIRQ(GPIOTE_IRQn);
NVIC_SetPriority(GPIOTE_IRQn, 1);
NVIC_SetPriority(GPIOTE_IRQn, 3); // Same priority as Uart
NVIC_EnableIRQ(GPIOTE_IRQn);
}

/*
* \brief Specifies a named Interrupt Service Routine (ISR) to call when an interrupt occurs.
* Replaces any previous function that was attached to the interrupt.
*/
void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode)
int attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode)
{
if (!enabled) {
__initialize();
enabled = 1;
}
uint32_t polarity;
uint8_t ch;

if (pin >= PINS_COUNT) {
return;
if (pin >= PINS_COUNT)
{
return -1;
}

pin = g_ADigitalPinMap[pin];

uint32_t polarity;
switch (mode)
{
//gpiote channel does not support LOW and HIGH mode. These are mantained for compatibility
case LOW:
polarity = GPIOTE_CONFIG_POLARITY_HiToLo; //same as FALLING
break;

case HIGH:
polarity = GPIOTE_CONFIG_POLARITY_LoToHi; //same as RISING
break;

switch (mode) {
case CHANGE:
polarity = GPIOTE_CONFIG_POLARITY_Toggle;
break;
Expand All @@ -79,11 +83,13 @@ void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode)
break;

default:
return;
return -1;
}

for (int ch = 0; ch < NUMBER_OF_GPIO_TE; ch++) {
if (channelMap[ch] == -1 || (uint32_t)channelMap[ch] == pin) {
for (ch = 0; ch < NUMBER_OF_GPIO_TE; ch++)
{
if (channelMap[ch] == -1 || (uint32_t)channelMap[ch] == pin)
{
channelMap[ch] = pin;
callbacksInt[ch] = callback;

Expand All @@ -98,6 +104,16 @@ void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode)
break;
}
}

// enable the interrupt after the first one is configured
if (!enabled)
{
__initialize();
enabled = 1;
}

// return the interrupt mask
return (1 << ch);
}

/*
Expand Down Expand Up @@ -127,21 +143,31 @@ void detachInterrupt(uint32_t pin)

void GPIOTE_IRQHandler()
{
uint32_t event = offsetof(NRF_GPIOTE_Type, EVENTS_IN[0]);

for (int ch = 0; ch < NUMBER_OF_GPIO_TE; ch++) {
if ((*(uint32_t *)((uint32_t)NRF_GPIOTE + event) == 0x1UL) && (NRF_GPIOTE->INTENSET & (1 << ch))) {
if (channelMap[ch] != -1 && callbacksInt[ch]) {
callbacksInt[ch]();
}

*(uint32_t *)((uint32_t)NRF_GPIOTE + event) = 0;
#if __CORTEX_M == 0x04
volatile uint32_t dummy = *((volatile uint32_t *)((uint32_t)NRF_GPIOTE + event));
(void)dummy;
#endif
uint32_t event;
uint8_t ch;

for (ch = 0; ch < NUMBER_OF_GPIO_TE; ch++)
{
event = offsetof(NRF_GPIOTE_Type, EVENTS_IN[ch]);
if ((*(uint32_t *)((uint32_t)NRF_GPIOTE + event) == 0x1UL) && (NRF_GPIOTE->INTENSET & (1 << ch)))
{
break;
}

event = (uint32_t)((uint32_t)event + 4);
}

// clear event
*(uint32_t *)((uint32_t)NRF_GPIOTE + event) = 0;
#if __CORTEX_M == 0x04
volatile uint32_t dummy = *((volatile uint32_t *)((uint32_t)NRF_GPIOTE + event));
(void)dummy;
#endif

// disable the interrupt
NRF_GPIOTE->INTENCLR = (1 << ch);

// initiate the callback
callbacksInt[ch]();

// enable the interrupt
NRF_GPIOTE->INTENSET = (1 << ch);
}
2 changes: 1 addition & 1 deletion cores/nRF5/WInterrupts.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ typedef void (*voidFuncPtr)(void);
* \brief Specifies a named Interrupt Service Routine (ISR) to call when an interrupt occurs.
* Replaces any previous function that was attached to the interrupt.
*/
void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode);
int attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode);

/*
* \brief Turns off the given interrupt.
Expand Down
30 changes: 30 additions & 0 deletions libraries/SoftwareSerial/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
### SoftwareSerial

This library is based off SoftwareSerial from @arduino-org's arduino-core-nrf52 release [1.0.1](https://github.com/arduino-org/arduino-core-nrf52/releases/tag/1.0.1)

#### Modifications
* merged SoftwareSerial.cpp into SoftwareSerial.h to allow ```_SS_MAX_RX_BUFF``` to be user-defined
* added ```_SS_TX_ONLY``` user define to allow this to be used as a transmit only library (no interrupts used)

### License

I do not claim copyright on the code, license taken from SoftwareSerial.h header.

```
SoftwareSerial.h - library for Arduino Primo
Copyright (c) 2016 Arduino. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
```
Loading

0 comments on commit d29cea0

Please sign in to comment.