Skip to content

Commit 2b7e90b

Browse files
committed
feat: added functionality for Wave Generator
1 parent 53f4102 commit 2b7e90b

13 files changed

+1379
-325
lines changed

assets/icons/ic_pwm_pic.png

1.35 KB
Loading

lib/communication/science_lab.dart

Lines changed: 277 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ class ScienceLab {
157157
for (String temp in ['CH1', 'CH2']) {
158158
await setGain(temp, 0, true);
159159
}
160-
for (String temp in ['SI1', 'SI1']) {
160+
for (String temp in ['SI1', 'SI2']) {
161161
await loadEquation(temp, 'sine');
162162
}
163163
}
@@ -1090,6 +1090,282 @@ class ScienceLab {
10901090
}
10911091
}
10921092

1093+
Future<double> setSI1(double frequency, String? waveType) async {
1094+
double freqLowLimit = 0.1;
1095+
int highRes, tableSize;
1096+
1097+
if (frequency < freqLowLimit) {
1098+
logger.e("frequency too low");
1099+
return -1;
1100+
} else if (frequency < 1100) {
1101+
highRes = 1;
1102+
tableSize = 512;
1103+
} else {
1104+
highRes = 0;
1105+
tableSize = 32;
1106+
}
1107+
1108+
if (waveType != null) {
1109+
if (waveType == "sine" || waveType == "tria") {
1110+
if (this.waveType["SI1"] != waveType) {
1111+
loadEquation("SI1", waveType);
1112+
}
1113+
} else {
1114+
logger.e("Not a valid waveform. try sine or tria");
1115+
}
1116+
}
1117+
1118+
List<int> p = [1, 8, 64, 256];
1119+
int prescalar = 0;
1120+
int wavelength = 0;
1121+
1122+
while (prescalar <= 3) {
1123+
wavelength = (64e6 ~/ frequency ~/ p[prescalar] ~/ tableSize);
1124+
frequency = 64e6 / wavelength / p[prescalar] / tableSize;
1125+
if (wavelength < 65525) break;
1126+
prescalar++;
1127+
}
1128+
1129+
if (prescalar == 4) {
1130+
logger.e("Out of range");
1131+
return -1;
1132+
}
1133+
1134+
try {
1135+
mPacketHandler.sendByte(mCommandsProto.wavegen);
1136+
mPacketHandler.sendByte(mCommandsProto.setSine1);
1137+
mPacketHandler.sendByte(highRes | (prescalar << 1));
1138+
mPacketHandler.sendInt(wavelength - 1);
1139+
await mPacketHandler.getAcknowledgement();
1140+
1141+
sin1Frequency = frequency;
1142+
return sin1Frequency;
1143+
} catch (e) {
1144+
logger.e("Error setting SI1: $e");
1145+
}
1146+
1147+
return -1;
1148+
}
1149+
1150+
Future<double> setSI2(double frequency, String? waveType) async {
1151+
double freqLowLimit = 0.1;
1152+
int highRes, tableSize;
1153+
1154+
if (frequency < freqLowLimit) {
1155+
logger.e("frequency too low");
1156+
return -1;
1157+
} else if (frequency < 1100) {
1158+
highRes = 1;
1159+
tableSize = 512;
1160+
} else {
1161+
highRes = 0;
1162+
tableSize = 32;
1163+
}
1164+
1165+
if (waveType != null) {
1166+
if (waveType == "sine" || waveType == "tria") {
1167+
if (this.waveType["SI2"] != waveType) {
1168+
loadEquation("SI2", waveType);
1169+
}
1170+
} else {
1171+
logger.e("Not a valid waveform. try sine or tria");
1172+
}
1173+
}
1174+
1175+
List<int> p = [1, 8, 64, 256];
1176+
int prescalar = 0;
1177+
int wavelength = 0;
1178+
1179+
while (prescalar <= 3) {
1180+
wavelength = (64e6 ~/ frequency ~/ p[prescalar] ~/ tableSize);
1181+
frequency = 64e6 / wavelength / p[prescalar] / tableSize;
1182+
if (wavelength < 65525) break;
1183+
prescalar++;
1184+
}
1185+
1186+
if (prescalar == 4) {
1187+
logger.e("Out of range");
1188+
return -1;
1189+
}
1190+
1191+
try {
1192+
mPacketHandler.sendByte(mCommandsProto.wavegen);
1193+
mPacketHandler.sendByte(mCommandsProto.setSine2);
1194+
mPacketHandler.sendByte(highRes | (prescalar << 1));
1195+
mPacketHandler.sendInt(wavelength - 1);
1196+
await mPacketHandler.getAcknowledgement();
1197+
1198+
sin2Frequency = frequency;
1199+
return sin2Frequency;
1200+
} catch (e) {
1201+
logger.e("Error setting SI2: $e");
1202+
}
1203+
1204+
return -1;
1205+
}
1206+
1207+
Future<double> setWaves(
1208+
double frequency, double phase, double frequency2) async {
1209+
int highRes, tableSize, highRes2, tableSize2;
1210+
int wavelength = 0, wavelength2 = 0;
1211+
1212+
if (frequency2 == -1) frequency2 = frequency;
1213+
1214+
if (frequency < 0.1) {
1215+
logger.e("frequency 1 too low");
1216+
return -1;
1217+
} else if (frequency < 1100) {
1218+
highRes = 1;
1219+
tableSize = 512;
1220+
} else {
1221+
highRes = 0;
1222+
tableSize = 32;
1223+
}
1224+
1225+
if (frequency2 < 0.1) {
1226+
logger.e("frequency 2 too low");
1227+
return -1;
1228+
} else if (frequency2 < 1100) {
1229+
highRes2 = 1;
1230+
tableSize2 = 512;
1231+
} else {
1232+
highRes2 = 0;
1233+
tableSize2 = 32;
1234+
}
1235+
1236+
if (frequency < 1 || frequency2 < 1) {
1237+
logger.e(
1238+
"extremely low frequencies will have reduced amplitudes due to AC coupling restrictions");
1239+
}
1240+
1241+
List<int> p = [1, 8, 64, 256];
1242+
1243+
int prescalar = 0;
1244+
double retFrequency = 0;
1245+
while (prescalar <= 3) {
1246+
wavelength = (64e6 ~/ frequency ~/ p[prescalar] ~/ tableSize);
1247+
retFrequency = 64e6 / wavelength / p[prescalar] / tableSize;
1248+
if (wavelength < 65525) break;
1249+
prescalar++;
1250+
}
1251+
if (prescalar == 4) {
1252+
logger.e("#1 out of range");
1253+
return -1;
1254+
}
1255+
1256+
int prescalar2 = 0;
1257+
double retFrequency2 = 0;
1258+
while (prescalar2 <= 3) {
1259+
wavelength2 = (64e6 ~/ frequency2 ~/ p[prescalar2] ~/ tableSize2);
1260+
retFrequency2 = 64e6 / wavelength2 / p[prescalar2] / tableSize2;
1261+
if (wavelength2 < 65525) break;
1262+
prescalar2++;
1263+
}
1264+
if (prescalar2 == 4) {
1265+
logger.e("#2 out of range");
1266+
return -1;
1267+
}
1268+
1269+
int phaseCoarse = (tableSize2 * (phase) / 360).toInt();
1270+
int phaseFine = (wavelength2 *
1271+
(phase - (phaseCoarse) * 360 / tableSize2) /
1272+
(360 / tableSize2))
1273+
.toInt();
1274+
1275+
try {
1276+
mPacketHandler.sendByte(mCommandsProto.wavegen);
1277+
mPacketHandler.sendByte(mCommandsProto.setBothWg);
1278+
mPacketHandler.sendInt(wavelength - 1);
1279+
mPacketHandler.sendInt(wavelength2 - 1);
1280+
mPacketHandler.sendInt(phaseCoarse);
1281+
mPacketHandler.sendInt(phaseFine);
1282+
mPacketHandler.sendByte(
1283+
(prescalar2 << 4) | (prescalar << 2) | (highRes2 << 1) | (highRes));
1284+
await mPacketHandler.getAcknowledgement();
1285+
1286+
sin1Frequency = retFrequency;
1287+
sin2Frequency = retFrequency2;
1288+
return retFrequency;
1289+
} catch (e) {
1290+
logger.e("Error setting waves: $e");
1291+
}
1292+
1293+
return -1;
1294+
}
1295+
1296+
Future<double> sqrPWM(
1297+
double frequency,
1298+
double h0,
1299+
double p1,
1300+
double h1,
1301+
double p2,
1302+
double h2,
1303+
double p3,
1304+
double h3,
1305+
bool pulse,
1306+
) async {
1307+
if (frequency == 0) return -1;
1308+
1309+
if (h0 == 0) h0 = 0.1;
1310+
if (h1 == 0) h1 = 0.1;
1311+
if (h2 == 0) h2 = 0.1;
1312+
if (h3 == 0) h3 = 0.1;
1313+
1314+
if (frequency > 10e6) {
1315+
logger.e(
1316+
"Frequency is greater than 10MHz. Please use map_reference_clock for 16 & 32MHz outputs",
1317+
);
1318+
return -1;
1319+
}
1320+
1321+
List<int> p = [1, 8, 64, 256];
1322+
int prescalar = 0;
1323+
int wavelength = 0;
1324+
1325+
while (prescalar <= 3) {
1326+
wavelength = (64e6 ~/ frequency ~/ p[prescalar]);
1327+
if (wavelength < 65525) break;
1328+
prescalar++;
1329+
}
1330+
1331+
if (prescalar == 4 || wavelength == 0) {
1332+
logger.e("Out of Range");
1333+
return -1;
1334+
}
1335+
1336+
if (!pulse) prescalar |= (1 << 5);
1337+
1338+
int a1 = ((p1 % 1) * wavelength).toInt();
1339+
int b1 = (((h1 + p1) % 1) * wavelength).toInt();
1340+
int a2 = ((p2 % 1) * wavelength).toInt();
1341+
int b2 = (((h2 + p2) % 1) * wavelength).toInt();
1342+
int a3 = ((p3 % 1) * wavelength).toInt();
1343+
int b3 = (((h3 + p3) % 1) * wavelength).toInt();
1344+
1345+
try {
1346+
mPacketHandler.sendByte(mCommandsProto.wavegen);
1347+
mPacketHandler.sendByte(mCommandsProto.sqr4);
1348+
mPacketHandler.sendInt(wavelength - 1);
1349+
mPacketHandler.sendInt((wavelength * h0).toInt() - 1);
1350+
mPacketHandler.sendInt(a1 > 0 ? a1 - 1 : 0);
1351+
mPacketHandler.sendInt(b1 > 1 ? b1 - 1 : 1);
1352+
mPacketHandler.sendInt(a2 > 0 ? a2 - 1 : 0);
1353+
mPacketHandler.sendInt(b2 > 1 ? b2 - 1 : 1);
1354+
mPacketHandler.sendInt(a3 > 0 ? a3 - 1 : 0);
1355+
mPacketHandler.sendInt(b3 > 1 ? b3 - 1 : 1);
1356+
mPacketHandler.sendByte(prescalar);
1357+
await mPacketHandler.getAcknowledgement();
1358+
} catch (e) {
1359+
logger.e("Error sending data: $e");
1360+
}
1361+
1362+
for (var channel in ["SQR1", "SQR2", "SQR3", "SQR4"]) {
1363+
squareWaveFrequency[channel] = 64e6 / wavelength / p[prescalar & 0x3];
1364+
}
1365+
1366+
return (64e6 / wavelength / p[prescalar & 0x3]);
1367+
}
1368+
10931369
Future<void> servo4(
10941370
double? angle1,
10951371
double? angle2,

lib/l10n/app_en.arb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,13 @@
111111
"phase": "Phase",
112112
"duty": "Duty",
113113
"produceSound": "Produce Sound",
114+
"frequency": "Frequency",
115+
"phaseOffset": "Phase Offset",
116+
"unitDeg": "°",
117+
"unitPercentage": "%",
118+
"sine": "Sine",
119+
"tri": "Tri",
120+
"pwm": "pwm",
114121
"analyze": "Analyze",
115122
"settings": "Settings",
116123
"autoStart": "Auto Start",

lib/l10n/app_localizations.dart

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -760,6 +760,48 @@ abstract class AppLocalizations {
760760
/// **'Produce Sound'**
761761
String get produceSound;
762762

763+
/// No description provided for @frequency.
764+
///
765+
/// In en, this message translates to:
766+
/// **'Frequency'**
767+
String get frequency;
768+
769+
/// No description provided for @phaseOffset.
770+
///
771+
/// In en, this message translates to:
772+
/// **'Phase Offset'**
773+
String get phaseOffset;
774+
775+
/// No description provided for @unitDeg.
776+
///
777+
/// In en, this message translates to:
778+
/// **'°'**
779+
String get unitDeg;
780+
781+
/// No description provided for @unitPercentage.
782+
///
783+
/// In en, this message translates to:
784+
/// **'%'**
785+
String get unitPercentage;
786+
787+
/// No description provided for @sine.
788+
///
789+
/// In en, this message translates to:
790+
/// **'Sine'**
791+
String get sine;
792+
793+
/// No description provided for @tri.
794+
///
795+
/// In en, this message translates to:
796+
/// **'Tri'**
797+
String get tri;
798+
799+
/// No description provided for @pwm.
800+
///
801+
/// In en, this message translates to:
802+
/// **'pwm'**
803+
String get pwm;
804+
763805
/// No description provided for @analyze.
764806
///
765807
/// In en, this message translates to:

lib/l10n/app_localizations_en.dart

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,27 @@ class AppLocalizationsEn extends AppLocalizations {
352352
@override
353353
String get produceSound => 'Produce Sound';
354354

355+
@override
356+
String get frequency => 'Frequency';
357+
358+
@override
359+
String get phaseOffset => 'Phase Offset';
360+
361+
@override
362+
String get unitDeg => '°';
363+
364+
@override
365+
String get unitPercentage => '%';
366+
367+
@override
368+
String get sine => 'Sine';
369+
370+
@override
371+
String get tri => 'Tri';
372+
373+
@override
374+
String get pwm => 'pwm';
375+
355376
@override
356377
String get analyze => 'Analyze';
357378

@@ -1058,6 +1079,7 @@ class AppLocalizationsEn extends AppLocalizations {
10581079
String get temperatureSensorUnavailableMessage =>
10591080
'Ambient temperature sensor is not available on this device';
10601081

1082+
@override
10611083
String get sharingMessage => 'Sharing PSLab Data';
10621084

10631085
@override

0 commit comments

Comments
 (0)