epicardium.h 54.6 KB
Newer Older
1001
 *
1002
1003
 * .. versionadded:: 1.4
 *
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
 * **Example**:
 *
 * .. code-block:: cpp
 *
 *    #include "epicardium.h"
 *
 *    // Configure a sensor & enable it
 *    struct bhi160_sensor_config cfg = {0};
 *    cfg.sample_buffer_len = 40;
 *    cfg.sample_rate = 4;   // Hz
 *    cfg.dynamic_range = 2; // g
 *
 *    int sd = epic_bhi160_enable_sensor(BHI160_ACCELEROMETER, &cfg);
 *
 *    // Read sensor data
 *    while (1) {
 *            struct bhi160_data_vector buf[10];
 *
 *            int n = epic_stream_read(sd, buf, sizeof(buf));
 *
 *            for (int i = 0; i < n; i++) {
 *                    printf("X: %6d Y: %6d Z: %6d\n",
 *                           buf[i].x,
 *                           buf[i].y,
 *                           buf[i].z);
 *            }
 *    }
 *
 *    // Disable the sensor
 *    epic_bhi160_disable_sensor(BHI160_ACCELEROMETER);
 */

/**
 * BHI160 Sensor Types
 * -------------------
 */

/**
 * BHI160 virtual sensor type.
 */
enum bhi160_sensor_type {
	/**
	 * Accelerometer
	 *
	 * - Data type: :c:type:`bhi160_data_vector`
	 * - Dynamic range: g's (1x Earth Gravity, ~9.81m*s^-2)
	 */
	BHI160_ACCELEROMETER               = 0,
1052
1053
1054
1055
1056
1057
	/**
	 * Magnetometer
	 *
	 * - Data type: :c:type:`bhi160_data_vector`
	 * - Dynamic range: -1000 to 1000 microtesla
	 */
1058
	BHI160_MAGNETOMETER                = 1,
koalo's avatar
koalo committed
1059
	/** Orientation */
1060
	BHI160_ORIENTATION                 = 2,
koalo's avatar
koalo committed
1061
	/** Gyroscope */
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
	BHI160_GYROSCOPE                   = 3,
	/** Gravity (**Unimplemented**) */
	BHI160_GRAVITY                     = 4,
	/** Linear acceleration (**Unimplemented**) */
	BHI160_LINEAR_ACCELERATION         = 5,
	/** Rotation vector (**Unimplemented**) */
	BHI160_ROTATION_VECTOR             = 6,
	/** Uncalibrated magnetometer (**Unimplemented**) */
	BHI160_UNCALIBRATED_MAGNETOMETER   = 7,
	/** Game rotation vector (whatever that is supposed to be) */
	BHI160_GAME_ROTATION_VECTOR        = 8,
	/** Uncalibrated gyroscrope (**Unimplemented**) */
	BHI160_UNCALIBRATED_GYROSCOPE      = 9,
	/** Geomagnetic rotation vector (**Unimplemented**) */
	BHI160_GEOMAGNETIC_ROTATION_VECTOR = 10,
};

1079
1080
1081
1082
enum bhi160_data_type {
	BHI160_DATA_TYPE_VECTOR
};

1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
/**
 * BHI160 Sensor Data Types
 * ------------------------
 */

/**
 * Vector Data.  The scaling of these values is dependent on the chosen dynamic
 * range.  See the individual sensor's documentation for details.
 */
struct bhi160_data_vector {
1093
1094
	enum bhi160_data_type data_type;

1095
1096
1097
1098
1099
1100
	/** X */
	int16_t x;
	/** Y */
	int16_t y;
	/** Z */
	int16_t z;
koalo's avatar
koalo committed
1101
1102
	/** Status */
	uint8_t status;
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
};

/**
 * BHI160 API
 * ----------
 */

/**
 * Configuration for a BHI160 sensor.
 *
 * This struct is used when enabling a sensor using
 * :c:func:`epic_bhi160_enable_sensor`.
 */
struct bhi160_sensor_config {
	/**
	 * Number of samples Epicardium should keep for this sensor.  Do not set
	 * this number too high as the sample buffer will eat RAM.
	 */
	size_t sample_buffer_len;
	/**
	 * Sample rate for the sensor in Hz.  Maximum data rate is limited
	 * to 200 Hz for all sensors though some might be limited at a lower
	 * rate.
	 */
	uint16_t sample_rate;
	/**
	 * Dynamic range.  Interpretation of this value depends on
	 * the sensor type.  Please refer to the specific sensor in
	 * :c:type:`bhi160_sensor_type` for details.
	 */
	uint16_t dynamic_range;
	/** Always zero. Reserved for future parameters. */
	uint8_t _padding[8];
};

