/*
* EP9302 Digital library
* Copyright (C) 2010 Andrea Milazzo aka Mancausoft
*
* 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 .
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "digital.h"
/* globals */
static unsigned long data_page, syscon_page;
static volatile uint8_t* port[8], *portd[8];
/**
* Set a bit of HW Port.
* \param nport The HW port to set. The value must be betwen 0 and 7.
* \param value The value of bit to set.
* \param pos The position of bit to set.
* \return The value returned is -1 if the param nport is incorrect.
* Otherwise return 0.
*/
int set_port_bit (uint8_t nport, bool value, uint8_t pos)
{
if(nport < 8 && pos < 8)
{
set_bit(value, port[nport], pos);
return 0;
}
return -1;
}
/**
* Get a bit of HW Port.
* \param nport The HW port to get. The value must be betwen 0 and 7.
* \param value The pointer to the return value.
* \param pos The position of bit to get.
* \return The value returned is -1 if the param nport is incorrect.
* Otherwise return 0.
*/
int get_port_bit (uint8_t nport, bool* value, uint8_t pos)
{
if(nport < 8 && pos < 8)
{
get_bit(*port[nport], value, pos);
return 0;
}
return -1;
}
/**
* Set direction bit of HW Port.
* \param nport The HW port to set. The value must be betwen 0 and 7.
* \param value The value of direction bit to set.
* \param pos The position of direction bit to set.
* \return The value returned is -1 if the param nport is incorrect.
* Otherwise return 0.
*/
int set_port_dir_bit (uint8_t nport, bool value, uint8_t pos)
{
if(nport < 8 && pos < 8)
{
set_bit(value, portd[nport], pos);
return 0;
}
return -1;
}
/**
* Get direction bit of HW Port.
* \param nport The HW port to get. The value must be betwen 0 and 7.
* \param value The pointer to the return value.
* \param pos The position of direction bit to get.
* \return The value returned is -1 if the param nport is incorrect.
* Otherwise return 0.
*/
int get_port_dir_bit (uint8_t nport, bool* value, uint8_t pos)
{
if(nport < 8 && pos < 8)
{
get_bit(*portd[nport], value, pos);
return 0;
}
return -1;
}
/**
* Set direction of HW Port.
* \param nport The HW port to set. The value must be betwen 0 and 7.
* \param value The value of direction to set.
* \return The value returned is -1 if the param nport is incorrect.
* Otherwise return 0.
*/
int set_port_dir(uint8_t nport, uint8_t value)
{
if(nport < 8)
{
*portd[nport] = value;
return 0;
}
return -1;
}
/**
* Get direction of HW Port.
* \param nport The HW port to get. The value must be betwen 0 and 7.
* \param value The pointer to the return value.
* \return The value returned is -1 if the param nport is incorrect.
* Otherwise return 0.
*/
int get_port_dir(uint8_t nport, uint8_t* value)
{
if(nport < 8)
{
*value = *portd[nport];
return 0;
}
return -1;
}
/**
* Set value of HW Port.
* \param nport The HW port to set. The value must be betwen 0 and 7.
* \param value The value to set.
* \return The value returned is -1 if the param nport is incorrect.
* Otherwise return 0.
*/
int set_port (uint8_t nport, uint8_t value)
{
if(nport < 8)
{
*port[nport] = value;
return 0;
}
return -1;
}
/**
* Get value of HW Port.
* \param nport The HW port to get. The value must be betwen 0 and 7.
* \param value The pointer to the return value.
* \return The value returned is -1 if the param nport is incorrect.
* Otherwise return 0.
*/
int get_port (uint8_t nport, uint8_t* value)
{
if(nport < 8)
{
*value = *port[nport];
return 0;
}
return -1;
}
/**
* Do intial setting to use HW port.
* \return The /dev/mem file descriptor.
*/
int init_ports()
{
int devmem = open("/dev/mem", O_RDWR|O_SYNC);
assert(devmem != -1);
data_page = (unsigned long)mmap(0, getpagesize(), PROT_READ|PROT_WRITE,
MAP_SHARED, devmem, DATA_PAGE);
assert (&data_page != MAP_FAILED);
syscon_page = (unsigned long)mmap(0, getpagesize(), PROT_READ|PROT_WRITE
, MAP_SHARED, devmem, SYSCON_PAGE);
assert(&syscon_page != MAP_FAILED);
uint32_t* deviceCfg = (uint32_t*) (syscon_page + DEVICECFG);
uint32_t* syscon_unlock = (uint32_t*) (syscon_page + SYSCON_UNLOCK);
*syscon_unlock = UNLOCK_VAL;
// TonG = 1 HonIDE = 1 GonIDE = 1 EonIDE = 1
*deviceCfg |= 0x08000D00;
port[0] = (uint8_t*) (data_page + PADR);
port[1] = (uint8_t*) (data_page + PBDR);
port[2] = (uint8_t*) (data_page + PCDR);
port[3] = (uint8_t*) (data_page + PDDR);
port[4] = (uint8_t*) (data_page + PEDR);
port[5] = (uint8_t*) (data_page + PFDR);
port[6] = (uint8_t*) (data_page + PGDR);
port[7] = (uint8_t*) (data_page + PHDR);
portd[0] = (uint8_t*) (data_page + PADDR);
portd[1] = (uint8_t*) (data_page + PBDDR);
portd[2] = (uint8_t*) (data_page + PCDDR);
portd[3] = (uint8_t*) (data_page + PDDDR);
portd[4] = (uint8_t*) (data_page + PEDDR);
portd[5] = (uint8_t*) (data_page + PFDDR);
portd[6] = (uint8_t*) (data_page + PGDDR);
portd[7] = (uint8_t*) (data_page + PHDDR);
return devmem;
}
/**
* Close /dev/mem.
* \param devmem The /dev/mem file descriptor.
*/
void close_ports(int devmem)
{
close(devmem);
}
inline void set_bit(bool src, volatile uint8_t *dst, uint8_t bit)
{
int value = 1 << bit;
if(src)
*dst |= value;
else
*dst &= ~value;
}
inline void get_bit(volatile uint8_t src, bool *dst, uint8_t bit)
{
int value = 1 << bit;
*dst = (src & value) >> bit;
}