Line data Source code
1 : #include "SIM_config.h"
2 :
3 : #if AP_SIM_LM2755_ENABLED
4 :
5 : #include "SIM_LM2755.h"
6 :
7 : using namespace SITL;
8 :
9 : #include <stdio.h>
10 :
11 2094 : void LM2755::init()
12 : {
13 2094 : add_register("GENERAL_PURPOSE", LM2755DevReg::GENERAL_PURPOSE, I2CRegisters::RegMode::WRONLY);
14 2094 : add_register("TIME_STEP", LM2755DevReg::TIME_STEP, I2CRegisters::RegMode::WRONLY);
15 :
16 2094 : add_register("D1_HIGH_LEVEL", LM2755DevReg::D1_HIGH_LEVEL, I2CRegisters::RegMode::WRONLY);
17 2094 : add_register("D1_LOW_LEVEL", LM2755DevReg::D1_LOW_LEVEL, I2CRegisters::RegMode::WRONLY);
18 2094 : add_register("D1_DELAY", LM2755DevReg::D1_DELAY, I2CRegisters::RegMode::WRONLY);
19 2094 : add_register("D1_RAMP_UP_STEP_TIME", LM2755DevReg::D1_RAMP_UP_STEP_TIME, I2CRegisters::RegMode::WRONLY);
20 2094 : add_register("D1_TIME_HIGH", LM2755DevReg::D1_TIME_HIGH, I2CRegisters::RegMode::WRONLY);
21 2094 : add_register("D1_RAMP_DOWN_STEP_TIME", LM2755DevReg::D1_RAMP_DOWN_STEP_TIME, I2CRegisters::RegMode::WRONLY);
22 2094 : add_register("D1_TIMING", LM2755DevReg::D1_TIMING, I2CRegisters::RegMode::WRONLY);
23 :
24 2094 : add_register("D2_HIGH_LEVEL", LM2755DevReg::D2_HIGH_LEVEL, I2CRegisters::RegMode::WRONLY);
25 2094 : add_register("D2_LOW_LEVEL", LM2755DevReg::D2_LOW_LEVEL, I2CRegisters::RegMode::WRONLY);
26 2094 : add_register("D2_DELAY", LM2755DevReg::D2_DELAY, I2CRegisters::RegMode::WRONLY);
27 2094 : add_register("D2_RAMP_UP_STEP_TIME", LM2755DevReg::D2_RAMP_UP_STEP_TIME, I2CRegisters::RegMode::WRONLY);
28 2094 : add_register("D2_TIME_HIGH", LM2755DevReg::D2_TIME_HIGH, I2CRegisters::RegMode::WRONLY);
29 2094 : add_register("D2_RAMP_DOWN_STEP_TIME", LM2755DevReg::D2_RAMP_DOWN_STEP_TIME, I2CRegisters::RegMode::WRONLY);
30 2094 : add_register("D2_TIMING", LM2755DevReg::D2_TIMING, I2CRegisters::RegMode::WRONLY);
31 :
32 2094 : add_register("D3_HIGH_LEVEL", LM2755DevReg::D3_HIGH_LEVEL, I2CRegisters::RegMode::WRONLY);
33 2094 : add_register("D3_LOW_LEVEL", LM2755DevReg::D3_LOW_LEVEL, I2CRegisters::RegMode::WRONLY);
34 2094 : add_register("D3_DELAY", LM2755DevReg::D3_DELAY, I2CRegisters::RegMode::WRONLY);
35 2094 : add_register("D3_RAMP_UP_STEP_TIME", LM2755DevReg::D3_RAMP_UP_STEP_TIME, I2CRegisters::RegMode::WRONLY);
36 2094 : add_register("D3_TIME_HIGH", LM2755DevReg::D3_TIME_HIGH, I2CRegisters::RegMode::WRONLY);
37 2094 : add_register("D3_RAMP_DOWN_STEP_TIME", LM2755DevReg::D3_RAMP_DOWN_STEP_TIME, I2CRegisters::RegMode::WRONLY);
38 2094 : add_register("D3_TIMING", LM2755DevReg::D3_TIMING, I2CRegisters::RegMode::WRONLY);
39 :
40 :
41 : // set startup register values. Note that a lot of these are zero
42 : // in the datasheet and are zero when we allocate this object, so
43 : // code is commented out here
44 :
45 : // set_register(LM2755DevReg::GENERAL_PURPOSE, 0b00000000);
46 2094 : set_register(LM2755DevReg::TIME_STEP, (uint8_t)0b10001000);
47 :
48 2094 : set_register(LM2755DevReg::D1_HIGH_LEVEL, (uint8_t)0b11100000);
49 2094 : set_register(LM2755DevReg::D1_LOW_LEVEL, (uint8_t)0b11100000);
50 : // set_register(LM2755DevReg::D1_DELAY, (uint8_t)0b00000000);
51 : // set_register(LM2755DevReg::D1_RAMP_UP_STEP_TIME, (uint8_t)0b00000000);
52 : // set_register(LM2755DevReg::D1_TIME_HIGH, (uint8_t)0b00000000);
53 : // set_register(LM2755DevReg::D1_RAMP_DOWN_STEP_TIME, (uint8_t)0b00000000);
54 : // set_register(LM2755DevReg::D1_TIMING, (uint8_t)0b00000000);
55 :
56 2094 : set_register(LM2755DevReg::D2_HIGH_LEVEL, (uint8_t)0b11100000);
57 2094 : set_register(LM2755DevReg::D2_LOW_LEVEL, (uint8_t)0b11100000);
58 : // set_register(LM2755DevReg::D2_DELAY, (uint8_t)0b00000000);
59 : // set_register(LM2755DevReg::D2_RAMP_UP_STEP_TIME, (uint8_t)0b00000000);
60 : // set_register(LM2755DevReg::D2_TIME_HIGH, (uint8_t)0b00000000);
61 : // set_register(LM2755DevReg::D2_RAMP_DOWN_STEP_TIME, (uint8_t)0b00000000);
62 : // set_register(LM2755DevReg::D2_TIMING, (uint8_t)0b00000000);
63 :
64 2094 : set_register(LM2755DevReg::D3_HIGH_LEVEL, (uint8_t)0b11100000);
65 2094 : set_register(LM2755DevReg::D3_LOW_LEVEL, (uint8_t)0b11100000);
66 : // set_register(LM2755DevReg::D3_DELAY, (uint8_t)0b00000000);
67 : // set_register(LM2755DevReg::D3_RAMP_UP_STEP_TIME, (uint8_t)0b00000000);
68 : // set_register(LM2755DevReg::D3_TIME_HIGH, (uint8_t)0b00000000);
69 : // set_register(LM2755DevReg::D3_RAMP_DOWN_STEP_TIME, (uint8_t)0b00000000);
70 : // set_register(LM2755DevReg::D3_TIMING, (uint8_t)0b00000000);
71 :
72 : // create objects for each of the channels to handle the dynamics
73 : // of updating each. The channel gets references to the relevant
74 : // configuration bytes.
75 2094 : d1 = NEW_NOTHROW LEDChannel(
76 2094 : byte[(uint8_t)LM2755DevReg::D1_HIGH_LEVEL],
77 2094 : byte[(uint8_t)LM2755DevReg::D1_LOW_LEVEL],
78 2094 : byte[(uint8_t)LM2755DevReg::D1_DELAY],
79 2094 : byte[(uint8_t)LM2755DevReg::D1_RAMP_UP_STEP_TIME],
80 2094 : byte[(uint8_t)LM2755DevReg::D1_TIME_HIGH],
81 2094 : byte[(uint8_t)LM2755DevReg::D1_RAMP_DOWN_STEP_TIME],
82 2094 : byte[(uint8_t)LM2755DevReg::D1_TIMING]
83 2094 : );
84 2094 : d2 = NEW_NOTHROW LEDChannel(
85 2094 : byte[(uint8_t)LM2755DevReg::D2_HIGH_LEVEL],
86 2094 : byte[(uint8_t)LM2755DevReg::D2_LOW_LEVEL],
87 2094 : byte[(uint8_t)LM2755DevReg::D2_DELAY],
88 2094 : byte[(uint8_t)LM2755DevReg::D2_RAMP_UP_STEP_TIME],
89 2094 : byte[(uint8_t)LM2755DevReg::D2_TIME_HIGH],
90 2094 : byte[(uint8_t)LM2755DevReg::D2_RAMP_DOWN_STEP_TIME],
91 2094 : byte[(uint8_t)LM2755DevReg::D2_TIMING]
92 2094 : );
93 2094 : d3 = NEW_NOTHROW LEDChannel(
94 2094 : byte[(uint8_t)LM2755DevReg::D3_HIGH_LEVEL],
95 2094 : byte[(uint8_t)LM2755DevReg::D3_LOW_LEVEL],
96 2094 : byte[(uint8_t)LM2755DevReg::D3_DELAY],
97 2094 : byte[(uint8_t)LM2755DevReg::D3_RAMP_UP_STEP_TIME],
98 2094 : byte[(uint8_t)LM2755DevReg::D3_TIME_HIGH],
99 2094 : byte[(uint8_t)LM2755DevReg::D3_RAMP_DOWN_STEP_TIME],
100 2094 : byte[(uint8_t)LM2755DevReg::D3_TIMING]
101 2094 : );
102 :
103 2094 : rgbled.init();
104 2094 : }
105 :
106 178759942 : void LM2755::update(const class Aircraft &aircraft)
107 : {
108 : union {
109 : struct {
110 : uint8_t d1_high_current : 1;
111 : uint8_t d2_high_current : 1;
112 : uint8_t d3_high_current : 1;
113 : uint8_t d1_dimming : 1;
114 : uint8_t d2_dimming : 1;
115 : uint8_t d3_dimming : 1;
116 : uint8_t external_clock : 1;
117 : uint8_t charge_pump : 1;
118 : } bits;
119 : uint8_t byte;
120 : } gp;
121 178759942 : gp.byte = get_register(LM2755DevReg::GENERAL_PURPOSE);
122 :
123 178759942 : if (gp.byte & 0x7) {
124 : // disallow high current
125 0 : AP_HAL::panic("High current bits set");
126 : }
127 178759942 : if (gp.bits.charge_pump) {
128 0 : AP_HAL::panic("Charge pump set");
129 : }
130 178759942 : if (gp.bits.external_clock) {
131 0 : AP_HAL::panic("external clock set");
132 : }
133 :
134 : // update each channel.
135 178759942 : if (gp.bits.d1_dimming) {
136 0 : d1->update();
137 : }
138 178759942 : if (gp.bits.d2_dimming) {
139 0 : d2->update();
140 : }
141 178759942 : if (gp.bits.d3_dimming) {
142 0 : d3->update();
143 : }
144 :
145 178759942 : rgbled.set_colours(
146 178759942 : d1->current_value(),
147 178759942 : d2->current_value(),
148 178759942 : d3->current_value()
149 : );
150 178759942 : }
151 :
152 0 : void LM2755::LEDChannel::update()
153 : {
154 : // calculate the brightness for this LED:
155 :
156 : // this is an awful simulation, which assumes that ArduPilot only
157 : // step-changtes the input for this device. AP could do better in
158 : // terms of passing through the "throbber" logic down to the
159 : // device itself - at which point a *lot* of these sanity checks
160 : // will fail.
161 :
162 0 : if (high_level != low_level) {
163 : // we should not be dimming when high != low
164 0 : AP_HAL::panic("high != low");
165 : }
166 0 : if (high_level > 31) {
167 0 : AP_HAL::panic("Invalid high value %u", high_level);
168 : }
169 0 : output_value = high_level * 8; // OK, so this is 0-248. So Sue me.
170 0 : }
171 :
172 : #endif
|