/**
 * Enable a BHI160 virtual sensor.  Calling this funciton will instruct the
 * BHI160 to collect data for this specific virtual sensor.  You can then
 * retrieve the samples using :c:func:`epic_stream_read`.
 *
 * :param bhi160_sensor_type sensor_type: Which sensor to enable.
 * :param bhi160_sensor_config* config: Configuration for this sensor.
 * :returns: A sensor descriptor which can be used with
 *    :c:func:`epic_stream_read` or a negative error value:
 *
 *    - ``-EBUSY``:  The BHI160 driver is currently busy with other tasks and
 *      could not be acquired for enabling a sensor.
1150
1151
 *
 * .. versionadded:: 1.4
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
 */
API(API_BHI160_ENABLE, int epic_bhi160_enable_sensor(
	enum bhi160_sensor_type sensor_type,
	struct bhi160_sensor_config *config
));

/**
 * Disable a BHI160 sensor.
 *
 * :param bhi160_sensor_type sensor_type: Which sensor to disable.
1162
1163
 *
 * .. versionadded:: 1.4
1164
1165
1166
1167
1168
 */
API(API_BHI160_DISABLE, int epic_bhi160_disable_sensor(
	enum bhi160_sensor_type sensor_type
));

1169
1170
/**
 * Disable all BHI160 sensors.
1171
1172
 *
 * .. versionadded:: 1.4
1173
1174
1175
 */
API(API_BHI160_DISABLE_ALL, void epic_bhi160_disable_all_sensors());

1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
/**
 * BHI160 Interrupt Handlers
 * -------------------------
 */

/**
 * **Interrupt Service Routine** for :c:data:`EPIC_INT_BHI160_ACCELEROMETER`
 *
 * :c:func:`epic_isr_bhi160_accelerometer` is called whenever the BHI160
 * accelerometer has new data available.
 */
API_ISR(EPIC_INT_BHI160_ACCELEROMETER, epic_isr_bhi160_accelerometer);

1189
1190
1191
1192
1193
1194
1195
1196
/**
 * **Interrupt Service Routine** for :c:data:`EPIC_INT_BHI160_MAGNETOMETER`
 *
 * :c:func:`epic_isr_bhi160_magnetometer` is called whenever the BHI160
 * magnetometer has new data available.
 */
API_ISR(EPIC_INT_BHI160_MAGNETOMETER, epic_isr_bhi160_magnetometer);

1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
/**
 * **Interrupt Service Routine** for :c:data:`EPIC_INT_BHI160_ORIENTATION`
 *
 * :c:func:`epic_isr_bhi160_orientation` is called whenever the BHI160
 * orientation sensor has new data available.
 */
API_ISR(EPIC_INT_BHI160_ORIENTATION, epic_isr_bhi160_orientation);

/**
 * **Interrupt Service Routine** for :c:data:`EPIC_INT_BHI160_GYROSCOPE`
 *
 * :c:func:`epic_isr_bhi160_orientation` is called whenever the BHI160
 * gyroscrope has new data available.
 */
API_ISR(EPIC_INT_BHI160_GYROSCOPE, epic_isr_bhi160_gyroscope);


Rahix's avatar
Rahix committed
1214
/**
Rahix's avatar
Rahix committed
1215
1216
 * Vibration Motor
 * ===============
Rahix's avatar
Rahix committed
1217
1218
1219
1220
1221
1222
1223
 */

/**
 * Turn vibration motor on or off
 *
 * :param status: 1 to turn on, 0 to turn off.
 */
Gerd's avatar
Gerd committed
1224
1225
API(API_VIBRA_SET, void epic_vibra_set(int status));

1226
1227
1228
1229
1230
1231
1232
/**
 * Turn vibration motor on for a given time
 *
 * :param millis: number of milliseconds to run the vibration motor.
 */
API(API_VIBRA_VIBRATE, void epic_vibra_vibrate(int millis));

Gerd's avatar
Gerd committed
1233
1234
1235
/**
 * Display
 * =======
1236
1237
 * The card10 has an LCD screen that can be accessed from user code.
 *
Rahix's avatar
Rahix committed
1238
1239
1240
1241
1242
1243
1244
1245
 * There are two ways to access the display:
 *
 *  - *immediate mode*, where you ask Epicardium to draw shapes and text for
 *    you.  Most functions in this subsection are related to *immediate mode*.
 *  - *framebuffer mode*, where you provide Epicardium with a memory range where
 *    you already drew graphics whichever way you wanted and Epicardium will
 *    copy them to the display.  To use *framebuffer mode*, use the
 *    :c:func:`epic_disp_framebuffer` function.
Gerd's avatar
Gerd committed
1246
1247
 */

