-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPCM3718.cpp
149 lines (127 loc) · 2.88 KB
/
PCM3718.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/*
*
Author: Diogo Guilherme Garcia de Freitas
*
*/
#include <sys/io.h>
#include <iostream>
#include <math.h>
#include "PCM3718.h"
PCM3718::PCM3718()
{
Base = 0x300;
Channel = 0;
LastLowByte = 0x00;
LastHighByte = 0x00;
}
void PCM3718::SetBase(int b)
{
Base = b;
}
void PCM3718::SetChannel(int c)
{
Channel = c;
}
void PCM3718::SetupADConversion()
{
outb(0x00, Base + 0x01); //Set input range
outb((Channel | (Channel << 4)), Base + 0x02); //Set input channel
outb(0x00, Base + 0x08); //Clear SREG
usleep(100000);
}
void PCM3718::ResetChannels()
{
outb(0x00, Base + 0x03); //Initialize low and high bytes as 0x00
outb(0x00, Base + 0x0B);
}
bool PCM3718::GetPermissions()
{
if(ioperm(Base, 16, 1) != 0)
{
return true;
}
else
{
return false;
}
}
int PCM3718::DigitalInputByte()
{
return inb(Base + (Channel*8) + 0x03);
}
int PCM3718::DigitalInputBit(int bit)
{
int byte = inb(Base + 0x03);
int mask = (int) pow(2.0, bit);
int state = 0;
if((byte & mask) == mask) //Checks if bit selected is currently on or off
{
state = 1; //If the bit selected is 1, then the current state is 1 (on). Otherwise, it remains 0 (off)
}
return state;
}
void PCM3718::DigitalOutputByte(int data)
{
outb(data, Base + (Channel*8) + 0x03);
if(Channel == 0) //Updates the value of the correspondent attribute
{
LastLowByte = data;
}
else if(Channel == 1)
{
LastHighByte = data;
}
}
void PCM3718::DigitalOutputBit(int data, int bit)
{
int output = 0;
int mask = (int) pow(2.0, bit);
int state = 0;
if(Channel == 0) //output is a temporary variable that
{
output = LastLowByte;
}
else if(Channel == 1)
{
output = LastHighByte;
}
if((output & mask) == mask) //Checks if bit selected is currently on or off
{
state = 1; //If the bit selected is 1, then the current state is 1 (on). Otherwise, it remains 0 (off)
}
if(state != data) //If the current state is different from the desired one, change it. Otherwise, it remains unchanged
{
output = (output ^ mask); //Will toggle the desired bit
outb(output, Base + (Channel*8) + 0x03);
}
if(Channel == 0) //Updates the value of the correspondent attribute
{
LastLowByte = output;
}
else if(Channel == 1)
{
LastHighByte = output;
}
}
double PCM3718::ConvertToVolts(int data)
{
return (((data*10)/4095)-5); //4095 == 0xFFF which is the max value that can be wrote in the 12 bit converter
}
double PCM3718::ReadAnalogInput()
{
outb(0x00, Base); //Trigger conversion
while(inb(Base + 0x08) & 0x10); //Wait until the INT bit turns on
int low = inb(Base); //Read values of low and high byte
int high = inb(Base + 0x01);
return ConvertToVolts((low >> 4) | (high << 4));
}
ostream& operator<<(ostream& os, PCM3718& card)
{
for(int i = 0 ; i < 2 ; i++) //Loops through all channels
{
card.SetChannel(i);
card.SetupADConversion();
os << "Channel " << i << ": " << card.ReadAnalogInput() << " volts" << endl;
}
return os;
}