1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/boards/avsextrem/drivers/avsextrem-ssp0.c

426 lines
9.4 KiB
C
Raw Normal View History

2013-08-19 16:17:58 +02:00
/*
2013-09-19 16:53:35 +02:00
* avsextrem-ssp0.c - implementation of the SPI0 interface for the LPC2387,
2013-08-19 16:17:58 +02:00
* and the AVSESTREM board.
2013-09-19 16:53:35 +02:00
* Copyright (C) 2013 Freie Universität Berlin
2013-08-19 16:17:58 +02:00
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
2013-08-19 16:17:58 +02:00
*/
/**
* @file
* @internal
* @brief Implements the SPI0 interface for the LPC2387
*
* @author Marco Ziegert <ziegert@inf.fu-berlin.de>
* @author Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
* @version $Revision: 3854 $
*
* @note $Id: avsextrem-ssp0.c 3854 2013-08-14 15:27:01Z zkasmi $
*/
2013-09-19 16:53:35 +02:00
#include "lpc23xx.h" /* LPC23XX/24xx Peripheral Registers */
2013-08-19 16:17:58 +02:00
#include "cpu.h"
#include "VIC.h"
#include "ssp0-board.h"
#include "smb380-board.h"
//#include "mma7455l-board.h"
#include "gpioint.h"
#include <stdio.h>
#include "lpm.h"
//uint16_t sampleRateMMA7455L;
//uint16_t interruptTicksMMA7455L;
//
//static void MMA7455L_extIntHandler(void);
uint32_t SSP0Init(void)
{
2013-09-19 16:53:35 +02:00
/*
* enable clock to SSP0 for security reason.
* By default, it's enabled already
*/
2013-08-19 16:17:58 +02:00
PCONP |= PCSSP0;
2013-09-19 16:53:35 +02:00
//TODO: configure CLK, MISO, MOSI by default as GPIOs.
2013-08-19 16:17:58 +02:00
#if USE_CS
2013-09-19 16:53:35 +02:00
// P1.20 1.21 1.23 1.24
// PINSEL3 |= BIT8 | BIT9 | BIT10 | BIT11 | BIT14 | BIT15 | BIT16 | BIT17;
2013-08-19 16:17:58 +02:00
#else
2013-09-19 16:53:35 +02:00
// No SSEL0
// PINSEL3 |= BIT8 | BIT9 | BIT14 | BIT15 | BIT16 | BIT17; //1.20 1.23 1.24
2013-08-19 16:17:58 +02:00
#endif
#if SSP1_INTERRUPT_MODE
if (install_irq(SSP1_INT, (void *)SSP0Handler, HIGHEST_PRIORITY) == FALSE) {
return (FALSE);
}
2013-09-19 16:53:35 +02:00
/*
* Set SSPINMS registers to enable interrupts,
* enable all error related interrupts
*/
2013-08-19 16:17:58 +02:00
SSP1IMSC = SSPIMSC_RORIM | SSPIMSC_RTIM;
#endif
return (1);
}
2013-09-19 16:53:35 +02:00
/*
* datasize (wordsize) in decimal (4-16), cpol&cpha =(0/1) and frequency divided
* by 1000 (e.g. 8 MHz = 8000)
2013-08-19 16:17:58 +02:00
*/
2013-09-19 16:53:35 +02:00
uint8_t SSP0Prepare(uint8_t chip, uint8_t datasize, uint8_t cpol, uint8_t cpha,
uint16_t freq)
2013-08-19 16:17:58 +02:00
{
switch (chip) {
case BMA180_INTERN:
case SMB380_ACC: {
#if USE_CS
2013-09-19 16:53:35 +02:00
PINSEL3 |= BIT8 | BIT9 | BIT10 | BIT11 | BIT14 | BIT15 | BIT16 |
BIT17; //P1.20 1.21 1.23 1.24
2013-08-19 16:17:58 +02:00
#else
2013-09-19 16:53:35 +02:00
// 1.20 1.23 1.24 are not configured as SSEL0
PINSEL3 |= BIT8 | BIT9 | BIT14 | BIT15 | BIT16 | BIT17;
2013-08-19 16:17:58 +02:00
#endif
break;
}
case BMA180_EXTERN:
case L3G_EXTERN:
case NANOPAN:
case ACAMDMS: {
#if USE_CS
PINSEL0 |= BIT31;
2013-09-19 16:53:35 +02:00
PINSEL1 |= BIT1 | BIT3 | BIT5; // P0.15 0.16 0.17 0.18
2013-08-19 16:17:58 +02:00
#else
2013-09-19 16:53:35 +02:00
// Turn on NanoPAN
2013-08-19 16:17:58 +02:00
PINSEL0 |= BIT31;
2013-09-19 16:53:35 +02:00
// 0.15 0.17 0.18 are not configured as SSEL0
PINSEL1 |= BIT3 | BIT5;
2013-08-19 16:17:58 +02:00
#endif
break;
}
case NORDIC: {
PINSEL0 |= BIT31;
2013-09-19 16:53:35 +02:00
PINSEL1 |= BIT3 | BIT5; // 0.15 0.17 0.18 SSEL0 (No)
2013-08-19 16:17:58 +02:00
break;
}
default: {
printf("wrong CHIP selected\n");
return 0;
}
}
uint32_t SSP0CR0tmp = 0;
switch (datasize) {
case 4:
SSP0CR0tmp = BIT0 | BIT1;
break;
case 5:
SSP0CR0tmp = BIT2;
break;
case 6:
SSP0CR0tmp = BIT0 | BIT2;
break;
case 7:
SSP0CR0tmp = BIT1 | BIT2;
break;
case 8:
SSP0CR0tmp = BIT0 | BIT1 | BIT2;
break;
case 9:
SSP0CR0tmp = BIT3;
break;
case 10:
SSP0CR0tmp = BIT0 | BIT3;
break;
case 11:
SSP0CR0tmp = BIT1 | BIT3;
break;
case 12:
SSP0CR0tmp = BIT0 | BIT1 | BIT3;
break;
case 13:
SSP0CR0tmp = BIT2 | BIT3;
break;
case 14:
SSP0CR0tmp = BIT0 | BIT2 | BIT3;
break;
case 15:
SSP0CR0tmp = BIT1 | BIT2 | BIT3;
break;
case 16:
SSP0CR0tmp = BIT0 | BIT1 | BIT2 | BIT3;
break;
default:
return 0;
}
if (cpol) {
SSP0CR0tmp |= BIT6;
}
if (cpha) {
SSP0CR0tmp |= BIT7;
}
2013-09-19 16:53:35 +02:00
SSP0CR1 = 0x00; // SSP0 disabled
2013-08-19 16:17:58 +02:00
// Setting xx-Bit Datasize, CPOL and CPHA
2013-08-19 16:17:58 +02:00
SSP0CR0 = SSP0CR0tmp;
// Clock Setup
uint32_t pclksel;
uint32_t cpsr;
lpc2387_pclk_scale(F_CPU / 1000, freq, &pclksel, &cpsr);
PCLKSEL1 &= ~(BIT10 | BIT11); // CCLK to PCLK divider ???
PCLKSEL1 |= pclksel << 10;
SSP0CPSR = cpsr;
// Enable
2013-09-19 16:53:35 +02:00
SSP0CR1 |= BIT1; // SSP0 enabled
2013-08-19 16:17:58 +02:00
uint32_t dummy;
2013-08-19 16:17:58 +02:00
for (uint32_t i = 0; i < FIFOSIZE; i++) {
dummy = SSP0DR; // clear the RxFIFO
2013-08-19 16:17:58 +02:00
}
/* to suppress unused-but-set-variable */
(void) dummy;
2013-08-19 16:17:58 +02:00
return 1;
}
uint8_t SSP0Unprepare(uint8_t chip)
{
switch (chip) {
case BMA180_INTERN:
case SMB380_ACC: {
2013-09-19 16:53:35 +02:00
// Turn off Acceleration Sensor
PINSEL3 &= ~(BIT8 | BIT9 | BIT10 | BIT11 | BIT14 | BIT15 | BIT16 |
BIT17);
2013-08-19 16:17:58 +02:00
FIO1DIR |= BIT20 | BIT21 | BIT24;
FIO1DIR &= ~BIT23; // MISO as Input
FIO1SET = BIT20 | BIT24; /*
2013-09-19 16:53:35 +02:00
* CLK + SSEL + MOSI GPIO as Output
* TODO: depends on CPOL+CPHA Settings
*/
2013-08-19 16:17:58 +02:00
FIO1CLR = BIT21;
break;
}
case BMA180_EXTERN:
case L3G_EXTERN:
case NORDIC:
case NANOPAN:
case ACAMDMS: {
2013-09-19 16:53:35 +02:00
// Turn off Nanopan (Pins to GPIO)
2013-08-19 16:17:58 +02:00
PINSEL0 &= ~(BIT30 | BIT31); //CLK to GPIO
PINSEL1 &= ~(BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5);
FIO0DIR |= BIT15 | BIT16 | BIT18; //CLK + SSEL + MOSI GPIO as Output
2013-09-19 16:53:35 +02:00
FIO0DIR &= ~BIT17; // MISO as Input
FIO0SET = BIT15 | BIT16; /*
* CLK + SSEL + MOSI GPIO as Output
* TODO: depends on CPOL+CPHA Settings
*/
2013-08-19 16:17:58 +02:00
FIO0CLR = BIT18;
break;
}
default: {
printf("wrong CHIP selected\n");
return 0;
}
}
return 1;
}
2013-09-19 16:53:35 +02:00
unsigned char SMB380_ssp_write(const unsigned char regAddr,
const unsigned char data, unsigned char flag)
2013-08-19 16:17:58 +02:00
{
uint16_t temp = 0;
if (flag) {
temp = (unsigned int)(((regAddr & 0xFF7F) << 8) | data);
}
else {
temp = (((unsigned int)(regAddr | 0x80) << 8) | 0xFF);
}
return SSP0_write(temp, SMB380_ACC);
}
unsigned char SSP0_write(const uint16_t data, uint8_t device)
{
unsigned char ret = 1;
while ((SSP0SR & (SSPSR_TNF | SSPSR_BSY)) != SSPSR_TNF)
;
if (!USE_CS) {
switch (device) {
case BMA180_INTERN:
case SMB380_ACC: {
FIO1CLR = SSP0_SEL;
break;
}
case BMA180_EXTERN:
case L3G_EXTERN:
case NANOPAN: {
FIO0CLR = SSP0_SELN;
break;
}
case ACAMDMS:
case NORDIC:
2013-09-19 16:53:35 +02:00
// Chip Select is done in Nordic driver
2013-08-19 16:17:58 +02:00
break;
default:
ret = 0;
goto ret;
}
}
SSP0DR = data;
if (!USE_CS) {
while (SSP0SR & SSPSR_BSY)
;
switch (device) {
case BMA180_INTERN:
case SMB380_ACC: {
FIO1SET = SSP0_SEL;
break;
}
case BMA180_EXTERN:
case L3G_EXTERN:
case NANOPAN: {
FIO0SET = SSP0_SELN;
break;
}
case ACAMDMS:
case NORDIC:
2013-09-19 16:53:35 +02:00
// Chip Select is done in Nordic driver
2013-08-19 16:17:58 +02:00
break;
default:
ret = 0;
goto ret;
}
}
ret:
return ret;
}
unsigned short SSP0_read(uint8_t device)
{
uint16_t data;
while (!(SSP0SR & SSPSR_RNE))
;
if (!USE_CS) {
switch (device) {
case BMA180_INTERN:
case SMB380_ACC: {
FIO1CLR = SSP0_SEL;
break;
}
case BMA180_EXTERN:
case L3G_EXTERN:
case NANOPAN: {
FIO0CLR = SSP0_SELN;
break;
}
case NORDIC:
case ACAMDMS:
2013-09-19 16:53:35 +02:00
// Chip Select is done in Nordic driver
2013-08-19 16:17:58 +02:00
break;
default:
data = 0xFFFF;
goto ret;
}
}
data = SSP0DR;
if (!USE_CS) {
switch (device) {
case BMA180_INTERN:
case SMB380_ACC: {
FIO1SET = SSP0_SEL;
break;
}
case BMA180_EXTERN:
case L3G_EXTERN:
case NANOPAN: {
FIO0SET = SSP0_SELN;
break;
}
case ACAMDMS:
case NORDIC:
2013-09-19 16:53:35 +02:00
// Chip Select is done in Nordic driver
2013-08-19 16:17:58 +02:00
break;
default:
data = 0xFFFF;
goto ret;
}
}
ret:
return data;
}
unsigned short SMB380_ssp_read(void)
{
return SSP0_read(SMB380_ACC);
}
unsigned short nrf24l01_ssp_read_write(const uint8_t data)
{
SSP0_write(data, NORDIC);
return SSP0_read(NORDIC);
}
unsigned short acam_trx(const uint8_t data)
{
SSP0_write(data, ACAMDMS);
return SSP0_read(ACAMDMS);
}