Rahix's avatar
Rahix committed
1248
/** Line-Style */
Rahix's avatar
Rahix committed
1249
enum disp_linestyle {
Rahix's avatar
Rahix committed
1250
  /** */
Gerd's avatar
Gerd committed
1251
  LINESTYLE_FULL = 0,
Rahix's avatar
Rahix committed
1252
  /** */
Gerd's avatar
Gerd committed
1253
1254
1255
  LINESTYLE_DOTTED = 1
};

Rahix's avatar
Rahix committed
1256
/** Fill-Style */
Rahix's avatar
Rahix committed
1257
enum disp_fillstyle {
Rahix's avatar
Rahix committed
1258
  /** */
Gerd's avatar
Gerd committed
1259
  FILLSTYLE_EMPTY = 0,
Rahix's avatar
Rahix committed
1260
  /** */
Gerd's avatar
Gerd committed
1261
1262
1263
  FILLSTYLE_FILLED = 1
};

1264
1265
1266
1267
1268
1269
/** Width of display in pixels */
#define DISP_WIDTH 160

/** Height of display in pixels */
#define DISP_HEIGHT 80

Rahix's avatar
Rahix committed
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
/**
 * Framebuffer
 *
 * The frambuffer stores pixels as RGB565, but byte swapped.  That is, for every ``(x, y)`` coordinate, there are two ``uint8_t``\ s storing 16 bits of pixel data.
 *
 * .. todo::
 *
 *    Document (x, y) in relation to chirality.
 *
 * **Example**: Fill framebuffer with red
 *
 * .. code-block:: cpp
 *
 * 	union disp_framebuffer fb;
 * 	uint16_t red = 0b1111100000000000;
 * 	for (int y = 0; y < DISP_HEIGHT; y++) {
 * 		for (int x = 0; x < DISP_WIDTH; x++) {
 * 			fb.fb[y][x][0] = red >> 8;
 * 			fb.fb[y][x][1] = red & 0xFF;
 * 		}
 * 	}
 * 	epic_disp_framebuffer(&fb);
 */
1293
union disp_framebuffer {
Rahix's avatar
Rahix committed
1294
  /** Coordinate based access (as shown in the example above). */
1295
  uint8_t fb[DISP_HEIGHT][DISP_WIDTH][2];
Rahix's avatar
Rahix committed
1296
  /** Raw byte-indexed access. */
1297
1298
1299
  uint8_t raw[DISP_HEIGHT*DISP_WIDTH*2];
};

Gerd's avatar
Gerd committed
1300
1301
1302
1303
/**
 * Locks the display.
 *
 * :return: ``0`` on success or a negative value in case of an error:
Rahix's avatar
Rahix committed
1304
1305
 *
 *    - ``-EBUSY``: Display was already locked from another task.
Gerd's avatar
Gerd committed
1306
1307
1308
1309
1310
1311
1312
 */
API(API_DISP_OPEN, int epic_disp_open());

/**
 * Unlocks the display again.
 *
 * :return: ``0`` on success or a negative value in case of an error:
Rahix's avatar
Rahix committed
1313
1314
 *
 *    - ``-EBUSY``: Display was already locked from another task.
Gerd's avatar
Gerd committed
1315
1316
1317
1318
1319
1320
 */
API(API_DISP_CLOSE, int epic_disp_close());

/**
 * Causes the changes that have been written to the framebuffer
 * to be shown on the display
1321
1322
1323
 * :return: ``0`` on success or a negative value in case of an error:
 *
 *    - ``-EBUSY``: Display was already locked from another task.
Gerd's avatar
Gerd committed
1324
1325
1326
1327
1328
1329
 */
API(API_DISP_UPDATE, int epic_disp_update());

/**
 * Prints a string into the display framebuffer
 *
1330
1331
 * :param posx: x position to print to.
 * :param posy: y position to print to.
Gerd's avatar
Gerd committed
1332
1333
1334
1335
 * :param pString: string to print
 * :param fg: foreground color in rgb565
 * :param bg: background color in rgb565
 * :return: ``0`` on success or a negative value in case of an error:
Rahix's avatar
Rahix committed
1336
1337
 *
 *    - ``-EBUSY``: Display was already locked from another task.
Gerd's avatar
Gerd committed
1338
1339
1340
 */
