Commit 55485da4 authored by claes's avatar claes

IO support for Gertboard

parent 57d40ffb
//=============================================================================
//
//
// Gertboard Common code
//
// This file is part of the gertboard test suite
//
//
// Copyright (C) Gert Jan van Loo & Myra VanInwegen 2012
// No rights reserved
// You may treat this program as if it was in the public domain
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//
// Notes:
// 1/ In some Linux systems (e.g. Debian) the UART is used by Linux.
// So for now do not demo the UART.
// 2/ At the moment (16-March-2012) there is no Linux driver for
// the audio yet so the PWM is free.
// This is likely to change and in that case the Linux
// audio/PWM driver must be disabled.
//
// This file contains code use by all the test programs for individual
// capabilities.
#include "rt_io_gb_common.h"
#define BCM2708_PERI_BASE 0x20000000
#define CLOCK_BASE (BCM2708_PERI_BASE + 0x101000) /* Clocks */
#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO */
#define PWM_BASE (BCM2708_PERI_BASE + 0x20C000) /* PWM */
#define SPI0_BASE (BCM2708_PERI_BASE + 0x204000) /* SPI0 controller */
#define UART0_BASE (BCM2708_PERI_BASE + 0x201000) /* Uart 0 */
#define UART1_BASE (BCM2708_PERI_BASE + 0x215000) /* Uart 1 (not used) */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <fcntl.h>
#include <assert.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#define PAGE_SIZE (4*1024)
#define BLOCK_SIZE (4*1024)
int mem_fd;
char *clk_mem_orig, *clk_mem, *clk_map;
char *gpio_mem_orig, *gpio_mem, *gpio_map;
char *pwm_mem_orig, *pwm_mem, *pwm_map;
char *spi0_mem_orig, *spi0_mem, *spi0_map;
char *uart_mem_orig, *uart_mem, *uart_map;
// I/O access
volatile unsigned *gpio;
volatile unsigned *pwm;
volatile unsigned *clk;
volatile unsigned *spi0;
volatile unsigned *uart;
//
// GPIO
//
// GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) or SET_GPIO_ALT(x,y)
#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
#define OUT_GPIO(g) *(gpio+((g)/10)) |= (1<<(((g)%10)*3))
#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))
#define GPIO_SET0 *(gpio+7) // Set GPIO high bits 0-31
#define GPIO_SET1 *(gpio+8) // Set GPIO high bits 32-53
#define GPIO_CLR0 *(gpio+10) // Set GPIO low bits 0-31
#define GPIO_CLR1 *(gpio+11) // Set GPIO low bits 32-53
#define GPIO_PULL *(gpio+37) // Pull up/pull down
#define GPIO_PULLCLK0 *(gpio+38) // Pull up/pull down clock
//
// UART 0
//
#define UART0_BAUD_HI *(uart+9)
#define UART0_BAUD_LO *(uart+10)
void setup_io();
void restore_io();
//
// This is a software loop to wait
// a short while.
//
void short_wait()
{ int w;
for (w=0; w<100; w++)
{ w++;
w--;
}
} // short_wait
//
// Simple SW wait loop
//
void long_wait(int v)
{ int w;
while (v--)
for (w=-800000; w<800000; w++)
{ w++;
w--;
}
} // long_wait
//
// Set up memory regions to access the peripherals.
// This is a bit of 'magic' which you should not touch.
// It it also the part of the code which makes that
// you have to use 'sudo' to run this program.
//
void setup_io()
{ unsigned long extra;
/* open /dev/mem */
if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) {
printf("Can't open /dev/mem\n");
printf("Did you forgot to use 'sudo .. ?'\n");
exit (-1);
}
/*
* mmap clock
*/
if ((clk_mem_orig = malloc(BLOCK_SIZE + (PAGE_SIZE-1))) == NULL) {
printf("allocation error \n");
exit (-1);
}
extra = (unsigned long)clk_mem_orig % PAGE_SIZE;
if (extra)
clk_mem = clk_mem_orig + PAGE_SIZE - extra;
else
clk_mem = clk_mem_orig;
clk_map = (unsigned char *)mmap(
(caddr_t)clk_mem,
BLOCK_SIZE,
PROT_READ|PROT_WRITE,
MAP_SHARED|MAP_FIXED,
mem_fd,
CLOCK_BASE
);
if ((long)clk_map < 0) {
printf("clk mmap error %d\n", (int)clk_map);
exit (-1);
}
clk = (volatile unsigned *)clk_map;
/*
* mmap GPIO
*/
if ((gpio_mem_orig = malloc(BLOCK_SIZE + (PAGE_SIZE-1))) == NULL) {
printf("allocation error \n");
exit (-1);
}
extra = (unsigned long)gpio_mem_orig % PAGE_SIZE;
if (extra)
gpio_mem = gpio_mem_orig + PAGE_SIZE - extra;
else
gpio_mem = gpio_mem_orig;
gpio_map = (unsigned char *)mmap(
(caddr_t)gpio_mem,
BLOCK_SIZE,
PROT_READ|PROT_WRITE,
MAP_SHARED|MAP_FIXED,
mem_fd,
GPIO_BASE
);
if ((long)gpio_map < 0) {
printf("gpio mmap error %d\n", (int)gpio_map);
exit (-1);
}
gpio = (volatile unsigned *)gpio_map;
/*
* mmap PWM
*/
if ((pwm_mem_orig = malloc(BLOCK_SIZE + (PAGE_SIZE-1))) == NULL) {
printf("allocation error \n");
exit (-1);
}
extra = (unsigned long)pwm_mem_orig % PAGE_SIZE;
if (extra)
pwm_mem = pwm_mem_orig + PAGE_SIZE - extra;
else
pwm_mem = pwm_mem_orig;
pwm_map = (unsigned char *)mmap(
(caddr_t)pwm_mem,
BLOCK_SIZE,
PROT_READ|PROT_WRITE,
MAP_SHARED|MAP_FIXED,
mem_fd,
PWM_BASE
);
if ((long)pwm_map < 0) {
printf("pwm mmap error %d\n", (int)pwm_map);
exit (-1);
}
pwm = (volatile unsigned *)pwm_map;
/*
* mmap SPI0
*/
if ((spi0_mem_orig = malloc(BLOCK_SIZE + (PAGE_SIZE-1))) == NULL) {
printf("allocation error \n");
exit (-1);
}
extra = (unsigned long)spi0_mem_orig % PAGE_SIZE;
if (extra)
spi0_mem = spi0_mem_orig + PAGE_SIZE - extra;
else
spi0_mem = spi0_mem_orig;
spi0_map = (unsigned char *)mmap(
(caddr_t)spi0_mem,
BLOCK_SIZE,
PROT_READ|PROT_WRITE,
MAP_SHARED|MAP_FIXED,
mem_fd,
SPI0_BASE
);
if ((long)spi0_map < 0) {
printf("spi0 mmap error %d\n", (int)spi0_map);
exit (-1);
}
spi0 = (volatile unsigned *)spi0_map;
/*
* mmap UART
*/
if ((uart_mem_orig = malloc(BLOCK_SIZE + (PAGE_SIZE-1))) == NULL) {
printf("allocation error \n");
exit (-1);
}
extra = (unsigned long)uart_mem_orig % PAGE_SIZE;
if (extra)
uart_mem = uart_mem_orig + PAGE_SIZE - extra;
else
uart_mem = uart_mem_orig;
uart_map = (unsigned char *)mmap(
(caddr_t)uart_mem,
BLOCK_SIZE,
PROT_READ|PROT_WRITE,
MAP_SHARED|MAP_FIXED,
mem_fd,
UART0_BASE
);
if ((long)uart_map < 0) {
printf("uart mmap error %d\n", (int)uart_map);
exit (-1);
}
uart = (volatile unsigned *)uart_map;
} // setup_io
//
// Undo what we did above
//
void restore_io()
{
munmap(uart_map,BLOCK_SIZE);
munmap(spi0_map,BLOCK_SIZE);
munmap(pwm_map,BLOCK_SIZE);
munmap(gpio_map,BLOCK_SIZE);
munmap(clk_map,BLOCK_SIZE);
// free memory
free(uart_mem_orig);
free(spi0_mem_orig);
free(pwm_mem_orig);
free(gpio_mem_orig);
free(clk_mem_orig);
} // restore_io
// simple routine to convert the last several bits of an integer to a string
// showing its binary value
// nbits is the number of bits in i to look at
// i is integer we want to show as a binary number
// we only look at the nbits least significant bits of i and we assume that
// s is at least nbits+1 characters long
void make_binary_string(int nbits, int i, char *s)
{ char *p;
int bit;
p = s;
for (bit = 1 << (nbits-1); bit > 0; bit = bit >> 1, p++)
*p = (i & bit) ? '1' : '0';
*p = '\0';
}
//
// Gertboard test suite
//
// main header file
//
// Copyright (C) Gert Jan van Loo & Myra VanInwegen 2012
// No rights reserved
// You may treat this program as if it was in the public domain
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Try to strike a balance between keep code simple for
// novice programmers but still have reasonable quality code
// (e.g. do not use #ifndef big_demo_h....)
//
#include <stdio.h>
// I/O access
extern volatile unsigned *gpio;
extern volatile unsigned *pwm;
extern volatile unsigned *clk;
extern volatile unsigned *spi0;
extern volatile unsigned *uart;
void short_wait();
void long_wait(int v);
void setup_io();
void restore_io();
void make_binary_string(int, int, char *);
// GPIO setup macros.
// Always use INP_GPIO(x) before using OUT_GPIO(x) or SET_GPIO_ALT(x,y)
#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
#define OUT_GPIO(g) *(gpio+((g)/10)) |= (1<<(((g)%10)*3))
#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))
#define GPIO_SET0 *(gpio+7) // Set GPIO high bits 0-31
#define GPIO_CLR0 *(gpio+10) // Set GPIO low bits 0-31
#define GPIO_IN0 *(gpio+13) // Reads GPIO input bits 0-31
#define GPIO_PULL *(gpio+37) // Pull up/pull down
#define GPIO_PULLCLK0 *(gpio+38) // Pull up/pull down clock
//
// UART 0
//
#define UART0_BAUD_HI *(uart+9)
#define UART0_BAUD_LO *(uart+10)
//
// Gertboard test
//
// SPI (ADC/DAC) control code
//
// This code is part of the Gertboard test suite
// These routines access the AD and DA chips
//
//
// Copyright (C) Gert Jan van Loo & Myra VanInwegen 2012
// No rights reserved
// You may treat this program as if it was in the public domain
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//
// Try to strike a balance between keep code simple for
// novice programmers but still have reasonable quality code
//
#include "rt_io_gb_common.h"
#include "rt_io_gb_spi.h"
//
// Set-up the SPI interface
//
// Speed depends on what you talk to
// In this case use 1MHz
//
void setup_spi()
{
// Want to have 1 MHz SPI clock.
// Assume 250 Mhz system clock
// So divide 250MHz system clock by 250 to get 1MHz45
SPI0_CLKSPEED = 250;
// clear FIFOs and all status bits
SPI0_CNTLSTAT = SPI0_CS_CLRALL;
SPI0_CNTLSTAT = SPI0_CS_DONE; // make sure done bit is cleared
} // setup_spi()
//
// Read a value from one of the two ADC channels
//
// To understand this code you had better read the
// datasheet of the AD chip (MCP3002)
//
int read_adc(int chan) // 'chan' must be 0 or 1. This is not checked!
{ unsigned char v1,v2,rec_c;
int status,w;
// Set up for single ended, MS comes out first
v1 = 0xD0 | (chan<<5);
// Delay to make sure chip select is high for a short while
short_wait();
// Enable SPI interface: Use CS 0 and set activate bit
SPI0_CNTLSTAT = SPI0_CS_CHIPSEL0|SPI0_CS_ACTIVATE;
// Write the command into the FIFO so it will
// be transmitted out of the SPI interface to the ADC
// We need a 16-bit transfer so we send a command byte
// folowed by a dummy byte
SPI0_FIFO = v1;
SPI0_FIFO = 0; // dummy
// wait for SPI to be ready
// This will take about 16 micro seconds
do {
status = SPI0_CNTLSTAT;
} while ((status & SPI0_CS_DONE)==0);
SPI0_CNTLSTAT = SPI0_CS_DONE; // clear the done bit
// Data from the ADC chip should now be in the receiver
// read the received data
v1 = SPI0_FIFO;
v2 = SPI0_FIFO;
// Combine the 8-bit and 2 bit values into an 10-bit integer
// NOT!!! return ((v1<<8)|v2)&0x3FF;
// I have checked the result and it returns 3 bits in the MS byte not 2!!
// So I might have my SPI clock/data pahse wrong.
// For now its easier to dadpt the results (running out of time)
return ( (v1<<7) | (v2>>1) ) & 0x3FF;
} // read_adc
//
// Write 12 bit value to DAC channel 0 or 1
//
// To understand this code you had better read the
// datasheet of the AD chip (MCP4802/MCP4812/MCP4822)
//
void write_dac(int chan, // chan must be 0 or 1, this is not checked
int val) // chan must be max 12 bit
{ char v1,v2,dummy;
int status;
val &= 0xFFF; // force value in 12 bits
// Build the first byte: write, channel 0 or 1 bit
// and the 4 most significant data bits
v1 = 0x30 | (chan<<7) | (val>>8);
// Remain the Least Significant 8 data bits
v2 = val & 0xFF;
// Delay to have CS high for a short while
short_wait();
// Enable SPI: Use CS 1 and set activate bit
SPI0_CNTLSTAT = SPI0_CS_CHIPSEL1|SPI0_CS_ACTIVATE;
// send the values
SPI0_FIFO = v1;
SPI0_FIFO = v2;
// wait for SPI to be ready
// This will take about 16 micro seconds
do {
status = SPI0_CNTLSTAT;
} while ((status & SPI0_CS_DONE)==0);
SPI0_CNTLSTAT = SPI0_CS_DONE; // clear the done bit
// For every transmit there is also data coming back
// We MUST read that received data from the FIFO
// even if we do not use it!
dummy = SPI0_FIFO;
dummy = SPI0_FIFO;
} // write_dac
//
// Gertboard test suite
//
// spi header file
//
// Copyright (C) Gert Jan van Loo & Myra VanInwegen 2012
// No rights reserved
// You may treat this program as if it was in the public domain
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// SPI macros and constants. There are lots!
//
#define SPI0_CNTLSTAT *(spi0 + 0)
#define SPI0_FIFO *(spi0 + 1)
#define SPI0_CLKSPEED *(spi0 + 2)
// SPI0_CNTLSTAT register bits
#define SPI0_CS_CS2ACTHIGH 0x00800000 // CS2 active high
#define SPI0_CS_CS1ACTHIGH 0x00400000 // CS1 active high
#define SPI0_CS_CS0ACTHIGH 0x00200000 // CS0 active high
#define SPI0_CS_RXFIFOFULL 0x00100000 // Receive FIFO full
#define SPI0_CS_RXFIFO3_4 0x00080000 // Receive FIFO 3/4 full
#define SPI0_CS_TXFIFOSPCE 0x00040000 // Transmit FIFO has space
#define SPI0_CS_RXFIFODATA 0x00020000 // Receive FIFO has data
#define SPI0_CS_DONE 0x00010000 // SPI transfer done. WRT to CLR!
#define SPI0_CS_MOSI_INPUT 0x00001000 // MOSI is input, read from MOSI (BI-dir mode)
#define SPI0_CS_DEASRT_CS 0x00000800 // De-assert CS at end
#define SPI0_CS_RX_IRQ 0x00000400 // Receive irq enable
#define SPI0_CS_DONE_IRQ 0x00000200 // irq when done
#define SPI0_CS_DMA_ENABLE 0x00000100 // Run in DMA mode
#define SPI0_CS_ACTIVATE 0x00000080 // Activate: be high before starting
#define SPI0_CS_CS_POLARIT 0x00000040 // Chip selects active high
#define SPI0_CS_CLRTXFIFO 0x00000020 // Clear TX FIFO (auto clear bit)
#define SPI0_CS_CLRRXFIFO 0x00000010 // Clear RX FIFO (auto clear bit)
#define SPI0_CS_CLRFIFOS 0x00000030 // Clear BOTH FIFOs (auto clear bit)
#define SPI0_CS_CLK_IDLHI 0x00000008 // Clock pin is high when idle
#define SPI0_CS_CLKTRANS 0x00000004 // 0=first clock in middle of data bit
// 1=first clock at begin of data bit
#define SPI0_CS_CHIPSEL0 0x00000000 // Use chip select 0
#define SPI0_CS_CHIPSEL1 0x00000001 // Use chip select 1
#define SPI0_CS_CHIPSEL2 0x00000002 // No chip select (e.g. use GPIO pin)
#define SPI0_CS_CHIPSELN 0x00000003 // No chip select (e.g. use GPIO pin)
#define SPI0_CS_CLRALL (SPI0_CS_CLRFIFOS|SPI0_CS_DONE)
// SPI functions
void setup_spi(void);
int read_adc(int);
void write_dac(int, int);
/*
* Proview Open Source Process Control.
* Copyright (C) 2005-2014 SSAB EMEA AB.
*
* This file is part of Proview.
*
* 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 2 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 Proview. If not, see <http://www.gnu.org/licenses/>
*
* Linking Proview statically or dynamically with other modules is
* making a combined work based on Proview. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* Proview give you permission to, from the build function in the
* Proview Configurator, combine Proview with modules generated by the
* Proview PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of Proview (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
/* rt_io_m_gertboard.c -- I/O methods for class Gertboard. */
#include "pwr.h"
#include "pwr_basecomponentclasses.h"
#include "pwr_otherioclasses.h"
#include "co_time.h"
#include "rt_io_base.h"
#include "rt_io_card_init.h"
#include "rt_io_card_close.h"
#include "rt_io_card_read.h"
#include "rt_io_card_write.h"
#include "rt_io_msg.h"
#include "rt_io_gb_common.h"
#include "rt_io_gb_spi.h"
#define GPIO_CHANNELS 12
#define AD0_CHANNEL 12
#define AD1_CHANNEL 13
#define DA0_CHANNEL 14
#define DA1_CHANNEL 15
typedef struct {
FILE *value_fp[GPIO_CHANNELS];
unsigned int number[GPIO_CHANNELS];
unsigned int mask[GPIO_CHANNELS];
int type[GPIO_CHANNELS];
unsigned int in_mask;
unsigned int out_mask;
int interval_cnt;
int has_read_method;
} io_sLocalGertboard;
static pwr_tStatus IoCardInit( io_tCtx ctx,
io_sAgent *ap,
io_sRack *rp,
io_sCard *cp)
{
int i;
pwr_sClass_Gertboard *op = (pwr_sClass_Gertboard *)cp->op;
io_sLocalGertboard *local;
int spi_init = 0;
local = (io_sLocalGertboard *) calloc( 1, sizeof(io_sLocalGertboard));
cp->Local = local;
setup_io();
if ( (cp->chanlist[AD0_CHANNEL].cop && cp->chanlist[AD0_CHANNEL].sop) ||
(cp->chanlist[AD1_CHANNEL].cop && cp->chanlist[AD1_CHANNEL].sop) ||
(cp->chanlist[DA0_CHANNEL].cop && cp->chanlist[DA0_CHANNEL].sop) ||
(cp->chanlist[DA1_CHANNEL].cop && cp->chanlist[DA1_CHANNEL].sop)) {
// Init SPI
INP_GPIO(7);
SET_GPIO_ALT(7,0);
INP_GPIO(8);
SET_GPIO_ALT(8,0);
INP_GPIO(9);
SET_GPIO_ALT(9,0);
INP_GPIO(10);
SET_GPIO_ALT(10,0);
INP_GPIO(11);
SET_GPIO_ALT(11,0);
setup_spi();
spi_init = 1;
}
for ( i = 0; i < GPIO_CHANNELS; i++) {
if ( cp->chanlist[i].cop && cp->chanlist[i].sop) {
switch( cp->chanlist[i].ChanClass) {
case pwr_cClass_ChanD:
if ( local->number[i] > 32) {
errh_Error("Gertboard channel number error, Buf%d", i+1);
op->Status = IO__INITFAIL;
return IO__INITFAIL;
}
local->type[i] = ((pwr_sClass_ChanD *)cp->chanlist[i].cop)->Type;
local->number[i] = ((pwr_sClass_ChanD *)cp->chanlist[i].cop)->Number;
if ( spi_init && (local->number[i] == 7 || local->number[i] == 8 ||
local->number[i] == 9 || local->number[i] == 10 ||
local->number[i] == 11)) {
errh_Warning("GPIO Buf and SPI overlap, %d", local->number[i]);
break;
}
local->mask[i] = 1 << local->number[i];
if ( local->type[i] == pwr_eDChanTypeEnum_Di) {
local->in_mask |= local->mask[i];
INP_GPIO(local->number[i]);
}
else {
local->out_mask |= local->mask[i];
INP_GPIO(local->number[i]);
OUT_GPIO(local->number[i]);
}
break;
default: ;
}
}
}
if ( local->in_mask) {
GPIO_PULL = 2;
short_wait();
GPIO_PULLCLK0 = local->in_mask;
short_wait();
GPIO_PULL = 0;
GPIO_PULLCLK0 = 0;
}
if ( cp->chanlist[DA0_CHANNEL].cop && cp->chanlist[AD0_CHANNEL].sop) {
io_AiRangeToCoef( &cp->chanlist[AD0_CHANNEL]);
}
if ( cp->chanlist[DA1_CHANNEL].cop && cp->chanlist[AD1_CHANNEL].sop) {
io_AiRangeToCoef( &cp->chanlist[AD1_CHANNEL]);
}
if ( cp->chanlist[DA0_CHANNEL].cop && cp->chanlist[DA0_CHANNEL].sop) {
io_AoRangeToCoef( &cp->chanlist[DA0_CHANNEL]);
}
if ( cp->chanlist[DA1_CHANNEL].cop && cp->chanlist[DA1_CHANNEL].sop) {
io_AoRangeToCoef( &cp->chanlist[DA1_CHANNEL]);
}
errh_Info( "Init of Gertboard '%s'", cp->Name);
op->Status = IO__SUCCESS;
return IO__SUCCESS;
}
static pwr_tStatus IoCardClose( io_tCtx ctx,
io_sAgent *ap,
io_sRack *rp,
io_sCard *cp)
{
io_sLocalGertboard *local = (io_sLocalGertboard *)cp->Local;
pwr_sClass_Gertboard *op = (pwr_sClass_Gertboard *)cp->op;
if ( local->in_mask) {
GPIO_PULL = 0;
short_wait();
GPIO_PULLCLK0 = local->in_mask;
short_wait();
GPIO_PULL = 0;
GPIO_PULLCLK0 = 0;
}
free( cp->Local);
op->Status = 0;
return IO__SUCCESS;
}
static pwr_tStatus IoCardRead( io_tCtx ctx,
io_sAgent *ap,
io_sRack *rp,
io_sCard *cp)
{
io_sLocalGertboard *local = (io_sLocalGertboard *)cp->Local;
int i;
unsigned int value_mask;
int ivalue;
value_mask = GPIO_IN0;
for ( i = 0; i < GPIO_CHANNELS; i++) {
if ( local->mask[i] & local->in_mask && cp->chanlist[i].cop && cp->chanlist[i].vbp) {
if ( value_mask & local->mask[i])
*(pwr_tBoolean *)cp->chanlist[i].vbp = 1;
else
*(pwr_tBoolean *)cp->chanlist[i].vbp = 0;
}
}
for ( i = 0; i < 2; i++) {
if ( cp->chanlist[AD0_CHANNEL+i].cop && cp->chanlist[AD0_CHANNEL+i].sop) {
io_sChannel *chanp = &cp->chanlist[AD0_CHANNEL + i];
pwr_sClass_ChanAi *cop = (pwr_sClass_ChanAi *)chanp->cop;
pwr_sClass_Ai *sop = (pwr_sClass_Ai *)chanp->sop;
float actvalue;
if ( cop->CalculateNewCoef)
// Request to calculate new coefficients
io_AiRangeToCoef( chanp);
ivalue = read_adc(i);
io_ConvertAi( cop, ivalue, &actvalue);
// Filter
if ( sop->FilterType == 1 &&
sop->FilterAttribute[0] > 0 &&
sop->FilterAttribute[0] > ctx->ScanTime) {
actvalue = *(pwr_tFloat32 *)chanp->vbp + ctx->ScanTime / sop->FilterAttribute[0] *
(actvalue - *(pwr_tFloat32 *)chanp->vbp);
}
*(pwr_tFloat32 *)chanp->vbp = actvalue;
sop->SigValue = cop->SigValPolyCoef1 * ivalue + cop->SigValPolyCoef0;
sop->RawValue = ivalue;
}
}
return IO__SUCCESS;
}
static pwr_tStatus IoCardWrite( io_tCtx ctx,
io_sAgent *ap,
io_sRack *rp,
io_sCard *cp)
{
io_sLocalGertboard *local = (io_sLocalGertboard *)cp->Local;
int i;
unsigned int clear_mask = 0;
unsigned int set_mask = 0;
int ivalue;
for ( i = 0; i < GPIO_CHANNELS; i++) {
if ( local->mask[i] & local->out_mask && cp->chanlist[i].cop && cp->chanlist[i].vbp) {
if ( *(pwr_tBoolean *)cp->chanlist[i].vbp)
set_mask |= local->mask[i];
else
clear_mask |= local->mask[i];
}
}
GPIO_CLR0 = clear_mask;
GPIO_SET0 = set_mask;
for ( i = 0; i < 2; i++) {
if ( cp->chanlist[DA0_CHANNEL+i].cop && cp->chanlist[DA0_CHANNEL+i].sop) {
pwr_sClass_ChanAo *cop = (pwr_sClass_ChanAo *)cp->chanlist[DA0_CHANNEL+i].cop;
pwr_sClass_Ao *sop = (pwr_sClass_Ao *)cp->chanlist[DA0_CHANNEL+i].sop;
if ( cop->CalculateNewCoef)
// Request to calculate new coefficients
io_AoRangeToCoef( &cp->chanlist[DA0_CHANNEL+i]);
ivalue = (int)( *(pwr_tFloat32 *)cp->chanlist[DA0_CHANNEL+i].vbp *
cop->OutPolyCoef1 + cop->OutPolyCoef0 + 0.5);
if ( ivalue < 0)
ivalue = 0;
else if (ivalue > 4095)
ivalue = 4095;
sop->RawValue = ivalue;
sop->SigValue = *(pwr_tFloat32 *)cp->chanlist[DA0_CHANNEL+i].vbp * cop->SigValPolyCoef1
+ cop->SigValPolyCoef0;
write_dac( i, ivalue);
}
}
return IO__SUCCESS;
}
/* Every method should be registred here. */
pwr_dExport pwr_BindIoMethods(Gertboard) = {
pwr_BindIoMethod(IoCardInit),
pwr_BindIoMethod(IoCardClose),
pwr_BindIoMethod(IoCardRead),
pwr_BindIoMethod(IoCardWrite),
pwr_NullMethod
};
...@@ -33,4 +33,5 @@ Epl_Module ...@@ -33,4 +33,5 @@ Epl_Module
Epl_CNServer Epl_CNServer
Epl_CNServerModule Epl_CNServerModule
PiFace_Digital PiFace_Digital
Gertboard
#endif #endif
\ No newline at end of file
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment