#include #include #include "std.h" #include "misc.h" #include "led.h" #include "storage.h" #include "font_petme128_8x8.h" void delay_ms(int ms); static void impl02_c_version() { int x = 0; while (x < 400) { int y = 0; while (y < 400) { volatile int z = 0; while (z < 400) { z = z + 1; } y = y + 1; } x = x + 1; } } void set_bits(__IO uint32_t *addr, uint32_t shift, uint32_t mask, uint32_t value) { uint32_t x = *addr; x &= ~(mask << shift); x |= (value << shift); *addr = x; } void gpio_init() { RCC->AHB1ENR |= RCC_AHB1ENR_CCMDATARAMEN | RCC_AHB1ENR_GPIOCEN | RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOAEN; } void gpio_pin_init(GPIO_TypeDef *gpio, uint32_t pin, uint32_t moder, uint32_t otyper, uint32_t ospeedr, uint32_t pupdr) { set_bits(&gpio->MODER, 2 * pin, 3, moder); set_bits(&gpio->OTYPER, pin, 1, otyper); set_bits(&gpio->OSPEEDR, 2 * pin, 3, ospeedr); set_bits(&gpio->PUPDR, 2 * pin, 3, pupdr); } void gpio_pin_af(GPIO_TypeDef *gpio, uint32_t pin, uint32_t af) { // set the AF bits for the given pin // pins 0-7 use low word of AFR, pins 8-15 use high word set_bits(&gpio->AFR[pin >> 3], 4 * (pin & 0x07), 0xf, af); } static void mma_init() { RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; // enable I2C1 gpio_pin_init(GPIOB, 6 /* B6 is SCL */, 2 /* AF mode */, 1 /* open drain output */, 1 /* 25 MHz */, 0 /* no pull up or pull down */); gpio_pin_init(GPIOB, 7 /* B7 is SDA */, 2 /* AF mode */, 1 /* open drain output */, 1 /* 25 MHz */, 0 /* no pull up or pull down */); gpio_pin_af(GPIOB, 6, 4 /* AF 4 for I2C1 */); gpio_pin_af(GPIOB, 7, 4 /* AF 4 for I2C1 */); // get clock speeds RCC_ClocksTypeDef rcc_clocks; RCC_GetClocksFreq(&rcc_clocks); // disable the I2C peripheral before we configure it I2C1->CR1 &= ~I2C_CR1_PE; // program peripheral input clock I2C1->CR2 = 4; // no interrupts; 4 MHz (hopefully!) (could go up to 42MHz) // configure clock control reg uint32_t freq = rcc_clocks.PCLK1_Frequency / (100000 << 1); // want 100kHz, this is the formula for freq I2C1->CCR = freq; // standard mode (speed), freq calculated as above // configure rise time reg I2C1->TRISE = (rcc_clocks.PCLK1_Frequency / 1000000) + 1; // formula for trise, gives maximum rise time // enable the I2C peripheral I2C1->CR1 |= I2C_CR1_PE; // set START bit in CR1 to generate a start cond! } static uint32_t i2c_get_sr() { // must read SR1 first, then SR2, as the read can clear some flags uint32_t sr1 = I2C1->SR1; uint32_t sr2 = I2C1->SR2; return (sr2 << 16) | sr1; } static void mma_restart(uint8_t addr, int write) { // send start condition I2C1->CR1 |= I2C_CR1_START; // wait for BUSY, MSL and SB --> Slave has acknowledged start condition while ((i2c_get_sr() & 0x00030001) != 0x00030001) { } if (write) { // send address and write bit I2C1->DR = (addr << 1) | 0; // wait for BUSY, MSL, ADDR, TXE and TRA while ((i2c_get_sr() & 0x00070082) != 0x00070082) { } } else { // send address and read bit I2C1->DR = (addr << 1) | 1; // wait for BUSY, MSL and ADDR flags while ((i2c_get_sr() & 0x00030002) != 0x00030002) { } } } static void mma_start(uint8_t addr, int write) { // wait until I2C is not busy while (I2C1->SR2 & I2C_SR2_BUSY) { } // do rest of start mma_restart(addr, write); } static void mma_send_byte(uint8_t data) { // send byte I2C1->DR = data; // wait for TRA, BUSY, MSL, TXE and BTF (byte transmitted) int timeout = 1000000; while ((i2c_get_sr() & 0x00070084) != 0x00070084) { if (timeout-- <= 0) { printf("mma_send_byte timed out!\n"); break; } } } static uint8_t mma_read_ack() { // enable ACK of received byte I2C1->CR1 |= I2C_CR1_ACK; // wait for BUSY, MSL and RXNE (byte received) while ((i2c_get_sr() & 0x00030040) != 0x00030040) { } // read and return data uint8_t data = I2C1->DR; return data; } static uint8_t mma_read_nack() { // disable ACK of received byte (to indicate end of receiving) I2C1->CR1 &= (uint16_t)~((uint16_t)I2C_CR1_ACK); // last byte should apparently also generate a stop condition I2C1->CR1 |= I2C_CR1_STOP; // wait for BUSY, MSL and RXNE (byte received) while ((i2c_get_sr() & 0x00030040) != 0x00030040) { } // read and return data uint8_t data = I2C1->DR; return data; } static void mma_stop() { // send stop condition I2C1->CR1 |= I2C_CR1_STOP; } #define PYB_USRSW_PORT (GPIOA) #define PYB_USRSW_PORT_NUM (13) void sw_init() { // make it an input with pull-up gpio_pin_init(PYB_USRSW_PORT, PYB_USRSW_PORT_NUM, 0, 0, 0, 1); } int sw_get() { if (PYB_USRSW_PORT->IDR & (1 << PYB_USRSW_PORT_NUM)) { // pulled high, so switch is not pressed return 0; } else { // pulled low, so switch is pressed return 1; } } #define PYB_LCD_PORT (GPIOA) #define PYB_LCD_CS1_PIN (0) #define PYB_LCD_RST_PIN (1) #define PYB_LCD_A0_PIN (2) #define PYB_LCD_SCL_PIN (3) #define PYB_LCD_SI_PIN (4) static void lcd_comm_out(uint8_t i) { delay_ms(0); PYB_LCD_PORT->BSRRH = 1 << PYB_LCD_CS1_PIN; // CS=0; enable PYB_LCD_PORT->BSRRH = 1 << PYB_LCD_A0_PIN; // A0=0; select instr reg // send byte bigendian, latches on rising clock for (uint32_t n = 0; n < 8; n++) { delay_ms(0); PYB_LCD_PORT->BSRRH = 1 << PYB_LCD_SCL_PIN; // SCL=0 if ((i & 0x80) == 0) { PYB_LCD_PORT->BSRRH = 1 << PYB_LCD_SI_PIN; // SI=0 } else { PYB_LCD_PORT->BSRRL = 1 << PYB_LCD_SI_PIN; // SI=1 } i <<= 1; delay_ms(0); PYB_LCD_PORT->BSRRL = 1 << PYB_LCD_SCL_PIN; // SCL=1 } PYB_LCD_PORT->BSRRL = 1 << PYB_LCD_CS1_PIN; // CS=1; disable /* in Python, native types: CS1_PIN(const) = 0 n = int(0) delay_ms(0) PORT[word:BSRRH] = 1 << CS1_PIN for n in range(0, 8): delay_ms(0) PORT[word:BSRRH] = 1 << SCL_PIN if i & 0x80 == 0: PORT[word:BSRRH] = 1 << SI_PIN else: PORT[word:BSRRL] = 1 << SI_PIN i <<= 1 delay_ms(0) PORT[word:BSRRL] = 1 << SCL_PIN */ } static void lcd_data_out(uint8_t i) { delay_ms(0); PYB_LCD_PORT->BSRRH = 1 << PYB_LCD_CS1_PIN; // CS=0; enable PYB_LCD_PORT->BSRRL = 1 << PYB_LCD_A0_PIN; // A0=1; select data reg // send byte bigendian, latches on rising clock for (uint32_t n = 0; n < 8; n++) { delay_ms(0); PYB_LCD_PORT->BSRRH = 1 << PYB_LCD_SCL_PIN; // SCL=0 if ((i & 0x80) == 0) { PYB_LCD_PORT->BSRRH = 1 << PYB_LCD_SI_PIN; // SI=0 } else { PYB_LCD_PORT->BSRRL = 1 << PYB_LCD_SI_PIN; // SI=1 } i <<= 1; delay_ms(0); PYB_LCD_PORT->BSRRL = 1 << PYB_LCD_SCL_PIN; // SCL=1 } PYB_LCD_PORT->BSRRL = 1 << PYB_LCD_CS1_PIN; // CS=1; disable } #define LCD_BUF_W (16) #define LCD_BUF_H (4) char lcd_buffer[LCD_BUF_W * LCD_BUF_H]; int lcd_line; int lcd_column; int lcd_next_line; void lcd_print_strn(const char *str, unsigned int len) { int redraw_min = lcd_line * LCD_BUF_W + lcd_column; int redraw_max = redraw_min; int did_new_line = 0; for (; len > 0; len--, str++) { // move to next line if needed if (lcd_next_line) { if (lcd_line + 1 < LCD_BUF_H) { lcd_line += 1; } else { lcd_line = LCD_BUF_H - 1; for (int i = 0; i < LCD_BUF_W * (LCD_BUF_H - 1); i++) { lcd_buffer[i] = lcd_buffer[i + LCD_BUF_W]; } for (int i = 0; i < LCD_BUF_W; i++) { lcd_buffer[LCD_BUF_W * (LCD_BUF_H - 1) + i] = ' '; } redraw_min = 0; redraw_max = LCD_BUF_W * LCD_BUF_H; } lcd_next_line = 0; lcd_column = 0; did_new_line = 1; } if (*str == '\n') { lcd_next_line = 1; } else if (lcd_column >= LCD_BUF_W) { lcd_next_line = 1; str -= 1; len += 1; } else { lcd_buffer[lcd_line * LCD_BUF_W + lcd_column] = *str; lcd_column += 1; int max = lcd_line * LCD_BUF_W + lcd_column; if (max > redraw_max) { redraw_max = max; } } } int last_page = -1; for (int i = redraw_min; i < redraw_max; i++) { int page = i / LCD_BUF_W; if (page != last_page) { int offset = 8 * (i - (page * LCD_BUF_W)); lcd_comm_out(0xb0 | page); // page address set lcd_comm_out(0x10 | ((offset >> 4) & 0x0f)); // column address set upper lcd_comm_out(0x00 | (offset & 0x0f)); // column address set lower last_page = page; } int chr = lcd_buffer[i]; if (chr < 32 || chr > 126) { chr = 127; } const uint8_t *chr_data = &font_petme128_8x8[(chr - 32) * 8]; for (int i = 0; i < 8; i++) { lcd_data_out(chr_data[i]); } } if (did_new_line) { delay_ms(200); } } static void lcd_init() { // set the outputs high PYB_LCD_PORT->BSRRL = 1 << PYB_LCD_CS1_PIN; PYB_LCD_PORT->BSRRL = 1 << PYB_LCD_RST_PIN; PYB_LCD_PORT->BSRRL = 1 << PYB_LCD_A0_PIN; PYB_LCD_PORT->BSRRL = 1 << PYB_LCD_SCL_PIN; PYB_LCD_PORT->BSRRL = 1 << PYB_LCD_SI_PIN; // make them push/pull outputs gpio_pin_init(PYB_LCD_PORT, PYB_LCD_CS1_PIN, 1, 0, 0, 0); gpio_pin_init(PYB_LCD_PORT, PYB_LCD_RST_PIN, 1, 0, 0, 0); gpio_pin_init(PYB_LCD_PORT, PYB_LCD_A0_PIN, 1, 0, 0, 0); gpio_pin_init(PYB_LCD_PORT, PYB_LCD_SCL_PIN, 1, 0, 0, 0); gpio_pin_init(PYB_LCD_PORT, PYB_LCD_SI_PIN, 1, 0, 0, 0); // init the LCD delay_ms(1); // wait a bit PYB_LCD_PORT->BSRRH = 1 << PYB_LCD_RST_PIN; // RST=0; reset delay_ms(1); // wait for reset; 2us min PYB_LCD_PORT->BSRRL = 1 << PYB_LCD_RST_PIN; // RST=1; enable delay_ms(1); // wait for reset; 2us min lcd_comm_out(0xa0); // ADC select, normal lcd_comm_out(0xc8); // common output mode select, reverse lcd_comm_out(0xa2); // LCD bias set, 1/9 bias lcd_comm_out(0x2f); // power control set, 0b111=(booster on, vreg on, vfollow on) lcd_comm_out(0x21); // v0 voltage regulator internal resistor ratio set, 0b001=small lcd_comm_out(0x81); // electronic volume mode set lcd_comm_out(0x34); // electronic volume register set, 0b110100 lcd_comm_out(0x40); // display start line set, 0 lcd_comm_out(0xaf); // LCD display, on // clear display for (int page = 0; page < 4; page++) { lcd_comm_out(0xb0 | page); // page address set lcd_comm_out(0x10); // column address set upper lcd_comm_out(0x00); // column address set lower for (int i = 0; i < 128; i++) { lcd_data_out(0x00); } } for (int i = 0; i < LCD_BUF_H * LCD_BUF_W; i++) { lcd_buffer[i] = ' '; } lcd_line = 0; lcd_column = 0; lcd_next_line = 0; } void __fatal_error(const char *msg) { lcd_print_strn("\nFATAL ERROR:\n", 14); lcd_print_strn(msg, strlen(msg)); for (;;) { led_state(PYB_LED_R1, 1); led_state(PYB_LED_R2, 0); delay_ms(150); led_state(PYB_LED_R1, 0); led_state(PYB_LED_R2, 1); delay_ms(150); } } #include "misc.h" #include "lexer.h" #include "mpyconfig.h" #include "parse.h" #include "compile.h" #include "runtime.h" py_obj_t pyb_delay(py_obj_t count) { delay_ms(rt_get_int(count)); return py_const_none; } py_obj_t pyb_led(py_obj_t state) { led_state(PYB_LED_G1, rt_is_true(state)); return state; } py_obj_t pyb_sw() { if (sw_get()) { return py_const_true; } else { return py_const_false; } } #include "ff.h" FATFS fatfs0; #include "nlr.h" /* void g(uint i) { printf("g:%d\n", i); if (i & 1) { nlr_jump((void*)(42 + i)); } } void f() { nlr_buf_t nlr; int i; for (i = 0; i < 4; i++) { printf("f:loop:%d:%p\n", i, &nlr); if (nlr_push(&nlr) == 0) { // normal //printf("a:%p:%p %p %p %u\n", &nlr, nlr.ip, nlr.sp, nlr.prev, nlr.ret_val); g(i); printf("f:lp:%d:nrm\n", i); nlr_pop(); } else { // nlr //printf("b:%p:%p %p %p %u\n", &nlr, nlr.ip, nlr.sp, nlr.prev, nlr.ret_val); printf("f:lp:%d:nlr:%d\n", i, (int)nlr.ret_val); } } } void nlr_test() { f(1); } */ int main() { // TODO disable JTAG qstr_init(); rt_init(); gpio_init(); led_init(); sw_init(); lcd_init(); storage_init(); // print a message printf(" micro py board\n"); // flash to indicate we are alive! for (int i = 0; i < 2; i++) { led_state(PYB_LED_R1, 1); led_state(PYB_LED_R2, 0); delay_ms(100); led_state(PYB_LED_R1, 0); led_state(PYB_LED_R2, 1); delay_ms(100); } // turn LEDs off led_state(PYB_LED_R1, 0); led_state(PYB_LED_R2, 0); led_state(PYB_LED_G1, 0); led_state(PYB_LED_G2, 0); // get and print clock speeds // SYSCLK=168MHz, HCLK=168MHz, PCLK1=42MHz, PCLK2=84MHz /* { RCC_ClocksTypeDef rcc_clocks; RCC_GetClocksFreq(&rcc_clocks); printf("S=%lu H=%lu P1=%lu P2=%lu\n", rcc_clocks.SYSCLK_Frequency, rcc_clocks.HCLK_Frequency, rcc_clocks.PCLK1_Frequency, rcc_clocks.PCLK2_Frequency); delay_ms(1000); } */ // USB if (1) { void usb_init(); usb_init(); } /* // to print info about memory for (;;) { led_state(PYB_LED_G1, 1); delay_ms(100); led_state(PYB_LED_G1, 0); extern void *_sidata; extern void *_sdata; extern void *_edata; extern void *_sbss; extern void *_ebss; extern void *_estack; extern void *_etext; extern void *_heap_start; if (sw_get()) { printf("_sidata=%p\n", &_sidata); printf("_sdata=%p\n", &_sdata); printf("_edata=%p\n", &_edata); printf("_sbss=%p\n", &_sbss); printf("_ebss=%p\n", &_ebss); printf("_estack=%p\n", &_estack); printf("_etext=%p\n", &_etext); printf("_heap_start=%p\n", &_heap_start); delay_ms(1000); } delay_ms(500); } */ //printf("init;al=%u\n", m_get_total_bytes_allocated()); // 1600, due to qstr_init //delay_ms(1000); #if 1 // Python! if (0) { //const char *pysrc = "def f():\n x=x+1\nprint(42)\n"; const char *pysrc = // impl01.py /* "x = 0\n" "while x < 400:\n" " y = 0\n" " while y < 400:\n" " z = 0\n" " while z < 400:\n" " z = z + 1\n" " y = y + 1\n" " x = x + 1\n"; */ // impl02.py /* "#@micropython.native\n" "def f():\n" " x = 0\n" " while x < 400:\n" " y = 0\n" " while y < 400:\n" " z = 0\n" " while z < 400:\n" " z = z + 1\n" " y = y + 1\n" " x = x + 1\n" "f()\n"; */ /* "print('in python!')\n" "x = 0\n" "while x < 4:\n" " pyb_led(True)\n" " pyb_delay(201)\n" " pyb_led(False)\n" " pyb_delay(201)\n" " x = x + 1\n" "print('press me!')\n" "while True:\n" " pyb_led(pyb_sw())\n"; */ /* // impl16.py "@micropython.asm_thumb\n" "def delay(r0):\n" " b(loop_entry)\n" " label(loop1)\n" " movw(r1, 55999)\n" " label(loop2)\n" " subs(r1, r1, 1)\n" " cmp(r1, 0)\n" " bgt(loop2)\n" " subs(r0, r0, 1)\n" " label(loop_entry)\n" " cmp(r0, 0)\n" " bgt(loop1)\n" "print('in python!')\n" "@micropython.native\n" "def flash(n):\n" " x = 0\n" " while x < n:\n" " pyb_led(True)\n" " delay(249)\n" " pyb_led(False)\n" " delay(249)\n" " x = x + 1\n" "flash(20)\n"; */ // impl18.py /* "# basic exceptions\n" "x = 1\n" "try:\n" " x.a()\n" "except:\n" " print(x)\n"; */ // impl19.py "# for loop\n" "def f():\n" " for x in range(400):\n" " for y in range(400):\n" " for z in range(400):\n" " pass\n" "f()\n"; py_lexer_t *lex = py_lexer_from_str_len("<>", pysrc, strlen(pysrc), false); if (0) { while (!py_lexer_is_kind(lex, PY_TOKEN_END)) { py_token_show(py_lexer_cur(lex)); py_lexer_to_next(lex); delay_ms(1000); } } else { // nalloc=1740;6340;6836 -> 140;4600;496 bytes for lexer, parser, compiler printf("lex; al=%u\n", m_get_total_bytes_allocated()); delay_ms(1000); py_parse_node_t pn = py_parse(lex, 0); //printf("----------------\n"); printf("pars;al=%u\n", m_get_total_bytes_allocated()); delay_ms(1000); //parse_node_show(pn, 0); py_compile(pn, false); printf("comp;al=%u\n", m_get_total_bytes_allocated()); delay_ms(1000); if (1) { // execute it! // add some functions to the python namespace rt_store_name(qstr_from_str_static("pyb_delay"), rt_make_function_1(pyb_delay)); rt_store_name(qstr_from_str_static("pyb_led"), rt_make_function_1(pyb_led)); rt_store_name(qstr_from_str_static("pyb_sw"), rt_make_function_0(pyb_sw)); py_obj_t module_fun = rt_make_function_from_id(1); // flash once led_state(PYB_LED_G1, 1); delay_ms(100); led_state(PYB_LED_G1, 0); nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { py_obj_t ret = rt_call_function_0(module_fun); printf("done! got: "); py_obj_print(ret); printf("\n"); nlr_pop(); } else { // uncaught exception printf("exception: "); py_obj_print((py_obj_t)nlr.ret_val); printf("\n"); } // flash once led_state(PYB_LED_G1, 1); delay_ms(100); led_state(PYB_LED_G1, 0); delay_ms(1000); printf("nalloc=%u\n", m_get_total_bytes_allocated()); delay_ms(1000); } } } #endif // benchmark C version of impl02.py if (0) { led_state(PYB_LED_G1, 1); delay_ms(100); led_state(PYB_LED_G1, 0); impl02_c_version(); led_state(PYB_LED_G1, 1); delay_ms(100); led_state(PYB_LED_G1, 0); } // MMA testing if (0) { printf("1"); mma_init(); printf("2"); mma_start(0x4c, 1); printf("3"); mma_send_byte(0); printf("4"); mma_stop(); printf("5"); mma_start(0x4c, 1); printf("6"); mma_send_byte(0); printf("7"); mma_restart(0x4c, 0); for (int i = 0; i <= 0xa; i++) { int data; if (i == 0xa) { data = mma_read_nack(); } else { data = mma_read_ack(); } printf(" %02x", data); } printf("\n"); mma_start(0x4c, 1); mma_send_byte(7); // mode mma_send_byte(1); // active mode mma_stop(); for (;;) { delay_ms(500); mma_start(0x4c, 1); mma_send_byte(0); mma_restart(0x4c, 0); for (int i = 0; i <= 3; i++) { int data; if (i == 3) { data = mma_read_nack(); printf(" %02x\n", data); } else { data = mma_read_ack() & 0x3f; if (data & 0x20) { data |= 0xc0; } printf(" % 2d", data); } } } } // fatfs testing if (0) { FRESULT res = f_mount(&fatfs0, "0:", 1); if (res == FR_OK) { printf("mount success\n"); } else if (res == FR_NO_FILESYSTEM) { res = f_mkfs("0:", 0, 0); if (res == FR_OK) { printf("mkfs success\n"); } else { printf("mkfs fail %d\n", res); } } else { printf("mount fail %d\n", res); } // write a file if (0) { FIL fp; f_open(&fp, "0:/boot.py", FA_WRITE | FA_CREATE_ALWAYS); UINT n; f_write(&fp, "# this is boot.py\n", 18, &n); printf("wrote %d\n", n); f_close(&fp); } // read a file if (0) { FIL fp; f_open(&fp, "0:/boot.py", FA_READ); UINT n; char buf[20]; f_read(&fp, buf, 18, &n); buf[n + 1] = 0; printf("read %d\n%s", n, buf); f_close(&fp); } DWORD nclst; FATFS *fatfs; f_getfree("0:", &nclst, &fatfs); printf("free=%u\n", (uint)(nclst * fatfs->csize * 512)); } // SD card testing if (0) { //sdio_init(); } // USB VCP testing if (0) { //usb_vcp_init(); } int i = 0; int n = 0; for (;;) { delay_ms(10); if (sw_get()) { led_state(PYB_LED_R1, 1); led_state(PYB_LED_G1, 0); i = 1 - i; if (i) { printf(" angel %05x.\n", n); //usb_vcp_send("hello!\r\n", 8); } else { printf(" mishka %4u.\n", n); //usb_vcp_send("angel!\r\n", 8); } n += 1; } else { led_state(PYB_LED_R1, 0); led_state(PYB_LED_G1, 1); } } return 0; }