API(API_DISP_PRINT,
    int epic_disp_print(
1341
1342
	    int16_t posx,
	    int16_t posy,
Gerd's avatar
Gerd committed
1343
1344
1345
1346
1347
	    const char *pString,
	    uint16_t fg,
	    uint16_t bg)
    );

1348
1349
1350
1351
/*
 * Font Selection
 */
enum disp_font_name {
1352
	DISP_FONT8  = 0,
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
	DISP_FONT12 = 1,
	DISP_FONT16 = 2,
	DISP_FONT20 = 3,
	DISP_FONT24 = 4,
};

/**
 * Prints a string into the display framebuffer with font type selectable
 *
 * :param fontName: number of font, use FontName enum
1363
1364
 * :param posx: x position to print to.
 * :param posy: y position to print to.
1365
1366
 * :param pString: string to print
 * :param fg: foreground color in rgb565
1367
 * :param bg: background color in rgb565, no background is drawn if bg==fg
1368
1369
1370
1371
 * :return: ``0`` on success or a negative value in case of an error:
 *
 *    - ``-EBUSY``: Display was already locked from another task.
 */
1372
1373
API(API_DISP_PRINT_ADV, int epic_disp_print_adv(
	uint8_t font,
1374
1375
	int16_t posx,
	int16_t posy,
1376
1377
1378
1379
	const char *pString,
	uint16_t fg,
	uint16_t bg
));
1380

Gerd's avatar
Gerd committed
1381
1382
1383
1384
1385
/**
 * Fills the whole screen with one color
 *
 * :param color: fill color in rgb565
 * :return: ``0`` on success or a negative value in case of an error:
Rahix's avatar
Rahix committed
1386
1387
 *
 *    - ``-EBUSY``: Display was already locked from another task.
Gerd's avatar
Gerd committed
1388
1389
1390
 */
API(API_DISP_CLEAR, int epic_disp_clear(uint16_t color));

1391
1392
1393
/**
 * Draws a pixel on the display
 *
1394
1395
 * :param x: x position;
 * :param y: y position;
1396
1397
1398
1399
1400
 * :param color: pixel color in rgb565
 * :return: ``0`` on success or a negative value in case of an error:
 *
 *    - ``-EBUSY``: Display was already locked from another task.
 */
1401
API(API_DISP_PIXEL, int epic_disp_pixel(
1402
	int16_t x, int16_t y, uint16_t color
1403
));
1404

Gerd's avatar
Gerd committed
1405
1406
1407
/**
 * Draws a line on the display
 *
1408
1409
1410
1411
 * :param xstart: x starting position
 * :param ystart: y starting position
 * :param xend: x ending position
 * :param yend: y ending position
Gerd's avatar
Gerd committed
1412
1413
1414
1415
 * :param color: line color in rgb565
 * :param linestyle: 0 for solid, 1 for dottet (almost no visual difference)
 * :param pixelsize: thickness of the line; 1 <= pixelsize <= 8
 * :return: ``0`` on success or a negative value in case of an error:
Rahix's avatar
Rahix committed
1416
1417
 *
 *    - ``-EBUSY``: Display was already locked from another task.
Gerd's avatar
Gerd committed
1418
 */
1419
API(API_DISP_LINE, int epic_disp_line(
1420
1421
1422
1423
	int16_t xstart,
	int16_t ystart,
	int16_t xend,
	int16_t yend,
1424
1425
1426
1427
	uint16_t color,
	enum disp_linestyle linestyle,
	uint16_t pixelsize
));
Gerd's avatar
Gerd committed
1428
1429
1430
1431

/**
 * Draws a rectangle on the display
 *
1432
1433
1434
1435
 * :param xstart: x coordinate of top left corner
 * :param ystart: y coordinate of top left corner
 * :param xend: x coordinate of bottom right corner
 * :param yend: y coordinate of bottom right corner
Gerd's avatar
Gerd committed
1436
1437
1438
1439
 * :param color: line color in rgb565
 * :param fillstyle: 0 for empty, 1 for filled
 * :param pixelsize: thickness of the rectangle outline; 1 <= pixelsize <= 8
 * :return: ``0`` on success or a negative value in case of an error:
Rahix's avatar
Rahix committed
1440
1441
 *
 *    - ``-EBUSY``: Display was already locked from another task.
Gerd's avatar
Gerd committed
1442
 */
1443
API(API_DISP_RECT, int epic_disp_rect(
1444
1445
1446
1447
	int16_t xstart,
	int16_t ystart,
	int16_t xend,
	int16_t yend,
1448
1449
1450
1451
	uint16_t color,
	enum disp_fillstyle fillstyle,
	uint16_t pixelsize
));
Gerd's avatar
Gerd committed
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462

