Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F79075124
dma_spi.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sat, Aug 24, 15:17
Size
7 KB
Mime Type
text/x-c
Expires
Mon, Aug 26, 15:17 (2 d)
Engine
blob
Format
Raw Data
Handle
20144529
Attached To
R6619 Oncilla Motordriver Firmware
dma_spi.c
View Options
/*
* dma_spi.c
*
* Copyright (c) Alexandre Tuleu
* EPFL Biorobotics Laboratory (http://biorob.epfl.ch)
* EPFL Ecole Polytechnique Federale de Lausanne (http://www.epfl.ch)
*
* * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* \file dma_sbcp.c
* DMA management for spi communications
* \author Alexandre Tuleu
*/
#include <p33Fxxxx.h>
#include "dma_spi.h"
#include "timer.h"
#include "misc.h"
#include "control_table.h"
#include "sbcp.h"
/*******************************************************************************
*
* Module data variables
*
******************************************************************************/
DMA_SPI_data
dma_spi
;
DMA_SPI_ME_rx_buffer
dma_spi_me_rx_buffer
__attribute__
((
space
(
dma
)));
/*******************************************************************************
*
* Interruption
*
******************************************************************************/
/**
* Interruption when the SPI 1 finished its reading
*/
void
__attribute__
((
__interrupt__
,
no_auto_psv
))
_DMA2Interrupt
(){
dma_spi
.
ME_rx_state
=
DMA_SPI_ME_DATA_READY_TO_BE_PROCESSED
;
SPI_ME_STOP_TRANSFER
;
//clear the interruption flag
IFS1bits
.
DMA2IF
=
0
;
}
/*******************************************************************************
*
* Private functions
*
******************************************************************************/
//Initializes the dma channel for SPI recpetions
void
spi_dma_init
()
{
//Use DMA channel 2 for reading SPI 1
DMA2CONbits
.
CHEN
=
0
;
//disable channel 2, will be enabled when needed.
DMA2CONbits
.
SIZE
=
0
;
//Word transfer enabled
DMA2CONbits
.
DIR
=
0
;
//from device to ram
DMA2CONbits
.
HALF
=
0
;
//inetrrupt when transfer is finished
DMA2CONbits
.
NULLW
=
1
;
//Null write mode enabled for DMA Master RX only
DMA2CONbits
.
AMODE
=
0
b00
;
//Register indirect with post-increment
DMA2CONbits
.
MODE
=
0
b01
;
//One - shot mode, Ping - Pong disabled
DMA2STA
=
__builtin_dmaoffset
(
dma_spi_me_rx_buffer
.
w
);
//no need to set DMA2STB , since no Ping-Pong
DMA2PAD
=
(
volatile
unsigned
int
)
&
SPI1BUF
;
DMA2REQ
=
0x000A
;
DMA2CNT
=
3
;
//transfer 4 word, so 8 bytes so 64 bits
IFS1bits
.
DMA2IF
=
0
;
//clear DMA2 Interrupt flag
IEC1bits
.
DMA2IE
=
1
;
//enable DMA2 Interrupt flag
}
/*******************************************************************************
*
* Public functions
*
******************************************************************************/
/**
* Used to start the reading of SPI device. Reading takes time, so should be
* launched beofre motor control. Evenetually makes this function inline to
* speed up (a little) the process.
*/
void
spi_start_reading
(){
//start the reading of magnetic encoders.
dma_spi
.
ME_rx_state
=
DMA_SPI_ME_WAITING_FOR_DEVICES
;
DMA2CONbits
.
CHEN
=
1
;
//enable the channel, transfer will not start
//until something is written to SPI1BUF
SPI_ME_START_TRANSFER
;
TIMER_2_START
;
//the interruption will start the actual transfer.
}
/**
* Used to process the data that comes from spi bus.
*/
void
spi_main
(){
//check if receivingg is finished
if
(
dma_spi
.
ME_rx_state
==
DMA_SPI_ME_DATA_READY_TO_BE_PROCESSED
)
{
//we assume that the parity is always correct.
/// \todo : check the parity of the data, buts it's rather complicated.
//this status flags are initialized with the magnetic amplitude values
unsigned
char
q1_status
=
(
dma_spi_me_rx_buffer
.
w
[
1
]
&
0xc000
)
>>
9
;
unsigned
char
q2_status
=
(
dma_spi_me_rx_buffer
.
w
[
2
]
&
0x1800
)
>>
6
;
unsigned
char
q3_status
=
(
dma_spi_me_rx_buffer
.
w
[
3
]
&
0x0300
)
>>
3
;
//check if Q1 data is correct
if
(
!
(
dma_spi_me_rx_buffer
.
b
.
Q1_OCF
)
//algorithm was unfinsihed
||
(
dma_spi_me_rx_buffer
.
b
.
Q1_LIN
)
//linearity error
||
(
dma_spi_me_rx_buffer
.
b
.
Q1_COF
)
//filtering error
||
q1_status
==
0x60
)
{
//magnetic amplitude error
q1_status
|=
0x80
;
}
control_table
[
A_MDRV_ME_Q1_POSITION
].
c
[
LOW_BYTE
]
=
dma_spi_me_rx_buffer
.
b
.
Q1_ENC_DATA_LOW
;
//if previous data was invalid, this will erase this statement
control_table
[
A_MDRV_ME_Q1_POSITION
].
c
[
HIGH_BYTE
]
=
dma_spi_me_rx_buffer
.
b
.
Q1_ENC_DATA_HIGH
|
q1_status
;
//check if Q2 data is correct
if
(
!
(
dma_spi_me_rx_buffer
.
b
.
Q2_OCF
)
//algorithm was unfinsihed
||
(
dma_spi_me_rx_buffer
.
b
.
Q2_LIN
)
//linearity error
||
(
dma_spi_me_rx_buffer
.
b
.
Q2_COF
)
//filtering error
||
q2_status
==
0x60
)
{
//magnetic amplitude error
q2_status
|=
0x80
;
}
control_table
[
A_MDRV_ME_Q2_POSITION
].
c
[
LOW_BYTE
]
=
dma_spi_me_rx_buffer
.
b
.
Q2_ENC_DATA_LOW
;
//this statement erase previous status value
control_table
[
A_MDRV_ME_Q2_POSITION
].
c
[
HIGH_BYTE
]
=
dma_spi_me_rx_buffer
.
b
.
Q2_ENC_DATA_HIGH
|
q2_status
;
//check if Q3 data is correct
if
(
!
(
dma_spi_me_rx_buffer
.
b
.
Q3_OCF
)
//algorithm was unfinsihed
||
(
dma_spi_me_rx_buffer
.
b
.
Q3_LIN
)
//linearity error
||
(
dma_spi_me_rx_buffer
.
b
.
Q3_COF
)
//filtering error
||
q3_status
==
0x60
)
{
//magnetic amplitude error
q3_status
|=
0x80
;
}
//the lower byte is cut in half here
control_table
[
A_MDRV_ME_Q3_POSITION
].
c
[
LOW_BYTE
]
=
dma_spi_me_rx_buffer
.
b
.
Q3_ENC_DATA_LOW
+
(
dma_spi_me_rx_buffer
.
b
.
Q3_ENC_DATA_MID
<<
3
);
//if previous data was invalid, this will erase this statement
control_table
[
A_MDRV_ME_Q3_POSITION
].
c
[
HIGH_BYTE
]
=
dma_spi_me_rx_buffer
.
b
.
Q3_ENC_DATA_HIGH
|
q3_status
;
//we getted some new value to send, so we mark it :
sbcp
.
bus_low_latency_flags
|=
SBCP_LL_TX_IS_AVAILABLE
;
//we have readen the data, nothing more to do
dma_spi
.
ME_rx_state
=
DMA_SPI_ME_IDLE
;
}
}
/**
* Used to init SPI communications properly
*/
void
spi_init
(){
//Initialization of the control structures
dma_spi
.
ME_rx_state
=
DMA_SPI_ME_IDLE
;
//clear the magnetic encoders buffer
dma_spi_me_rx_buffer
.
w
[
0
]
=
0x0000
;
//clear the whole word
dma_spi_me_rx_buffer
.
w
[
1
]
=
0x0000
;
//clear the whole word
dma_spi_me_rx_buffer
.
w
[
2
]
=
0x0000
;
//clear the whole word
dma_spi_me_rx_buffer
.
w
[
3
]
=
0x0000
;
//clear the whole word
//initilaization of the SPI modules
//SPI 1 is for magentic encoders :
IEC0bits
.
SPI1IE
=
0
;
//disable interrupt. This is needed because we use DMA
IFS0bits
.
SPI1IF
=
0
;
//clear the interrupt flag.
SPI1CON1bits
.
DISSCK
=
0
;
//Us the clock
SPI1CON1bits
.
DISSDO
=
1
;
//Disable data output. This is not needed by the application, no pin are routed
SPI1CON1bits
.
MODE16
=
1
;
//Transmit word. Rx buffer is in byte, but we don't care because we are transmitting an even number of byte
SPI1CON1bits
.
SMP
=
0
;
//data is sampled at middle of clock time
SPI1CON1bits
.
CKE
=
1
;
//clock cycle start when going from active to idle clock state.
SPI1CON1bits
.
CKP
=
1
;
//clock idle state is at high level
SPI1CON1bits
.
MSTEN
=
1
;
//enable master mode
//Choose a clock frequency of 625 kHz, max accepted by AS5045 is 1Mhz
SPI1CON1bits
.
SPRE
=
0
b111
;
//Select a secondary prescaler of 1:1
SPI1CON1bits
.
PPRE
=
0
b00
;
//select a primary prescaler of 64:1
SPI1CON2bits
.
FRMEN
=
0
;
//No frame support
SPI1STATbits
.
SPIEN
=
1
;
//Enable SPI 1 module
spi_dma_init
();
}
Event Timeline
Log In to Comment