-
Notifications
You must be signed in to change notification settings - Fork 41
/
misc.c
155 lines (143 loc) · 4.18 KB
/
misc.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include "pico/stdlib.h"
#include "hardware/pio.h"
#include "pins.h"
#include <string.h>
#include "hardware/vreg.h"
#include "ws2812.pio.h"
#include "board_detect.h"
#include "misc.h"
#include "board_detect.h"
extern int ws_pio_offset;
#define BLINK_TIME 700
#define SHORT_TIME ( BLINK_TIME * 2 / 10 )
#define SHORT_PAUSE_TIME ((BLINK_TIME - SHORT_TIME) / 2)
#define LONG_TIME ( BLINK_TIME * 8 / 10 )
#define LONG_PAUSE_TIME ((BLINK_TIME - LONG_TIME) / 2)
#define PAUSE_BETWEEN 2000
#define PAUSE_BEFORE 750
#define CODE_REPEATS 3
#define GPIO_OD PADS_BANK0_GPIO0_OD_BITS
#define GPIO_IE PADS_BANK0_GPIO0_IE_BITS
#define GPIO_OD_PD (GPIO_OD | PADS_BANK0_GPIO0_PDE_BITS)
typedef void nopar();
void __not_in_flash_func(zzz)() {
*(uint32_t*)(0x4000803C + 0x3000) = 1; // go to 12 MHz
uint32_t * vreg = (uint32_t*)0x40064000;
vreg[1] &= ~1; // disable brownout
*(uint32_t*)0x40060000 = 0x00d1e000; // disable rosc
vreg[0] = 1; // lowest possible power
*(uint32_t*)0x40024000 = 0x00d1e000; // disable xosc
while(1);
}
void finish_pins_except_leds() {
for(int pin = 0; pin <= 29; pin += 1) {
if (pin == led_pin() || pin == pwr_pin())
continue;
if (pin == PIN_GLI_PICO || pin == PIN_GLI_XIAO || pin == PIN_GLI_WS || pin == PIN_GLI_ITSY)
{
gpio_pull_down(pin);
}
else
{
gpio_disable_pulls(pin);
}
gpio_disable_input_output(pin);
}
}
void finish_pins_leds() {
if (!is_tiny())
{
gpio_disable_input_output(led_pin());
}
gpio_disable_input_output(pwr_pin());
}
void halt_with_error(uint32_t err, uint32_t bits)
{
finish_pins_except_leds();
pio_set_sm_mask_enabled(pio0, 0xF, false);
pio_set_sm_mask_enabled(pio1, 0xF, false);
set_sys_clock_khz(48000, true);
vreg_set_voltage(VREG_VOLTAGE_0_95);
if (bits != 1)
{
put_pixel(0);
sleep_ms(PAUSE_BEFORE);
}
for(int j = 0; j < CODE_REPEATS; j++)
{
for(int i = 0; i < bits; i++)
{
bool is_long = err & (1 << (bits - i - 1));
sleep_ms(is_long ? LONG_PAUSE_TIME : SHORT_PAUSE_TIME);
bool success = bits == 1 && is_long == 0;
if (success)
put_pixel(PIX_whi);
else
put_pixel(PIX_yel);
sleep_ms(is_long ? LONG_TIME : success ? SHORT_TIME * 2 : SHORT_TIME);
put_pixel(0);
if (i != bits - 1 || j != CODE_REPEATS - 1)
sleep_ms(is_long ? LONG_PAUSE_TIME : SHORT_PAUSE_TIME);
if (i == bits - 1 && j != CODE_REPEATS - 1)
sleep_ms(PAUSE_BETWEEN);
}
// first write case, do not repeat this kind of error code
if (bits == 1)
break;
}
finish_pins_leds();
zzz();
}
void put_pixel(uint32_t pixel_grb)
{
static bool led_enabled = false;
if (is_pico())
{
gpio_init(led_pin());
if (pixel_grb) {
gpio_set_dir(led_pin(), true);
gpio_put(led_pin(), 1);
}
return;
}
ws2812_program_init(pio0, 3, ws_pio_offset, led_pin(), 800000, true);
if (!led_enabled && pwr_pin() != 31)
{
led_enabled = true;
gpio_init(pwr_pin());
gpio_set_drive_strength(pwr_pin(), GPIO_DRIVE_STRENGTH_12MA);
gpio_set_dir(pwr_pin(), true);
gpio_put(pwr_pin(), 1);
sleep_us(200);
}
pio_sm_put_blocking(pio0, 3, pixel_grb << 8u);
sleep_us(50);
pio_sm_set_enabled(pio0, 3, false);
if (!is_tiny())
{
gpio_init(led_pin());
}
}
void gpio_disable_input_output(int pin)
{
uint32_t pad_reg = 0x4001c000 + 4 + pin*4;
*(uint32_t*)(pad_reg + 0x2000) = GPIO_OD;
*(uint32_t*)(pad_reg + 0x3000) = GPIO_IE;
}
void gpio_enable_input_output(int pin)
{
uint32_t pad_reg = 0x4001c000 + 4 + pin*4;
*(uint32_t*)(pad_reg + 0x3000) = GPIO_OD;
*(uint32_t*)(pad_reg + 0x2000) = GPIO_IE;
}
void reset_cpu() {
gpio_enable_input_output(PIN_RST);
gpio_pull_up(PIN_RST);
sleep_us(1000);
gpio_init(PIN_RST);
gpio_set_dir(PIN_RST, true);
sleep_us(2000);
gpio_deinit(PIN_RST);
gpio_disable_pulls(PIN_RST);
gpio_disable_input_output(PIN_RST);
}