/**
 * Draws a circle on the display
 *
 * :param x: x coordinate of the center; 0 <= x <= 160
 * :param y: y coordinate of the center; 0 <= y <= 80
 * :param rad: radius of the circle
 * :param color: fill and outline color of the circle (rgb565)
 * :param fillstyle: 0 for empty, 1 for filled
 * :param pixelsize: thickness of the circle outline; 1 <= pixelsize <= 8
 * :return: ``0`` on success or a negative value in case of an error:
Rahix's avatar
Rahix committed
1463
1464
 *
 *    - ``-EBUSY``: Display was already locked from another task.
Gerd's avatar
Gerd committed
1465
 */
1466
API(API_DISP_CIRC, int epic_disp_circ(
1467
1468
	int16_t x,
	int16_t y,
1469
1470
1471
1472
1473
	uint16_t rad,
	uint16_t color,
	enum disp_fillstyle fillstyle,
	uint16_t pixelsize
));
1474

1475
1476
1477
1478
1479
1480
1481
1482
1483
/**
 * Immediately send the contents of a framebuffer to the display. This overrides
 * anything drawn by immediate mode graphics and displayed using ``epic_disp_update``.
 *
 * :param fb: framebuffer to display
 * :return: ``0`` on success or negative value in case of an error:
 *
 *    - ``-EBUSY``: Display was already locked from another task.
 */
1484
1485
1486
API(API_DISP_FRAMEBUFFER, int epic_disp_framebuffer(
	union disp_framebuffer *fb
));
1487
1488


1489
/**
1490
 * Set the backlight brightness.
1491
 *
1492
 * Note that this function does not require acquiring the display.
1493
 *
1494
1495
 * :param brightness: brightness from 0 - 100
 * :return: ``0`` on success or negative value in case of an error
1496
1497
1498
1499
 */
API(API_DISP_BACKLIGHT, int epic_disp_backlight(uint16_t brightness));


1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
/**
 * Start continuous readout of the light sensor. Will read light level
 * at preconfigured interval and make it available via `epic_light_sensor_get()`.
 *
 * If the continuous readout was already running, this function will silently pass.
 *
 *
 * :return: `0` if the start was successful or a negative error value
 *      if an error occured. Possible errors:
 *
 *      - ``-EBUSY``: The timer could not be scheduled.
 */
API(API_LIGHT_SENSOR_RUN, int epic_light_sensor_run());

/**
 * Get the last light level measured by the continuous readout.
 *
 * :param uint16_t* value: where the last light level should be written.
 * :return: `0` if the readout was successful or a negative error
 *      value. Possible errors:
 *
 *      - ``-ENODATA``: Continuous readout not currently running.
 */
API(API_LIGHT_SENSOR_GET, int epic_light_sensor_get(uint16_t* value));


/**
 * Stop continuous readout of the light sensor.
 *
 * If the continuous readout wasn't running, this function will silently pass.
 *
 * :return: `0` if the stop was sucessful or a negative error value
 *      if an error occured. Possible errors:
 *
 *      - ``-EBUSY``: The timer stop could not be scheduled.
 */
API(API_LIGHT_SENSOR_STOP, int epic_light_sensor_stop());

1538
/**
Rahix's avatar
Rahix committed
1539
1540
1541
1542
1543
 * Get the light level directly.
 *
 * Each call has an intrinsic delay of about 240us, I recommend another
 * 100-300us delay  between calls. Whether or not the IR LED is fast enough is
 * another issue.
1544
1545
 *
 * :return: Light level
Rahix's avatar
Rahix committed
1546
1547
 *
 * .. versionadded:: 1.8
1548
1549
1550
1551
 */
API(API_LIGHT_SENSOR_READ, uint16_t epic_light_sensor_read(void));


1552
1553
1554
/**
 * File
 * ====
1555
1556
 * Except for :c:func:`epic_file_open`, which models C stdio's ``fopen``
 * function, ``close``, ``read`` and ``write`` model `close(2)`_, `read(2)`_ and
Rahix's avatar
Rahix committed
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
 * `write(2)`_.  All file-related functions return >= ``0`` on success and
 * ``-Exyz`` on failure, with error codes from errno.h (``EIO``, ``EINVAL``
 * etc.)
 *
 * .. _close(2): http://man7.org/linux/man-pages/man2/close.2.html
 * .. _read(2): http://man7.org/linux/man-pages/man2/read.2.html
 * .. _write(2): http://man7.org/linux/man-pages/man2/write.2.html
 */

