summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/osm/protocol.h84
-rw-r--r--include/osm/types.h6
-rw-r--r--src/types.c154
3 files changed, 194 insertions, 50 deletions
diff --git a/include/osm/protocol.h b/include/osm/protocol.h
index 29eb6cc..5eec65f 100644
--- a/include/osm/protocol.h
+++ b/include/osm/protocol.h
@@ -19,7 +19,7 @@ extern const char OSM_MAGIC_INIT[4];
extern const char OSM_MAGIC_FRAME[4];
/**
- * The init frame from the controller
+ * The init frame header from the controller
* includes the uuid of the sender and the public
* key the sender will use to sign messages (up to 4096 bytes)
*
@@ -28,10 +28,20 @@ extern const char OSM_MAGIC_FRAME[4];
*/
typedef struct {
uint8_t magic[4];
+ uint8_t version;
uint8_t uuid[8];
uint8_t keytype;
uint16_t keylen;
- uint8_t pubkey[4096];
+} OSMInitFrameHeader;
+
+/**
+ * The max possible length of an init frame.
+ * The actual frame length will vary based on the size of the
+ * pubkey.
+ */
+typedef struct {
+ OSMInitFrameHeader header;
+ uint8_t key[4096];
} OSMInitFrame;
/**
@@ -41,22 +51,27 @@ typedef struct {
typedef struct {
uint8_t magic[4];
uint8_t uuid[8];
+} OSMPairHeader;
-} OSMInitPairfmt;
+/**
+ * Represents a frame which describes
+ */
+typedef struct {
+ OSMPairHeader header;
+ uint8_t data[1024]; // message data
+} OSMPairFrame;
/**
- * All OSM messages are at most 2048 bytes long and include a gpg signature at
- * the start of the data to validate the sender. The signature length is determined based on
- * the signing key of the sender.
+ * Main OSM Frame header: All frames contain this plus a secondary header
+ * with more information based on the frame's type
*/
typedef struct {
uint8_t magic[4]; // magic number
uint8_t uuid[8]; // device that this message is from
uint8_t sub_uuid[8]; // sub device that this message is from
uint8_t frame_type; // type of frame
- uint8_t data[2048]; // message data
-} OSMFrame;
+} OSMFrameHeader;
/*
* Once the data has been validated, it is one of the following frame types
@@ -81,20 +96,59 @@ typedef struct {
* Result of a sent frame
*/
typedef struct {
- uint8_t res_type; // the type of frame sent
- uint8_t a;
-} OSMResFrame;
+ uint8_t res_type; // the type of frame we are replying to
+} OSMResHeader;
+/**
+ * Header for frames where we are attempting to set
+ * data on the other device
+ */
typedef struct {
uint8_t num_set;
- uint8_t pairs[2047];
-} OSMSetFrame;
+} OSMSetHeader;
+
+/**
+ * Header for frames where we are attempting to get
+ * data from the other device
+ */
+typedef struct {
+ uint8_t num_get;
+} OSMGetHeader;
+
+/**
+ * Header for frames where we are sending
+ * an arbitrary data payload to the other device
+ */
+typedef struct {
+ uint8_t number; // Which "set" this data frame belongs to (if multiple data streams are being sent at once)
+ uint16_t len; // How many significant bytes are in this frame
+} OSMDataHeader;
+
+/**
+ * Header for streams where we are going to send a
+ * continuous stream of data to the other device
+ */
+typedef struct {
+} OSMStreamOutHeader;
+
+/**
+ * Header for streams where we are asking for
+ * a continuous data stream from the other device
+ */
+typedef struct {
+} OSMStreamInHeader;
+
+/**
+ * Header for a control frame where we are closing
+ * a previously opened stream.
+ */
+typedef struct {
+} OSMStreamCloseHeader;
typedef struct {
uint8_t control_id[8]; // The ID of the control we are setting the value on
- uint8_t val_type; // The data type of the value (or 0 for future data frames)
uint8_t value[8]; // The new value for the control, or the data frame number we will next use
-} OSMSetControl;
+} OSMControl;
diff --git a/include/osm/types.h b/include/osm/types.h
index 08a0d03..81a072e 100644
--- a/include/osm/types.h
+++ b/include/osm/types.h
@@ -33,6 +33,12 @@ typedef int64_t OSMInteger;
/// Represents a floating point (IEEE 754 64 bit)
typedef uint64_t OSMFloat;
+#define OSM_FLOAT_EXPO_LEN 11
+#define OSM_FLOAT_EXPO_MASK 0x7ff
+#define OSM_FLOAT_EXPO_BIAS 0x3ff
+#define OSM_FLOAT_FRAC_LEN 52
+#define OSM_FLOAT_FRAC_MASK 0xffffffffffffff
+
/// Represents the broken down floating point number
typedef struct {
uint8_t sign;
diff --git a/src/types.c b/src/types.c
index ff0459e..8fda424 100644
--- a/src/types.c
+++ b/src/types.c
@@ -16,9 +16,9 @@ OSMFloatBreakdown osm_float_to_break(OSMFloat f)
{
OSMFloatBreakdown out;
- out.sign = f >> 63;
- out.mantissa = (f >> 52) & 0x7ff;
- out.fraction = f & 0xfffffffffffff;
+ out.sign = f >> (OSM_FLOAT_EXPO_LEN + OSM_FLOAT_FRAC_LEN);
+ out.mantissa = (f >> OSM_FLOAT_FRAC_LEN) & OSM_FLOAT_EXPO_MASK;
+ out.fraction = f & OSM_FLOAT_FRAC_MASK;
return out;
}
@@ -39,32 +39,37 @@ OSMFloatBreakdown _osm_ieee754_enlarge(uint64_t d, uint16_t m_len, uint16_t f_le
mask = (1 << f_len) - 1;
out.fraction = d & mask;
+ // Create corrected mantissa and fraction (if not denormal)
if (out.mantissa >= bias)
{
// non-negative exponent
out.mantissa -= bias;
- out.mantissa += 0x3ff;
+ out.mantissa += OSM_FLOAT_EXPO_BIAS;
}
else if (out.mantissa < bias && out.mantissa > 0)
{
- out.mantissa = bias - out.mantissa; // true exponent (abs value)
- out.mantissa = 0x3ff - out.mantissa; // corrected for double precision numbers (won't overflow since we use this function with smaller mantissa)
- out.fraction = out.fraction << (52 - f_len); // corrected fraction based on difference in bit lengths
+ // true exponent (abs value)
+ out.mantissa = bias - out.mantissa;
+ // corrected for double precision numbers (won't overflow since we use this function with smaller mantissa)
+ out.mantissa = OSM_FLOAT_EXPO_BIAS - out.mantissa;
+ // corrected fraction based on difference in bit lengths
+ out.fraction = out.fraction << (OSM_FLOAT_FRAC_LEN - f_len);
}
-
+
+ // Handle zero and denormal
if (out.mantissa == 0)
{
if (out.fraction == 0)
return out;
// Denormal numbers (TODO)
- out.mantissa = 0x3ff - bias; // corrected mantissa
- out.fraction = out.fraction << (52 - f_len); // corrected fraction based on difference in bit lengths
+ out.mantissa = OSM_FLOAT_EXPO_BIAS - bias;
+ if (OSM_FLOAT_FRAC_LEN)
+ out.fraction = out.fraction << (OSM_FLOAT_FRAC_LEN - f_len); // corrected fraction based on difference in bit lengths
bias = (uint16_t) ceil(log2(out.fraction));
}
-
return out;
}
@@ -112,20 +117,110 @@ OSMFloat osm_break_to_float(OSMFloatBreakdown b)
if (b.sign)
out = 1;
- out = out << 63;
+ out = out << (OSM_FLOAT_FRAC_LEN + OSM_FLOAT_EXPO_LEN);
- out |= (OSMFloat)(b.mantissa & 0x7ff) << 52;
+ out |= (OSMFloat)(b.mantissa & OSM_FLOAT_EXPO_MASK) << OSM_FLOAT_FRAC_LEN;
- out |= b.fraction & 0xfffffffffffff;
+ out |= b.fraction & OSM_FLOAT_FRAC_MASK;
return out;
}
+bool _osm_is_nan(const OSMFloatBreakdown b)
+{
+ return b.mantissa == OSM_FLOAT_EXPO_MASK && b.fraction != 0;
+}
+
+int8_t _osm_is_infinity(const OSMFloatBreakdown b)
+{
+ if (b.mantissa == OSM_FLOAT_EXPO_MASK && b.fraction == 0)
+ {
+ if (b.sign)
+ return -1;
+ return 1;
+ }
+ return 0;
+}
+
+/// Handle NaN
+double _osm_ieee754_nan(OSMFloatBreakdown b, uint16_t m_len, uint16_t f_len)
+{
+}
+
+/// Handle subnormal numbers
+double _osm_ieee754_subnormal(OSMFloatBreakdown b, uint16_t m_len, uint16_t f_len)
+{
+ // TODO
+ return 0;
+}
+
+/**
+ * Converts a breakdown to a floating point number with given mantissa and
+ * fraction length (so long as the format is less than or equal to 64 bits)
+ */
double _osm_ieee754_assemble(OSMFloatBreakdown b, uint16_t m_len, uint16_t f_len)
{
- double out = 0;
- // Check
- return out;
+ uint64_t out = 0;
+
+ // Sign (assumed to be at end)
+ out |= b.sign << (m_len + f_len);
+
+ if (b.mantissa == 0 || )
+ {
+ // denormal numbers (TODO)
+ return *(double *)&out;
+ }
+
+ // Mantissa mask
+ uint64_t mask = (1 << m_len) - 1;
+
+ if (_osm_is_nan(b))
+ {
+ // Handle NaN
+ out |= mask << f_len;
+ if (f_len >= OSM_FLOAT_FRAC_LEN)
+ out |= b.fraction << (f_len - OSM_FLOAT_FRAC_LEN);
+ else
+ out |= b.fraction >> (OSM_FLOAT_FRAC_LEN - f_len);
+
+ // Make sure it's still nan just in case all the
+ // fraction bits got cleared
+ mask = (1 << f_len) - 1;
+ if ((out & mask) == 0)
+ out |= 1;
+
+ return *(double *)&out;
+ }
+
+ // Handle mantissa
+ uint64_t bias = mask >> 1;
+ if (b.mantissa > OSM_FLOAT_EXPO_BIAS)
+ {
+ b.mantissa -= OSM_FLOAT_EXPO_BIAS;
+ b.mantissa += bias;
+ }
+ else
+ {
+ b.mantissa = OSM_FLOAT_EXPO_BIAS - b.mantissa;
+ b.mantissa = bias - b.mantissa;
+ }
+
+ // Fraction (assumed to be low bits)
+ mask = (1 << f_len) - 1;
+
+ if (f_len >= OSM_FLOAT_FRAC_LEN)
+ out |= b.fraction << (f_len - OSM_FLOAT_FRAC_LEN);
+ else
+ out |= b.fraction >> (OSM_FLOAT_FRAC_LEN - f_len);
+
+ if ( && (out & mask) != 0)
+ out &= ~mask;
+
+#ifdef _OSM_FLOAT_USE_HIGH_BITS
+ out = out << (64 - (m_len + f_len + 1));
+#endif
+
+ return *(double *)&out;
}
/*
@@ -136,26 +231,26 @@ double _osm_ieee754_assemble(OSMFloatBreakdown b, uint16_t m_len, uint16_t f_len
*
* WARNING: This code flushes out of bounds values to infinity
*
- * INFO: This code keeps NaN values
+ * INFO: The fraction part of NaN values are set to 1
*
* Should probably be updated with more formats if I was
* feeling frisky.
*/
double osm_break_to_native_float(OSMFloatBreakdown b)
{
- double out = 0;
-
switch(sizeof(double))
{
case 2: {
+ return _osm_ieee754_assemble(b, 5, 10);
} break;
case 4: {
+ return _osm_ieee754_assemble(b, 8, 23);
} break;
case 8: {
OSMFloat f = osm_break_to_float(b);
- out = * (double *) &f;
+ return * (double *) &f;
} break;
default:
@@ -163,10 +258,7 @@ double osm_break_to_native_float(OSMFloatBreakdown b)
break;
}
- if (b.sign)
- out = -out;
-
- return out;
+ return 0;
}
double osm_float_to_native(OSMFloat f)
@@ -187,20 +279,12 @@ OSMFloat osm_native_to_float(double d)
bool osm_is_nan(OSMFloat f)
{
- OSMFloatBreakdown b = osm_float_to_break(f);
- return b.mantissa == 0x3ff && b.fraction != 0;
+ return _osm_is_nan(osm_float_to_break(f));
}
int8_t osm_is_infinity(OSMFloat f)
{
- OSMFloatBreakdown b = osm_float_to_break(f);
- if (b.mantissa == 0x3ff && b.fraction == 0)
- {
- if (b.sign)
- return -1;
- return 1;
- }
- return 0;
+ return _osm_is_infinity(osm_float_to_break(f));
}
OSMColor osm_rgb_to_color(uint8_t r, uint8_t g, uint8_t b)