Posthumous tronkination

This commit is contained in:
Ben Meadors
2024-10-08 05:33:38 -05:00
parent a0dd7b43d5
commit a05b009379
6 changed files with 79 additions and 69 deletions
@@ -7,8 +7,8 @@
#ifndef _HARDWARE_ROSC_H_
#define _HARDWARE_ROSC_H_
#include "pico.h"
#include "hardware/structs/rosc.h"
#include "pico.h"
#ifdef __cplusplus
extern "C" {
@@ -68,15 +68,18 @@ uint rosc_find_freq(uint32_t low_mhz, uint32_t high_mhz);
void rosc_set_div(uint32_t div);
inline static void rosc_clear_bad_write(void) {
inline static void rosc_clear_bad_write(void)
{
hw_clear_bits(&rosc_hw->status, ROSC_STATUS_BADWRITE_BITS);
}
inline static bool rosc_write_okay(void) {
inline static bool rosc_write_okay(void)
{
return !(rosc_hw->status & ROSC_STATUS_BADWRITE_BITS);
}
inline static void rosc_write(io_rw_32 *addr, uint32_t value) {
inline static void rosc_write(io_rw_32 *addr, uint32_t value)
{
rosc_clear_bad_write();
assert(rosc_write_okay());
*addr = value;
+18 -9
View File
@@ -12,11 +12,13 @@
// Given a ROSC delay stage code, return the next-numerically-higher code.
// Top result bit is set when called on maximum ROSC code.
uint32_t next_rosc_code(uint32_t code) {
uint32_t next_rosc_code(uint32_t code)
{
return ((code | 0x08888888u) + 1u) & 0xf7777777u;
}
uint rosc_find_freq(uint32_t low_mhz, uint32_t high_mhz) {
uint rosc_find_freq(uint32_t low_mhz, uint32_t high_mhz)
{
// TODO: This could be a lot better
rosc_set_div(1);
for (uint32_t code = 0; code <= 0x77777777u; code = next_rosc_code(code)) {
@@ -29,33 +31,40 @@ uint rosc_find_freq(uint32_t low_mhz, uint32_t high_mhz) {
return 0;
}
void rosc_set_div(uint32_t div) {
void rosc_set_div(uint32_t div)
{
assert(div <= 31 && div >= 1);
rosc_write(&rosc_hw->div, ROSC_DIV_VALUE_PASS + div);
}
void rosc_set_freq(uint32_t code) {
void rosc_set_freq(uint32_t code)
{
rosc_write(&rosc_hw->freqa, (ROSC_FREQA_PASSWD_VALUE_PASS << ROSC_FREQA_PASSWD_LSB) | (code & 0xffffu));
rosc_write(&rosc_hw->freqb, (ROSC_FREQA_PASSWD_VALUE_PASS << ROSC_FREQA_PASSWD_LSB) | (code >> 16u));
}
void rosc_set_range(uint range) {
void rosc_set_range(uint range)
{
// Range should use enumvals from the headers and thus have the password correct
rosc_write(&rosc_hw->ctrl, (ROSC_CTRL_ENABLE_VALUE_ENABLE << ROSC_CTRL_ENABLE_LSB) | range);
}
void rosc_disable(void) {
void rosc_disable(void)
{
uint32_t tmp = rosc_hw->ctrl;
tmp &= (~ROSC_CTRL_ENABLE_BITS);
tmp |= (ROSC_CTRL_ENABLE_VALUE_DISABLE << ROSC_CTRL_ENABLE_LSB);
rosc_write(&rosc_hw->ctrl, tmp);
// Wait for stable to go away
while(rosc_hw->status & ROSC_STATUS_STABLE_BITS);
while (rosc_hw->status & ROSC_STATUS_STABLE_BITS)
;
}
void rosc_set_dormant(void) {
void rosc_set_dormant(void)
{
// WARNING: This stops the rosc until woken up by an irq
rosc_write(&rosc_hw->dormant, ROSC_DORMANT_VALUE_DORMANT);
// Wait for it to become stable once woken up
while(!(rosc_hw->status & ROSC_STATUS_STABLE_BITS));
while (!(rosc_hw->status & ROSC_STATUS_STABLE_BITS))
;
}