Add partial ST7789 support
This commit is contained in:
parent
dfeccd50b9
commit
846f909cfe
@ -5,11 +5,14 @@ add_library(picoled
|
|||||||
include/picoled/buffer.h
|
include/picoled/buffer.h
|
||||||
include/picoled/gfx/2D.h
|
include/picoled/gfx/2D.h
|
||||||
include/picoled/SSD1306.h
|
include/picoled/SSD1306.h
|
||||||
|
include/picoled/ST7789.h
|
||||||
|
|
||||||
src/picoled.cpp
|
src/picoled.cpp
|
||||||
|
src/buffer.cpp
|
||||||
src/2D.cpp
|
src/2D.cpp
|
||||||
src/SSD1306.cpp
|
src/SSD1306.cpp
|
||||||
|
src/ST7789.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(picoled PUBLIC hardware_i2c pico_stdlib)
|
target_link_libraries(picoled PUBLIC pico_stdlib hardware_i2c hardware_spi)
|
||||||
target_include_directories(picoled PUBLIC include)
|
target_include_directories(picoled PUBLIC include)
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
namespace picoled
|
namespace picoled
|
||||||
{
|
{
|
||||||
|
|
||||||
// rgb565
|
|
||||||
class pixel
|
class pixel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -59,7 +58,7 @@ public:
|
|||||||
size_t get_width() const { return buffer_a.get_width(); }
|
size_t get_width() const { return buffer_a.get_width(); }
|
||||||
size_t get_height() const { return buffer_a.get_height(); }
|
size_t get_height() const { return buffer_a.get_height(); }
|
||||||
|
|
||||||
void write(int x, int y, const pixel& p) { active_buffer().write(x, y, p); }
|
virtual void write(int x, int y, const pixel& p) { active_buffer().write(x, y, p); }
|
||||||
|
|
||||||
buffer<pixel>& active_buffer() { return active ? buffer_b : buffer_a; }
|
buffer<pixel>& active_buffer() { return active ? buffer_b : buffer_a; }
|
||||||
|
|
||||||
@ -67,9 +66,10 @@ public:
|
|||||||
void swap_buffers();
|
void swap_buffers();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void update_impl() = 0;
|
virtual void update_impl() const = 0;
|
||||||
|
|
||||||
buffer<pixel>& inactive_buffer() { return active ? buffer_a : buffer_b; }
|
buffer<pixel>& inactive_buffer() { return active ? buffer_a : buffer_b; }
|
||||||
|
const buffer<pixel>& inactive_buffer() const { return active ? buffer_a : buffer_b; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool active;
|
bool active;
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
#ifndef PICOLED_SSD1306_H
|
#ifndef PICOLED_SSD1306_H
|
||||||
#define PICOLED_SSD1306_H
|
#define PICOLED_SSD1306_H
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
#include <hardware/i2c.h>
|
#include <hardware/i2c.h>
|
||||||
|
|
||||||
#include "picoled.h"
|
#include "picoled.h"
|
||||||
@ -17,7 +15,7 @@ public:
|
|||||||
virtual ~ssd1306();
|
virtual ~ssd1306();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void update_impl() override;
|
void update_impl() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void command(uint8_t cmd) const;
|
void command(uint8_t cmd) const;
|
||||||
|
39
include/picoled/ST7789.h
Normal file
39
include/picoled/ST7789.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#ifndef PICOLED_ST7889_H
|
||||||
|
#define PICOLED_ST7889_H
|
||||||
|
|
||||||
|
#include <hardware/spi.h>
|
||||||
|
|
||||||
|
#include "picoled.h"
|
||||||
|
|
||||||
|
namespace picoled
|
||||||
|
{
|
||||||
|
|
||||||
|
class st7789 : public oled
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
st7789(size_t width, size_t height, spi_inst_t* spi, uint8_t cs_pin, uint8_t dc_pin);
|
||||||
|
virtual ~st7789() = default;
|
||||||
|
|
||||||
|
void write(int x, int y, const pixel& p) override
|
||||||
|
{
|
||||||
|
oled::write(x, y, format(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void update_impl() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void command(uint8_t cmd) const;
|
||||||
|
void command(uint8_t cmd, uint8_t param) const;
|
||||||
|
void command(uint8_t cmd, const uint8_t* params, size_t param_count) const;
|
||||||
|
|
||||||
|
spi_inst_t* spi;
|
||||||
|
uint8_t cs_pin;
|
||||||
|
uint8_t dc_pin;
|
||||||
|
|
||||||
|
static pixel format(const pixel& p);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif//PICOLED_ST7889_H
|
@ -2,10 +2,45 @@
|
|||||||
#define PICOLED_BUFFER_H
|
#define PICOLED_BUFFER_H
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
namespace picoled
|
namespace picoled
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class fixed
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
fixed();
|
||||||
|
|
||||||
|
fixed(float value);
|
||||||
|
operator int16_t() const;
|
||||||
|
|
||||||
|
fixed operator-() const;
|
||||||
|
fixed operator~() const;
|
||||||
|
|
||||||
|
fixed operator+(const fixed& other) const;
|
||||||
|
fixed operator-(const fixed& other) const;
|
||||||
|
fixed operator*(const fixed& other) const;
|
||||||
|
fixed operator/(const fixed& other) const;
|
||||||
|
|
||||||
|
fixed& operator+=(const fixed& other);
|
||||||
|
fixed& operator-=(const fixed& other);
|
||||||
|
fixed& operator*=(const fixed& other);
|
||||||
|
fixed& operator/=(const fixed& other);
|
||||||
|
|
||||||
|
bool operator<(const fixed& other) const;
|
||||||
|
bool operator<=(const fixed& other) const;
|
||||||
|
bool operator>(const fixed& other) const;
|
||||||
|
bool operator>=(const fixed& other) const;
|
||||||
|
bool operator==(const fixed& other) const;
|
||||||
|
|
||||||
|
static fixed min(fixed a, fixed b);
|
||||||
|
static fixed max(fixed a, fixed b);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int32_t value;
|
||||||
|
};
|
||||||
|
|
||||||
// behavior when out of bounds
|
// behavior when out of bounds
|
||||||
enum class buffer_read_mode
|
enum class buffer_read_mode
|
||||||
{
|
{
|
||||||
@ -45,9 +80,9 @@ public:
|
|||||||
data[x + y * width] = pixel;
|
data[x + y * width] = pixel;
|
||||||
}
|
}
|
||||||
|
|
||||||
T read_uv(float x, float y, buffer_read_mode mode = buffer_read_mode::clamp) const
|
T read_uv(fixed x, fixed y, buffer_read_mode mode = buffer_read_mode::clamp) const
|
||||||
{
|
{
|
||||||
return read(x * width, y * height, mode);
|
return read(x * fixed(width), y * fixed(height), mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
T read(int x, int y, buffer_read_mode mode = buffer_read_mode::clamp) const
|
T read(int x, int y, buffer_read_mode mode = buffer_read_mode::clamp) const
|
||||||
@ -67,6 +102,11 @@ public:
|
|||||||
return T();
|
return T();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const uint8_t* data_pointer() const
|
||||||
|
{
|
||||||
|
return reinterpret_cast<const uint8_t*>(data);
|
||||||
|
}
|
||||||
|
|
||||||
void clear()
|
void clear()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < width * height; i++)
|
for (int i = 0; i < width * height; i++)
|
||||||
|
@ -9,31 +9,31 @@ namespace picoled::gfx
|
|||||||
class vec2
|
class vec2
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
float x;
|
fixed x;
|
||||||
float y;
|
fixed y;
|
||||||
|
|
||||||
vec2 operator+(const vec2& other) const { return { x + other.x, y + other.y }; }
|
vec2 operator+(const vec2& other) const { return { x + other.x, y + other.y }; }
|
||||||
vec2 operator-(const vec2& other) const { return { x - other.x, y - other.y }; }
|
vec2 operator-(const vec2& other) const { return { x - other.x, y - other.y }; }
|
||||||
vec2 operator*(const vec2& other) const { return { x * other.x, y * other.y }; }
|
vec2 operator*(const vec2& other) const { return { x * other.x, y * other.y }; }
|
||||||
vec2 operator/(const vec2& other) const { return { x / other.x, y / other.y }; }
|
vec2 operator/(const vec2& other) const { return { x / other.x, y / other.y }; }
|
||||||
|
|
||||||
float operator%(const vec2& other) const { return x * other.x + y * other.y; }
|
fixed operator%(const vec2& other) const { return x * other.x + y * other.y; }
|
||||||
float operator^(const vec2& other) const { return x * other.y - y * other.x; }
|
fixed operator^(const vec2& other) const { return x * other.y - y * other.x; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class vec3
|
class vec3
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
float x;
|
fixed x;
|
||||||
float y;
|
fixed y;
|
||||||
float z;
|
fixed z;
|
||||||
|
|
||||||
vec3 operator+(const vec3& other) const { return { x + other.x, y + other.y, z + other.z }; }
|
vec3 operator+(const vec3& other) const { return { x + other.x, y + other.y, z + other.z }; }
|
||||||
vec3 operator-(const vec3& other) const { return { x - other.x, y - other.y, z - other.z }; }
|
vec3 operator-(const vec3& other) const { return { x - other.x, y - other.y, z - other.z }; }
|
||||||
vec3 operator*(const vec3& other) const { return { x * other.x, y * other.y, z * other.z }; }
|
vec3 operator*(const vec3& other) const { return { x * other.x, y * other.y, z * other.z }; }
|
||||||
vec3 operator/(const vec3& other) const { return { x / other.x, y / other.y, z / other.z }; }
|
vec3 operator/(const vec3& other) const { return { x / other.x, y / other.y, z / other.z }; }
|
||||||
|
|
||||||
float operator%(const vec3& other) const { return x * other.x + y * other.y + z * other.z; }
|
fixed operator%(const vec3& other) const { return x * other.x + y * other.y + z * other.z; }
|
||||||
vec3 operator^(const vec3& other) const
|
vec3 operator^(const vec3& other) const
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
@ -67,7 +67,7 @@ public:
|
|||||||
vec2 max() const;
|
vec2 max() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float area_double() const;
|
fixed area_double() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class gfx2d
|
class gfx2d
|
||||||
|
36
src/2D.cpp
36
src/2D.cpp
@ -10,7 +10,7 @@ namespace picoled::gfx
|
|||||||
|
|
||||||
triangle triangle::fix_winding() const
|
triangle triangle::fix_winding() const
|
||||||
{
|
{
|
||||||
if (((b.position - a.position) ^ (c.position - a.position)) < 0)
|
if (((b.position - a.position) ^ (c.position - a.position)) < fixed(0))
|
||||||
{
|
{
|
||||||
return { a, c, b };
|
return { a, c, b };
|
||||||
}
|
}
|
||||||
@ -22,27 +22,27 @@ triangle triangle::fix_winding() const
|
|||||||
|
|
||||||
vec3 triangle::barycentric(const vec2& p) const
|
vec3 triangle::barycentric(const vec2& p) const
|
||||||
{
|
{
|
||||||
const float total = area_double();
|
const fixed total = area_double();
|
||||||
const float u = triangle{ b, a, p }.area_double() / total;
|
const fixed u = triangle{ b, a, p }.area_double() / total;
|
||||||
const float v = triangle{ a, c, p }.area_double() / total;
|
const fixed v = triangle{ a, c, p }.area_double() / total;
|
||||||
return vec3{ u, v, 1 - u - v };
|
return vec3{ u, v, fixed(1) - u - v };
|
||||||
}
|
}
|
||||||
|
|
||||||
bool triangle::contains(const vec2& p) const
|
bool triangle::contains(const vec2& p) const
|
||||||
{
|
{
|
||||||
const float abp = (b.position - a.position) ^ (p - a.position);
|
const fixed abp = (b.position - a.position) ^ (p - a.position);
|
||||||
const float bcp = (c.position - b.position) ^ (p - b.position);
|
const fixed bcp = (c.position - b.position) ^ (p - b.position);
|
||||||
const float cap = (a.position - c.position) ^ (p - c.position);
|
const fixed cap = (a.position - c.position) ^ (p - c.position);
|
||||||
|
|
||||||
return abp >= 0 && bcp >= 0 && cap >= 0;
|
return abp >= fixed(0) && bcp >= fixed(0) && cap >= fixed(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
vec2 triangle::min() const
|
vec2 triangle::min() const
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
{
|
{
|
||||||
fminf(fminf(a.position.x, b.position.x), c.position.x),
|
fixed::min(fixed::min(a.position.x, b.position.x), c.position.x),
|
||||||
fminf(fminf(a.position.y, b.position.y), c.position.y)
|
fixed::min(fixed::min(a.position.y, b.position.y), c.position.y)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,12 +50,12 @@ vec2 triangle::max() const
|
|||||||
{
|
{
|
||||||
return
|
return
|
||||||
{
|
{
|
||||||
fmaxf(fmaxf(a.position.x, b.position.x), c.position.x),
|
fixed::max(fixed::max(a.position.x, b.position.x), c.position.x),
|
||||||
fmaxf(fmaxf(a.position.y, b.position.y), c.position.y)
|
fixed::max(fixed::max(a.position.y, b.position.y), c.position.y)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
float triangle::area_double() const
|
fixed triangle::area_double() const
|
||||||
{
|
{
|
||||||
// don't divide by two since it would cancel out
|
// don't divide by two since it would cancel out
|
||||||
// in the barycentric coordinate calculation anyway
|
// in the barycentric coordinate calculation anyway
|
||||||
@ -69,16 +69,16 @@ void gfx2d::draw_triangle(triangle tri, const buffer<pixel>& texture, bool ignor
|
|||||||
const vec2 min = tri.min();
|
const vec2 min = tri.min();
|
||||||
const vec2 max = tri.max();
|
const vec2 max = tri.max();
|
||||||
|
|
||||||
for (float i = min.x; i <= max.x; i += 0.75f)
|
for (fixed i = min.x; i <= max.x; i += 1)
|
||||||
{
|
{
|
||||||
for (float j = min.y; j <= max.y; j += 0.75f)
|
for (fixed j = min.y; j <= max.y; j += 1)
|
||||||
{
|
{
|
||||||
const vec2 position = { i, j };
|
const vec2 position = { i, j };
|
||||||
if (tri.contains(position))
|
if (tri.contains(position))
|
||||||
{
|
{
|
||||||
const vec3 barycentric = tri.barycentric(position);
|
const vec3 barycentric = tri.barycentric(position);
|
||||||
const float u = barycentric % vec3{ tri.a.texture_coordinates.x, tri.b.texture_coordinates.x, tri.c.texture_coordinates.x };
|
const fixed u = barycentric % vec3{ tri.a.texture_coordinates.x, tri.b.texture_coordinates.x, tri.c.texture_coordinates.x };
|
||||||
const float v = barycentric % vec3{ tri.a.texture_coordinates.y, tri.b.texture_coordinates.y, tri.c.texture_coordinates.y };
|
const fixed v = barycentric % vec3{ tri.a.texture_coordinates.y, tri.b.texture_coordinates.y, tri.c.texture_coordinates.y };
|
||||||
const pixel read = texture.read_uv(u, v, buffer_read_mode::clamp);
|
const pixel read = texture.read_uv(u, v, buffer_read_mode::clamp);
|
||||||
screen->write(i, j, read);
|
screen->write(i, j, read);
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ ssd1306::~ssd1306()
|
|||||||
delete[] buffer;
|
delete[] buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ssd1306::update_impl()
|
void ssd1306::update_impl() const
|
||||||
{
|
{
|
||||||
// clear display to zero
|
// clear display to zero
|
||||||
memset(&buffer[1], 0, get_width() * get_height() * sizeof(*buffer) / 8);
|
memset(&buffer[1], 0, get_width() * get_height() * sizeof(*buffer) / 8);
|
||||||
|
92
src/ST7789.cpp
Normal file
92
src/ST7789.cpp
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
#include "picoled/ST7789.h"
|
||||||
|
|
||||||
|
#include <pico/stdlib.h>
|
||||||
|
|
||||||
|
namespace picoled
|
||||||
|
{
|
||||||
|
|
||||||
|
st7789::st7789(size_t width, size_t height, spi_inst_t* spi, uint8_t cs_pin, uint8_t dc_pin) :
|
||||||
|
oled(width, height),
|
||||||
|
spi(spi),
|
||||||
|
cs_pin(cs_pin),
|
||||||
|
dc_pin(dc_pin)
|
||||||
|
{
|
||||||
|
command(0x01); sleep_ms(150); // reset device
|
||||||
|
command(0x11); sleep_ms(10); // stop sleeping
|
||||||
|
command(0x3A, 0x66); sleep_ms(10); // set display format
|
||||||
|
{
|
||||||
|
constexpr size_t PARAM_COUNT = 4;
|
||||||
|
// no clue where these numbers come from
|
||||||
|
// see https://github.com/adafruit/Adafruit-ST7735-Library/blob/62112b90eddcb2ecc51f474e9fe98b68eb26cb2a/Adafruit_ST7789.cpp#L111-L117
|
||||||
|
const uint8_t params[PARAM_COUNT] =
|
||||||
|
{
|
||||||
|
0x00,
|
||||||
|
0x35,
|
||||||
|
0x00,
|
||||||
|
0xBB
|
||||||
|
};
|
||||||
|
|
||||||
|
command(0x2A, params, PARAM_COUNT); // set column address range
|
||||||
|
}
|
||||||
|
{
|
||||||
|
constexpr size_t PARAM_COUNT = 4;
|
||||||
|
// no clue where these numbers come from
|
||||||
|
// see https://github.com/adafruit/Adafruit-ST7735-Library/blob/62112b90eddcb2ecc51f474e9fe98b68eb26cb2a/Adafruit_ST7789.cpp#L111-L117
|
||||||
|
const uint8_t params[PARAM_COUNT] =
|
||||||
|
{
|
||||||
|
0x00,
|
||||||
|
0x28,
|
||||||
|
0x01,
|
||||||
|
0x17
|
||||||
|
};
|
||||||
|
|
||||||
|
command(0x2B, params, PARAM_COUNT); // set row address range
|
||||||
|
}
|
||||||
|
command(0x36, 0b11000000); // set memory addressing mode
|
||||||
|
command(0x21); // turn on display inversion
|
||||||
|
command(0x13); sleep_ms(10); // set display to normal mode
|
||||||
|
command(0x29); sleep_ms(10); // turn on display
|
||||||
|
}
|
||||||
|
|
||||||
|
void st7789::update_impl() const
|
||||||
|
{
|
||||||
|
command(0x2C, inactive_buffer().data_pointer(), get_width() * get_height() * 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void st7789::command(uint8_t cmd) const
|
||||||
|
{
|
||||||
|
command(cmd, nullptr, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void st7789::command(uint8_t cmd, uint8_t param) const
|
||||||
|
{
|
||||||
|
command(cmd, ¶m, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void st7789::command(uint8_t cmd, const uint8_t* params, size_t param_count) const
|
||||||
|
{
|
||||||
|
gpio_put(cs_pin, false); // select chip
|
||||||
|
|
||||||
|
gpio_put(dc_pin, false); // command mode
|
||||||
|
spi_write_blocking(spi, &cmd, 1);
|
||||||
|
|
||||||
|
gpio_put(dc_pin, true); // parameters are sent via data mode
|
||||||
|
spi_write_blocking(spi, params, param_count);
|
||||||
|
|
||||||
|
gpio_put(cs_pin, true); // deselect chip
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel st7789::format(const pixel& p)
|
||||||
|
{
|
||||||
|
const uint16_t red_scaled = p.red() * 0x3F / 0xFF; // scale to 6-bit color
|
||||||
|
const uint16_t green_scaled = p.green() * 0x3F / 0xFF; // scale to 6-bit color
|
||||||
|
const uint16_t blue_scaled = p.blue() * 0x3F / 0xFF; // scale to 6-bit color
|
||||||
|
|
||||||
|
const uint8_t red = (red_scaled & 0xFF) << 2;
|
||||||
|
const uint8_t green = (green_scaled & 0xFF) << 2;
|
||||||
|
const uint8_t blue = (blue_scaled & 0xFF) << 2;
|
||||||
|
|
||||||
|
return { red, green, blue };
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
110
src/buffer.cpp
Normal file
110
src/buffer.cpp
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
#include "picoled/buffer.h"
|
||||||
|
|
||||||
|
#include <pico/stdio.h>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
constexpr int FRACTIONAL_BITS = 16;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace picoled
|
||||||
|
{
|
||||||
|
|
||||||
|
fixed::fixed() :
|
||||||
|
value(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
fixed::fixed(float value) :
|
||||||
|
value(value * (1 << FRACTIONAL_BITS))
|
||||||
|
{}
|
||||||
|
|
||||||
|
fixed::operator int16_t() const
|
||||||
|
{
|
||||||
|
return value >> FRACTIONAL_BITS;
|
||||||
|
}
|
||||||
|
|
||||||
|
fixed fixed::operator-() const
|
||||||
|
{
|
||||||
|
fixed f;
|
||||||
|
f.value = -value;
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
fixed fixed::operator~() const
|
||||||
|
{
|
||||||
|
fixed f;
|
||||||
|
f.value = ~value;
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
fixed fixed::operator+(const fixed& other) const
|
||||||
|
{
|
||||||
|
fixed copy = *this;
|
||||||
|
copy += other;
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
fixed fixed::operator-(const fixed& other) const
|
||||||
|
{
|
||||||
|
fixed copy = *this;
|
||||||
|
copy -= other;
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
fixed fixed::operator*(const fixed& other) const
|
||||||
|
{
|
||||||
|
fixed copy = *this;
|
||||||
|
copy *= other;
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
fixed fixed::operator/(const fixed& other) const
|
||||||
|
{
|
||||||
|
fixed copy = *this;
|
||||||
|
copy /= other;
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
fixed& fixed::operator+=(const fixed& other)
|
||||||
|
{
|
||||||
|
value += other.value;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
fixed& fixed::operator-=(const fixed& other)
|
||||||
|
{
|
||||||
|
value -= other.value;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
fixed& fixed::operator*=(const fixed& other)
|
||||||
|
{
|
||||||
|
value = (int64_t(value) * int64_t(other.value)) >> FRACTIONAL_BITS;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
fixed& fixed::operator/=(const fixed& other)
|
||||||
|
{
|
||||||
|
value = (int64_t(value) << FRACTIONAL_BITS) / other.value;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fixed::operator>(const fixed& other) const { return value > other.value; }
|
||||||
|
bool fixed::operator>=(const fixed& other) const { return value >= other.value; }
|
||||||
|
bool fixed::operator<(const fixed& other) const { return value < other.value; }
|
||||||
|
bool fixed::operator<=(const fixed& other) const { return value <= other.value; }
|
||||||
|
bool fixed::operator==(const fixed& other) const { return value == other.value; }
|
||||||
|
|
||||||
|
fixed fixed::min(fixed a, fixed b)
|
||||||
|
{
|
||||||
|
return a < b ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
fixed fixed::max(fixed a, fixed b)
|
||||||
|
{
|
||||||
|
return a > b ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user