#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>#ifndef __SP4418_FRIENDLY_
#define __SP4418_FRIENDLY_#define uint8 unsigned char
#define bool char
#define true 1
#define false 0
#endif#define uint32 intptr_t#define MAP_SIZE (getpagesize())class S5P4418{
public:static int dev_fd;S5P4418(){openMM();}~S5P4418(){closeMM();}static void openMM(){dev_fd = open("/dev/mem", O_RDWR | O_NONBLOCK);if (dev_fd < 0){printf("open(/dev/mem) failed.");}}static void closeMM(){if(dev_fd){close(dev_fd);dev_fd = 0;}}static intptr_t getMapBase(intptr_t baseAddr){intptr_t base = (intptr_t)mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, S5P4418::dev_fd, baseAddr);return base;}static void deleteMapBase(size_t base);static uint32* Register(size_t mem, uint32 offset);
};int S5P4418::dev_fd = 0;void S5P4418::deleteMapBase(size_t base)
{munmap((intptr_t *)base,(size_t)MAP_SIZE);
}uint32* S5P4418::Register(size_t mem, uint32 offset)
{if (mem == 0)return NULL;return (uint32 *)(mem + offset);
}
#define BaseGPIO 0xC001A000enum{
INPUT = 0, OUTPUT
};enum {PA = 0, PB, PC, PD, PE
};enum {Fun_0 = 0, Fun_1, Fun_2, Fun_3
};enum {PULLDOWN = 0, PULLUP, PULLDEFAULT
};class PORT
{
public:PORT(uint8 PORTx){intptr_t BaseADDR = 0;intptr_t Reg = 0;BaseADDR = BaseGPIO + (0x1000 * (uint32)(PORTx));this->hMem = S5P4418::getMapBase(BaseADDR);Reg = 0;OUT = S5P4418::Register(hMem, Reg+0x0000);OUTENB = S5P4418::Register(this->hMem, Reg+0x0004);DETMODE[0] = S5P4418::Register(this->hMem, Reg+0x0008);DETMODE[1] = S5P4418::Register(this->hMem, Reg+0x000C);INTENB = S5P4418::Register(this->hMem, Reg+0x0010);DET = S5P4418::Register(this->hMem, Reg+0x0014);PAD = S5P4418::Register(this->hMem, Reg+0x0018);ALTFN[0] = S5P4418::Register(this->hMem, Reg+0x0020);ALTFN[1] = S5P4418::Register(this->hMem, Reg+0x0024);DETMODEEX = S5P4418::Register(this->hMem, Reg+0x0028);DETENB = S5P4418::Register(this->hMem, Reg+0x003C);SLEW = S5P4418::Register(this->hMem, Reg+0x0040);SLEWDEF = S5P4418::Register(this->hMem, Reg+0x0044);DRV[0] = S5P4418::Register(this->hMem, Reg+0x0050);DRV[1] = S5P4418::Register(this->hMem, Reg+0x0048);DRVDEF[0] = S5P4418::Register(this->hMem, Reg+0x0054);DRVDEF[1] = S5P4418::Register(this->hMem, Reg+0x004C);PULLSEL = S5P4418::Register(this->hMem, Reg+0x0058);PULLDEF = S5P4418::Register(this->hMem, Reg+0x005C);PULLENB = S5P4418::Register(this->hMem, Reg+0x0060);PULLENBDEF = S5P4418::Register(this->hMem, Reg+0x0064);}~PORT(){if(hMem)S5P4418::deleteMapBase(hMem);}intptr_t hMem;uint32 *OUT;uint32 * OUTENB;uint32 * DETMODE[2];uint32 * INTENB;uint32 * DET;uint32 * PAD;uint32 * ALTFN[2];uint32 * DETMODEEX;uint32 * DETENB;uint32 * SLEW;uint32 * SLEWDEF;uint32 * DRV[2];uint32 * DRVDEF[2];uint32 * PULLSEL;uint32 * PULLDEF;uint32 * PULLENB;uint32 * PULLENBDEF;void SetData(uint32 Data);uint32 GetData();
};void PORT::SetData(uint32 Data)
{*OUT = Data;
}uint32 PORT::GetData()
{return *OUT;
}class GPIO{
public:PORT * Port;uint8 Pin;uint32 Bit;void SetFun(uint8 FUNx);void SetDir(uint8 IO );void SetDrv();void SetPull(uint8 Pull );void SetSlew(bool Slew ) ;bool GetSlew();void SetData(bool Data );bool GetData();void Flip();GPIO(uint8 PORTx ,uint8 PINx){Pin = 0;Bit = 0;Port = new PORT(PORTx );this->Pin = PINx;this->Bit = (0x1 << PINx);*this->Port->SLEWDEF &= ~this->Bit;}~GPIO(){delete Port;}
};void GPIO::SetFun(uint8 FUNx) {switch (Pin) {case 0:case 1:case 2:case 3:case 4:case 5:case 6:case 7:case 8:case 9:case 10:case 11:case 12:case 13:case 14:case 15:*Port->ALTFN[0] &= ~(0x3 << (Pin * 2));*Port->ALTFN[0] |= (uint32)(FUNx << (Pin * 2));break;default:*Port->ALTFN[1] &= ~(0x3 << ((Pin - 16) * 2));*Port->ALTFN[1] |= (uint32)(FUNx << ((Pin - 16) * 2));break;}
}void GPIO::SetDir(uint8 IO ) {switch (IO) {case INPUT:*Port->OUTENB &= ~Bit;break;case OUTPUT:*Port->OUTENB |= Bit;break;}
}void GPIO::SetDrv() {}void GPIO::SetPull(uint8 Pull ) {switch (Pull) {case PULLDOWN:*Port->PULLENB &= ~Bit;*Port->PULLDEF |= Bit;break;case PULLUP:*Port->PULLENB |= Bit;*Port->PULLDEF |= Bit;break;case PULLDEFAULT:*Port->PULLENB &= ~Bit;break;}
}void GPIO::SetSlew(bool Slew ) {*Port->SLEWDEF |= Bit;switch (Slew) {case true:*Port->SLEW &= ~Bit;break;case false:*Port->SLEW |= Bit;break;default:break;}
}bool GPIO::GetSlew() {return ((*Port->SLEWDEF & Bit) == Bit) && ((*Port->SLEW & Bit) == 0);
}void GPIO::SetData(bool Data ) {switch (Data) {case true:*Port->OUT |= Bit;break;case false:*Port->OUT &= ~Bit;break;}
}bool GPIO::GetData(){return (*Port->OUT & Bit) == Bit;
}void GPIO::Flip() {;*Port->OUT ^= Bit;
}
long BaseTIMER = 0xC0017000;
enum{TIMER_0 = 0, TIMER_1, TIMER_2, TIMER_3, TIMER_4
};class TIMER {
public:TIMER(uint8 TIMERx ,bool FunPWM );~TIMER(){if(hMem)S5P4418::deleteMapBase(hMem);if(gpio)delete gpio;}uint8 timerX;uint32 hMem;GPIO *gpio;uint32 * TCFG[2];uint32 * TCON;uint32 * TCNTB;uint32 * TCMPB;uint32 * TCNTO;uint32 * TINT;void Start();void Stop();void SetAutoReload(bool AutoReload);void SetDivider(uint8 Divider);void SetPrescale(uint8 Prescale);void SetDuration(uint32 Duration);void SetCompare(uint32 Compare );uint32 GetCount();uint32 getTest();uint32 getCount(uint8 timerX);
};TIMER::TIMER(uint8 TIMERx ,bool FunPWM ){timerX = TIMERx;gpio = NULL;if(FunPWM)BaseTIMER = 0xC0018000;hMem = S5P4418::getMapBase(BaseTIMER);TCFG[0] = S5P4418::Register(hMem, 0x00);TCFG[1] = S5P4418::Register(hMem, 0x04);TCON = S5P4418::Register(hMem, 0x08);switch (TIMERx){case TIMER_0:case TIMER_1:case TIMER_2:case TIMER_3:TCNTB = S5P4418::Register(hMem, 0x0C + (uint32)(TIMERx * 0x0C));TCMPB = S5P4418::Register(hMem, 0x10 + (uint32)(TIMERx * 0x0C));TCNTO = S5P4418::Register(hMem, 0x14 + (uint32)(TIMERx * 0x0C));break;case TIMER_4:TCNTB = S5P4418::Register(hMem, 0x3C);TCNTO = S5P4418::Register(hMem, 0x40);break;}printf("timerX:%d\n",timerX);printf("offset is:%x\n",0x14 + (uint32)(TIMERx * 0x0C));TINT = S5P4418::Register(hMem, 0x44);if (FunPWM) {switch (TIMERx) {case TIMER_2:gpio = new GPIO(PC, 14);gpio->SetFun(Fun_2);gpio->SetDir(OUTPUT);
*TCON &= ~(0x1 << 13);*TCON |= (0x1 << 14);break;}}
}
uint32 TIMER::getCount(uint8 timerX)
{uint32 * addr = NULL;addr = S5P4418::Register(hMem, 0x14 + (uint32)(timerX * 0x0C));return *addr;
}void TIMER::Start() {switch (timerX) {case 0:*TCON |= 0x1;break;case 1:case 2:case 3:case 4:*TCON |= (0x1 << (timerX * 4 + 4));break;}
}void TIMER::Stop() {switch (timerX) {case 0:*TCON &= ~0x1;break;case 1:case 2:case 3:case 4:*TCON &= ~(0x1 << (timerX * 4 + 4));break;}
}void TIMER::SetAutoReload(bool AutoReload) {if (AutoReload){switch (timerX) {case 0: *TCON |= (0x1 << 3);break;case 1: *TCON |= (0x1 << 11);break;case 2: *TCON |= (0x1 << 15);break;case 3: *TCON |= (0x1 << 19);break;case 4: *TCON |= (0x1 << 22);break;}} else{switch (timerX) {case 0: *TCON &= ~(0x1 << 3);break;case 1: *TCON &= ~(0x1 << 11);break;case 2: *TCON &= ~(0x1 << 15);break;case 3: *TCON &= ~(0x1 << 19);break;case 4: *TCON &= ~(0x1 << 22);break;}}
}void TIMER::SetDivider(uint8 Divider) {*TCFG[1] &= ~(0xF << (timerX * 4));*TCFG[1] |= (uint32(Divider & 0x7) << (timerX * 4));
}void TIMER::SetPrescale(uint8 Prescale) {switch (timerX) {case 0:case 1:*TCFG[0] &= ~0xFF;*TCFG[0] |= uint32(Prescale);break;case 2:case 3:case 4:*TCFG[0] &= ~(0xFF << 8);*TCFG[0] |= uint32(Prescale << 8);break;}
}void TIMER::SetDuration(uint32 Duration) {*TCNTB = Duration;
}void TIMER::SetCompare(uint32 Compare ) {*TCMPB = Compare;
}uint32 TIMER::GetCount() {return *TCNTO;
}uint32 TIMER::getTest()
{return *TCNTO;
}
void Sleep(int ms)
{struct timeval delay;delay.tv_sec = 0;delay.tv_usec = ms * 1000; select(0, NULL, NULL, NULL, &delay);
}int main(int argc, char **argv)
{S5P4418 * s5p4418 = new(S5P4418);
int k = 0;int max = 0;TIMER * PWM2 = new TIMER(TIMER_2, true);PWM2->Stop();printf("TCON Value:%X\n",PWM2->TCON);printf("TCON:%X\n",*PWM2->TCON);PWM2->SetAutoReload(true);PWM2->SetDivider(3);PWM2->SetPrescale(0xFF);PWM2->SetDuration(0xffffff);PWM2->SetCompare(0xfffff);PWM2->Start();printf("6*PWM2->TCON:%X\n",*PWM2->TCON);printf("GetCount:%d\n",PWM2->GetCount());printf("GetCount:%d\n",PWM2->GetCount());PWM2->Stop();delete PWM2;delete s5p4418;return 0;
}