/** */
1567
1568
1569
API(API_FILE_OPEN, int epic_file_open(
	const char* filename, const char* modeString
));
Rahix's avatar
Rahix committed
1570

1571
/** */
Rahix's avatar
Rahix committed
1572
API(API_FILE_CLOSE, int epic_file_close(int fd));
Rahix's avatar
Rahix committed
1573
1574

/** */
Rahix's avatar
Rahix committed
1575
API(API_FILE_READ, int epic_file_read(int fd, void* buf, size_t nbytes));
Rahix's avatar
Rahix committed
1576

1577
/**
1578
 * Write bytes to a file.
1579
 *
1580
1581
1582
 * :param int fd: Descriptor returned by :c:func:`epic_file_open`.
 * :param void* buf: Data to write.
 * :param size_t nbytes: Number of bytes to write.
1583
1584
1585
1586
 *
 * :return: ``< 0`` on error, ``nbytes`` on success. (Partial writes don't occur on success!)
 *
*/
1587
1588
1589
API(API_FILE_WRITE, int epic_file_write(
	int fd, const void* buf, size_t nbytes
));
Rahix's avatar
Rahix committed
1590
1591

/** */
Rahix's avatar
Rahix committed
1592
API(API_FILE_FLUSH, int epic_file_flush(int fd));
1593

1594
1595
1596
1597
1598
1599
/** */
API(API_FILE_SEEK, int epic_file_seek(int fd, long offset, int whence));

/** */
API(API_FILE_TELL, int epic_file_tell(int fd));

Rahix's avatar
Rahix committed
1600
/** */
1601
enum epic_stat_type {
Rahix's avatar
Rahix committed
1602
1603
1604
1605
1606
1607
	/**
	 * Basically ``ENOENT``. Although :c:func:`epic_file_stat` returns an
	 * error for 'none', the type will still be set to none additionally.
	 *
	 * This is also used internally to track open FS objects, where we use
	 * ``EPICSTAT_NONE`` to mark free objects.
1608
1609
1610
	 */
	EPICSTAT_NONE,
	/** normal file */
Rahix's avatar
Rahix committed
1611
	EPICSTAT_FILE,
1612
	/** directory */
Rahix's avatar
Rahix committed
1613
	EPICSTAT_DIR,
1614
1615
};

1616
1617
1618
1619
1620
/**
 * Maximum length of a path string (=255).
 */
#define EPICSTAT_MAX_PATH        255
/* conveniently the same as FF_MAX_LFN */
1621

Rahix's avatar
Rahix committed
1622
/** */
1623
1624
struct epic_stat {
	/** Entity Type: file, directory or none */
Rahix's avatar
Rahix committed
1625
	enum epic_stat_type type;
Rahix's avatar
Rahix committed
1626
1627
1628
1629
1630
1631
1632
1633
1634

	/*
	 * Note about padding & placement of uint32_t size:
	 *
	 *   To accomodate for future expansion, we want padding at the end of
	 *   this struct. Since sizeof(enum epic_stat_type) can not be assumed
	 *   to be have a certain size, we're placing uint32_t size here so we
	 *   can be sure it will be at offset 4, and therefore the layout of the
	 *   other fields is predictable.
1635
	 */
Rahix's avatar
Rahix committed
1636
1637

	/** Size in bytes. */
1638
	uint32_t size;
Rahix's avatar
Rahix committed
1639

1640
	/** File Name. */
1641
1642
	char name[EPICSTAT_MAX_PATH + 1];
	uint8_t _reserved[12];
1643
};
1644
1645
1646
1647

/**
 * stat path
 *
Rahix's avatar
Rahix committed
1648
 * :param char* filename: path to stat
1649
 * :param epic_stat* stat: pointer to result
1650
 *
Rahix's avatar
Rahix committed
1651
 * :return: ``0`` on success, negative on error
1652
 */
1653
1654
1655
API(API_FILE_STAT, int epic_file_stat(
	const char* path, struct epic_stat* stat
));
1656

1657
/**
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
 * Open a directory, for enumerating its contents.
 *
 * Use :c:func:`epic_file_readdir` to iterate over the directories entries.
 *
 * **Example**:
 *
 * .. code-block:: cpp
 *
 *    #include "epicardium.h"
 *
 *    int fd = epic_file_opendir("/path/to/dir");
 *
 *    struct epic_stat entry;
 *    for (;;) {
 *            epic_file_readdir(fd, &entry);
1673
 *
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
 *            if (entry.type == EPICSTAT_NONE) {
 *                    // End
 *                    break;
 *            }
 *
 *            printf("%s\n", entry.name);
 *    }
 *
 *    epic_file_close(fd);
 *
 * :param char* path: Directory to open.
1685
1686
1687
1688
1689
1690
 *
 * :return: ``> 0`` on success, negative on error
 */
API(API_FILE_OPENDIR, int epic_file_opendir(const char* path));

/**
1691
1692
1693
1694
1695
 * Read one entry from a directory.
 *
 * Call :c:func:`epic_file_readdir` multiple times to iterate over all entries
 * of a directory.  The end of the entry list is marked by returning
 * :c:data:`EPICSTAT_NONE` as the :c:member:`epic_stat.type`.
1696
 *
1697
1698
1699
 * :param int fd: Descriptor returned by :c:func:`epic_file_opendir`.
 * :param epic_stat* stat: Pointer where to store the result.  Pass NULL to
 *    reset iteration offset of ``fd`` back to the beginning.
1700
1701
1702
1703
1704
1705
 *
 * :return: ``0`` on success, negative on error
 */
API(API_FILE_READDIR, int epic_file_readdir(int fd, struct epic_stat* stat));

/**
1706
 * Unlink (remove) a file.
1707
1708
1709
1710
1711
1712
1713
 *
 * :param char* path: file to delete
 *
 * :return: ``0`` on success, negative on error
 */
API(API_FILE_UNLINK, int epic_file_unlink(const char* path));

swym's avatar
swym committed
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
/**
 * Rename a file or directory.
 *
 * :param char* oldp: old name
 * :param char* newp: new name
 *
 * :return: ``0`` on success, negative on error
 */
API(API_FILE_RENAME, int epic_file_rename(const char *oldp, const char* newp));

/**
 * Create directory in CWD
 *
 * :param char* dirname: directory name
 *
 * :return: ``0`` on success, negative on error
 */
API(API_FILE_MKDIR, int epic_file_mkdir(const char *dirname));
1732

1733
1734
1735
1736
1737
/**
 * RTC
 * ===
 */

1738
1739
1740
1741
/**
 * Get the monotonic time in seconds.
 *
 * :return: monotonic time in seconds
Rahix's avatar
Rahix committed
1742
1743
 *
 * .. versionadded:: 1.11
1744
1745
1746
1747
1748
1749
1750
1751
1752
 */
API(API_RTC_GET_MONOTONIC_SECONDS,
	uint32_t epic_rtc_get_monotonic_seconds(void)
);

/**
 * Get the monotonic time in ms.
 *
 * :return: monotonic time in milliseconds
Rahix's avatar
Rahix committed
1753
1754
 *
 * .. versionadded:: 1.11
1755
1756
1757
1758
1759
 */
API(API_RTC_GET_MONOTONIC_MILLISECONDS,
	uint64_t epic_rtc_get_monotonic_milliseconds(void)
);

1760
1761
1762
1763
1764
1765
1766
/**
 * Read the current RTC value.
 *
 * :return: Unix time in seconds
 */
API(API_RTC_GET_SECONDS, uint32_t epic_rtc_get_seconds(void));

1767
/**
Hinerk's avatar
Hinerk committed
1768
 * Read the current RTC value in ms.
1769
1770
1771
1772
1773
 *
 * :return: Unix time in milliseconds
 */
API(API_RTC_GET_MILLISECONDS, uint64_t epic_rtc_get_milliseconds(void));

Hauke Mehrtens's avatar
Hauke Mehrtens committed
1774
1775
1776
/**
 * Sets the current RTC time in milliseconds
 */
1777
1778
1779
API(API_RTC_SET_MILLISECONDS, void epic_rtc_set_milliseconds(
	uint64_t milliseconds
));
Hauke Mehrtens's avatar
Hauke Mehrtens committed
1780

Rahix's avatar
Rahix committed
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
/**
 * Schedule the RTC alarm for the given timestamp.
 *
 * :param uint32_t timestamp: When to schedule the IRQ
 * :return: `0` on success or a negative value if an error occured. Possible
 *    errors:
 *
 *    - ``-EINVAL``: RTC is in a bad state
 */
API(API_RTC_SCHEDULE_ALARM, int epic_rtc_schedule_alarm(uint32_t timestamp));

/**
1793
 * **Interrupt Service Routine** for :c:data:`EPIC_INT_RTC_ALARM`
Rahix's avatar
Rahix committed
1794
1795
1796
1797
1798
1799
 *
 * ``epic_isr_rtc_alarm()`` is called when the RTC alarm triggers.  The RTC alarm
 * can be scheduled using :c:func:`epic_rtc_schedule_alarm`.
 */
API_ISR(EPIC_INT_RTC_ALARM, epic_isr_rtc_alarm);

1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
/**
 * TRNG
 * ====
 */

/**
 * Read random bytes from the TRNG.
 *
 * :param uint8_t * dest: Destination buffer
 * :param size: Number of bytes to read.
 * :return: `0` on success or a negative value if an error occured. Possible
 *    errors:
 *
 *    - ``-EFAULT``: Invalid destination address.
 */
API(API_TRNG_READ, int epic_trng_read(uint8_t *dest, size_t size));

schneider's avatar
schneider committed
1817
/**
Rahix's avatar
Rahix committed
1818
1819
 * MAX30001
 * ========
schneider's avatar
schneider committed
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
 */

/**
 * Configuration for a MAX30001 sensor.
 *
 * This struct is used when enabling the sensor using
 * :c:func:`epic_max30001_enable_sensor`.
 */
struct max30001_sensor_config {
	/**
	 * Number of samples Epicardium should keep for this sensor.  Do not set
	 * this number too high as the sample buffer will eat RAM.
	 */
	size_t sample_buffer_len;
	/**
	 * Sample rate for the sensor in Hz.
	 */
	uint16_t sample_rate;

	/**
	 * Set to true if the second lead comes from USB-C
	 */
	bool usb;

	/**
1845
1846
	 * Set to true if the interal lead bias of the MAX30001 is to be used.
	 */
schneider's avatar
schneider committed
1847
1848
1849
1850
1851
1852
1853
	bool bias;

	/** Always zero. Reserved for future parameters. */
	uint8_t _padding[8];
};

/**
1854
1855
1856
1857
 * Enable a MAX30001 ecg sensor.
 *
 * Calling this funciton will instruct the MAX30001 to collect data for this
 * sensor.  You can then retrieve the samples using :c:func:`epic_stream_read`.
schneider's avatar
schneider committed
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
 *
 * :param max30001_sensor_config* config: Configuration for this sensor.
 * :returns: A sensor descriptor which can be used with
 *    :c:func:`epic_stream_read` or a negative error value:
 *
 *    - ``-EBUSY``:  The MAX30001 driver is currently busy with other tasks and
 *      could not be acquired for enabling a sensor.
 *
 * .. versionadded:: 1.6
 */
API(API_MAX30001_ENABLE, int epic_max30001_enable_sensor(
	struct max30001_sensor_config *config
));

/**
 * Disable MAX30001
 *
 * .. versionadded:: 1.6
 */
1877
API(API_MAX30001_DISABLE, int epic_max30001_disable_sensor());
schneider's avatar
schneider committed
1878

1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
/**
 * **Interrupt Service Routine** for :c:data:`EPIC_INT_MAX30001_ECG`
 *
 * This interrupt handler is called whenever the MAX30001 ECG has new data
 * available.
 */
API_ISR(EPIC_INT_MAX30001_ECG, epic_isr_max30001_ecg);

/**
 * USB
 * ===
 */

swym's avatar
swym committed
1892
1893
1894
1895
1896
/**
 * De-initialize the currently configured USB device (if any)
 *
 */
API(API_USB_SHUTDOWN, int epic_usb_shutdown(void));
1897

swym's avatar
swym committed
1898
1899
/**
 * Configure the USB peripheral to export the internal FLASH
1900
 * as a Mass Storage device.
swym's avatar
swym committed
1901
1902
 */
API(API_USB_STORAGE, int epic_usb_storage(void));
1903

swym's avatar
swym committed
1904
1905
/**
 * Configure the USB peripheral to provide card10's stdin/stdout
1906
 * on a USB CDC-ACM device.
swym's avatar
swym committed
1907
1908
 */
API(API_USB_CDCACM, int epic_usb_cdcacm(void));
schneider's avatar
schneider committed
1909

1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
/**
 * WS2812
 * ======
 */

/**
 * Takes a gpio pin specified with the gpio module and transmits
 * the led data. The format `GG:RR:BB` is expected.
 *
 * :param uint8_t pin: The gpio pin to be used for data.
 * :param uint8_t * pixels: The buffer, in which the pixel data is stored.
 * :param uint32_t n_bytes: The size of the buffer.
Rahix's avatar
Rahix committed
1922
1923
 *
 * .. versionadded:: 1.10
1924
1925
1926
 */
API(API_WS2812_WRITE, void epic_ws2812_write(uint8_t pin, uint8_t *pixels, uint32_t n_bytes));

Rahix's avatar
Rahix committed
1927
#endif /* _EPICARDIUM_H */
1928
For faster browsing, not all history is shown. View entire blame