├── LICENSE ├── README ├── count-s08 └── count.c ├── count-s08a └── count.c ├── count-s08b └── count.c ├── count-s16 └── count.c ├── hello-s16 └── hello.c ├── timer_irq_blink ├── LICENSE └── timer_irq_blink.c └── watchdog ├── LICENSE └── watchdog.c /LICENSE: -------------------------------------------------------------------------------- 1 | See the individual examples for the respective licenses. 2 | 3 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | These are code examples for Padauk Microcontrollers. 2 | 3 | Suitable simple boards for can be found at: https://github.com/free-pdk/f-eval-boards 4 | 5 | They are meant to be compiled with the Small Device C Compiler (SDCC), version 4.0.0 or later. 6 | 7 | The count-s08 demo has been tested using PFS172 on the f-eval-pdk-s08 board. 8 | The count-s08a demo has been tested using PFS154 and PFS173 on the f-eval-pdk-s08a board. 9 | The count-s16 and hello-s16 demos have been tested using PFS154 and PFS173 on the f-eval-pdk-s16 board. 10 | Other configurations have not yet been tested. 11 | 12 | Currently, there are 5 demos: 13 | 14 | * count-s08: A timer / LED example for the PFS122, PFS172, and PGS134 (e.g. on the f-eval-s08 board). 15 | 16 | * count-s08a: A timer / LED example for the PFC151, PFC154, PFC161, PFS123, PFS154, PFS173 (e.g. on the f-eval-s08a board). 17 | 18 | * count-s08b: A timer / LED example for the PFC161 (e.g. on the f-eval-s08b board). 19 | 20 | * count-s16: A timer / LED example for the PFC154, PFC232, PFS132, PFS154, PFS173, PGS134, and PGS152 (e.g. on the f-eval-pdk-s16 or f-eval-pdk-s16a board). 21 | 22 | * hello-s16: A serial output example for the PFC154, PFC232, PFS132, PFS154, PFS173, PGS134, and PGS152 (e.g. on the f-eval-pdk-s16 or f-eval-pdk-s16a board). 23 | 24 | * timer_irq_blink: An example ported from MINI-C to SDCC. 25 | 26 | * watchdog: An example ported from MINI-C to SDCC. 27 | 28 | -------------------------------------------------------------------------------- /count-s08/count.c: -------------------------------------------------------------------------------- 1 | // A 2-bit counter for the Padauk PFS122, PFS172, and PGS134, to be compiled with SDCC. 2 | // Counts seconds from 0 to 3 in binary using the 4 LED on the second-lowest and highest bit of port B. 3 | // Written by Philipp Klaus Krause 2019-2020. 4 | // Source code under CC0 1.0. 5 | 6 | #include 7 | #include 8 | 9 | __sfr __at(0x03) clkmd; 10 | __sfr __at(0x04) inten; 11 | __sfr __at(0x05) intrq; 12 | __sfr __at(0x0b) ihrcr; 13 | __sfr __at(0x15) pb; 14 | __sfr __at(0x16) pbc; 15 | __sfr __at(0x30) tm2c; 16 | __sfr __at(0x32) tm2s; 17 | __sfr __at(0x33) tm2b; 18 | 19 | typedef unsigned long int clock_t; 20 | #define CLOCKS_PER_SEC 1000ul 21 | 22 | volatile static clock_t clocktime; 23 | volatile static bool clockupdate; 24 | 25 | void tick(void) __interrupt(0) 26 | { 27 | if(!(intrq & 0x40)) 28 | return; 29 | intrq = 0x00; 30 | 31 | clocktime++; 32 | clockupdate = true; 33 | } 34 | 35 | clock_t clock(void) 36 | { 37 | clock_t ctmp; 38 | 39 | do 40 | { 41 | clockupdate = false; 42 | ctmp = clocktime; 43 | } while (clockupdate); 44 | 45 | return(ctmp); 46 | } 47 | 48 | #if __SDCC_REVISION >= 13762 49 | unsigned char __sdcc_external_startup(void) 50 | #else 51 | unsigned char _sdcc_external_startup(void) 52 | #endif 53 | { 54 | ihrcr = *((const unsigned char*)(0x87ed)); // Use PFS172 factory calibration value for IHRC at 16 Mhz. 55 | 56 | clkmd = 0x34; // Use IHRC / 2 = 8 Mhz for system clock, disable watchdog. 57 | clkmd = 0x30; // Disable ILRC 58 | 59 | return 0; // perform normal initialization 60 | } 61 | 62 | void main(void) 63 | { 64 | // Set timer 2 for interrupt at 1 kHz. 65 | tm2c = 0x10; // Use CLK (8 Mhz) 66 | tm2s = 0x54; // Divide by 16 * 25 ~> 20 kHz 67 | tm2b = 19; // Divide by 19 + 1 ~> 1 kHz 68 | inten = 0x40; 69 | 70 | __asm 71 | engint 72 | __endasm; 73 | 74 | pbc = 0x82; 75 | 76 | for(;;) 77 | { 78 | uint_fast8_t s = (clock() / 1000) % 4; 79 | pb = (s << 6 & 0x80) | (s << 1 & 0x02); 80 | } 81 | } 82 | 83 | -------------------------------------------------------------------------------- /count-s08a/count.c: -------------------------------------------------------------------------------- 1 | // A 2-bit counter for the Padauk PFC151, PFC154, PFC161, PFS123, PFS154, and PFS173, to be compiled with SDCC. 2 | // Counts seconds from 0 to 3 in binary using the 4 LED on the lowest and highest bit of port A. 3 | // Written by Philipp Klaus Krause 2019-2020. 4 | // Source code under CC0 1.0. 5 | 6 | #include 7 | #include 8 | 9 | __sfr __at(0x03) clkmd; 10 | __sfr __at(0x04) inten; 11 | __sfr __at(0x05) intrq; 12 | __sfr __at(0x0b) ihrcr; 13 | __sfr __at(0x10) pa; 14 | __sfr __at(0x11) pac; 15 | #ifdef __SDCC_pdk15 // PFS 123, PFS173 16 | __sfr __at(0x30) tm2c; 17 | __sfr __at(0x32) tm2s; 18 | __sfr __at(0x33) tm2b; 19 | #else // PFC151, PFC154, PFC161 or PFS154 20 | __sfr __at(0x1c) tm2c; 21 | __sfr __at(0x17) tm2s; 22 | __sfr __at(0x09) tm2b; 23 | #endif 24 | 25 | typedef unsigned long int clock_t; 26 | #define CLOCKS_PER_SEC 1000ul 27 | 28 | volatile static clock_t clocktime; 29 | volatile static bool clockupdate; 30 | 31 | void tick(void) __interrupt(0) 32 | { 33 | if(!(intrq & 0x40)) 34 | return; 35 | intrq = 0x00; 36 | 37 | clocktime++; 38 | clockupdate = true; 39 | } 40 | 41 | clock_t clock(void) 42 | { 43 | clock_t ctmp; 44 | 45 | do 46 | { 47 | clockupdate = false; 48 | ctmp = clocktime; 49 | } while (clockupdate); 50 | 51 | return(ctmp); 52 | } 53 | 54 | #if __SDCC_REVISION >= 13762 55 | unsigned char __sdcc_external_startup(void) 56 | #else 57 | unsigned char _sdcc_external_startup(void) 58 | #endif 59 | { 60 | #ifdef __SDCC_pdk15 61 | ihrcr = *((const unsigned char*)(0x8bed)); // Use PFS173 factory calibration value for IHRC at 16 Mhz. 62 | #else 63 | ihrcr = *((const unsigned char*)(0x87ed)); // Use PFS154 factory calibration value for IHRC at 16 Mhz. 64 | #endif 65 | 66 | clkmd = 0x34; // Use IHRC / 2 = 8 Mhz for system clock, disable watchdog. 67 | clkmd = 0x30; // Disable ILRC 68 | 69 | return 0; // perform normal initialization 70 | } 71 | 72 | void main(void) 73 | { 74 | // Set timer 2 for interrupt at 1 kHz. 75 | tm2c = 0x10; // Use CLK (8 Mhz) 76 | tm2s = 0x54; // Divide by 16 * 25 ~> 20 kHz 77 | tm2b = 19; // Divide by 19 + 1 ~> 1 kHz 78 | inten = 0x40; 79 | 80 | __asm 81 | engint 82 | __endasm; 83 | 84 | pac = 0x81; 85 | 86 | for(;;) 87 | { 88 | uint_fast8_t s = (clock() / 1000) % 4; 89 | pa = (s << 6 & 0x80) | (s & 0x01); 90 | } 91 | } 92 | 93 | -------------------------------------------------------------------------------- /count-s08b/count.c: -------------------------------------------------------------------------------- 1 | // A 2-bit counter for the Padauk PFC161, to be compiled with SDCC. 2 | // Counts seconds from 0 to 3 in binary using the 4 LED on the lowest bit of port b and highest bit of port A. 3 | // Written by Philipp Klaus Krause 2019-2020. 4 | // Source code under CC0 1.0. 5 | 6 | #include 7 | #include 8 | 9 | __sfr __at(0x03) clkmd; 10 | __sfr __at(0x04) inten; 11 | __sfr __at(0x05) intrq; 12 | __sfr __at(0x0b) ihrcr; 13 | __sfr __at(0x10) pa; 14 | __sfr __at(0x11) pac; 15 | __sfr __at(0x14) pb; 16 | __sfr __at(0x15) pbc; 17 | __sfr __at(0x1c) tm2c; 18 | __sfr __at(0x1e) tm2s; 19 | __sfr __at(0x1f) tm2b; 20 | 21 | typedef unsigned long int clock_t; 22 | #define CLOCKS_PER_SEC 1000ul 23 | 24 | volatile static clock_t clocktime; 25 | volatile static bool clockupdate; 26 | 27 | void tick(void) __interrupt(0) 28 | { 29 | if(!(intrq & 0x40)) 30 | return; 31 | intrq = 0x00; 32 | 33 | clocktime++; 34 | clockupdate = true; 35 | } 36 | 37 | clock_t clock(void) 38 | { 39 | clock_t ctmp; 40 | 41 | do 42 | { 43 | clockupdate = false; 44 | ctmp = clocktime; 45 | } while (clockupdate); 46 | 47 | return(ctmp); 48 | } 49 | 50 | #if __SDCC_REVISION >= 13762 51 | unsigned char __sdcc_external_startup(void) 52 | #else 53 | unsigned char _sdcc_external_startup(void) 54 | #endif 55 | { 56 | //ihrcr = *((const unsigned char*)(0x87ed)); // Use PFS154 factory calibration value for IHRC at 16 Mhz. 57 | 58 | //clkmd = 0x34; // Use IHRC / 2 = 8 Mhz for system clock, disable watchdog. 59 | //clkmd = 0x30; // Disable ILRC 60 | 61 | return 0; // perform normal initialization 62 | } 63 | 64 | void main(void) 65 | { 66 | // Set timer 2 for interrupt at 1 kHz. 67 | //tm2c = 0x10; // Use CLK (8 Mhz) 68 | //tm2s = 0x54; // Divide by 16 * 25 ~> 20 kHz 69 | //tm2b = 19; // Divide by 19 + 1 ~> 1 kHz 70 | //inten = 0x40; 71 | 72 | __asm 73 | engint 74 | __endasm; 75 | 76 | pbc = 0x01; 77 | pac = 0x80;pbc= 0xff; pac = 0xff; 78 | pa = 0xff; pb = 0xff; 79 | for(;;) 80 | { 81 | /*uint_fast8_t s = (clock() / 1000) % 4; 82 | pb = s & 0x01; 83 | pa = s << 6 & 0x80;*/ 84 | } 85 | } 86 | 87 | -------------------------------------------------------------------------------- /count-s16/count.c: -------------------------------------------------------------------------------- 1 | // A 4-bit counter for the Padauk PFC154, PFC232, PFS132, PFS154, PFS173, PGS134, and PGS152, to be compiled with SDCC. 2 | // Counts seconds from 0 to 15 in binary using the 4 LED on the lower 4 bits of Port B. 3 | // Written by Philipp Klaus Krause 2019-2020. 4 | // Source code under CC0 1.0. 5 | 6 | #include 7 | 8 | __sfr __at(0x03) clkmd; 9 | __sfr __at(0x04) inten; 10 | __sfr __at(0x05) intrq; 11 | __sfr __at(0x0b) ihrcr; 12 | #ifdef __SDCC_pdk15 // PFS173, or PGS134. 13 | __sfr __at(0x13) pb; 14 | __sfr __at(0x14) pbc; 15 | __sfr __at(0x30) tm2c; 16 | __sfr __at(0x32) tm2s; 17 | __sfr __at(0x33) tm2b; 18 | #else // PFC154, PFC232, PFS132, PFS154, or PGS152. 19 | __sfr __at(0x14) pb; 20 | __sfr __at(0x15) pbc; 21 | __sfr __at(0x1c) tm2c; 22 | __sfr __at(0x17) tm2s; 23 | __sfr __at(0x09) tm2b; 24 | #endif 25 | 26 | typedef unsigned long int clock_t; 27 | #define CLOCKS_PER_SEC 1000ul 28 | 29 | volatile static clock_t clocktime; 30 | volatile static bool clockupdate; 31 | 32 | void tick(void) __interrupt(0) 33 | { 34 | if(!(intrq & 0x40)) 35 | return; 36 | intrq = 0x00; 37 | 38 | clocktime++; 39 | clockupdate = true; 40 | } 41 | 42 | clock_t clock(void) 43 | { 44 | clock_t ctmp; 45 | 46 | do 47 | { 48 | clockupdate = false; 49 | ctmp = clocktime; 50 | } while (clockupdate); 51 | 52 | return(ctmp); 53 | } 54 | 55 | #if __SDCC_REVISION >= 13762 56 | unsigned char __sdcc_external_startup(void) 57 | #else 58 | unsigned char _sdcc_external_startup(void) 59 | #endif 60 | { 61 | #ifdef __SDCC_pdk15 62 | ihrcr = *((const unsigned char*)(0x8bed)); // Use PFS173 factory calibration value for IHRC at 16 Mhz. 63 | #else 64 | ihrcr = *((const unsigned char*)(0x87ed)); // Use PFC154 / PFC232 / PFS154 factory calibration value for IHRC at 16 Mhz. 65 | #endif 66 | 67 | clkmd = 0x34; // Use IHRC / 2 = 8 Mhz for system clock, disable watchdog. 68 | clkmd = 0x30; // Disable ILRC 69 | 70 | return 0; // perform normal initialization 71 | } 72 | 73 | void main(void) 74 | { 75 | // Set timer 2 for interrupt at 1 kHz. 76 | tm2c = 0x10; // Use CLK (8 Mhz) 77 | tm2s = 0x54; // Divide by 16 * 25 ~> 20 kHz 78 | tm2b = 19; // Divide by 19 + 1 ~> 1 kHz 79 | inten = 0x40; 80 | 81 | __asm 82 | engint 83 | __endasm; 84 | 85 | pbc = 0x0f; 86 | 87 | for(;;) 88 | pb = (clock() / 1000) % 16; 89 | } 90 | 91 | -------------------------------------------------------------------------------- /hello-s16/hello.c: -------------------------------------------------------------------------------- 1 | // "Hello, world!" for the Padauk PFC154, PFC232, PFS132, PFS154, PFS173, PGS134, and PGS152, to be compiled with SDCC. 2 | // Repeatedly outputs the string "Hello, World!" at 9600 baud, 1 stop bit, no parity on pin 0 of Port A. 3 | // Written by Philipp Klaus Krause 2019-2020. 4 | // Source code under CC0 1.0. 5 | 6 | #include 7 | #include 8 | 9 | volatile unsigned char sendcounter; 10 | volatile unsigned int senddata; 11 | volatile bool sending; 12 | 13 | __sfr __at(0x03) clkmd; 14 | __sfr __at(0x04) inten; 15 | __sfr __at(0x05) intrq; 16 | __sfr __at(0x0b) ihrcr; 17 | __sfr __at(0x10) pa; 18 | __sfr __at(0x11) pac; 19 | #ifdef __SDCC_pdk15 // PFS173, or PGS134. 20 | __sfr __at(0x30) tm2c; 21 | __sfr __at(0x31) tm2ct; 22 | __sfr __at(0x32) tm2s; 23 | __sfr __at(0x33) tm2b; 24 | #else // PFC154, PFC232, PFS132, PFS154, or PGS152. 25 | __sfr __at(0x1c) tm2c; 26 | __sfr __at(0x1d) tm2ct; 27 | __sfr __at(0x17) tm2s; 28 | __sfr __at(0x09) tm2b; 29 | #endif 30 | 31 | void send_bit(void) __interrupt(0) 32 | { 33 | // Reset interrupt request, proceed only if we had a timer interrupt. 34 | if(!(intrq & 0x40)) 35 | { 36 | intrq = 0x00; 37 | return; 38 | } 39 | intrq = 0x00; 40 | 41 | if(!sending) 42 | return; 43 | 44 | pa = senddata & 1; 45 | senddata >>= 1; 46 | 47 | if(!--sendcounter) 48 | { 49 | sending = false; 50 | 51 | inten &= ~0x40; 52 | } 53 | } 54 | 55 | int putchar(int c) 56 | { 57 | while(sending); 58 | 59 | senddata = (c << 1) | 0x200; 60 | 61 | sendcounter = 10; 62 | 63 | tm2ct = 0; 64 | 65 | sending = true; 66 | 67 | inten |= 0x40; 68 | 69 | return (c); 70 | } 71 | 72 | #if __SDCC_REVISION >= 13762 73 | unsigned char __sdcc_external_startup(void) 74 | #else 75 | unsigned char _sdcc_external_startup(void) 76 | #endif 77 | { 78 | #ifdef __SDCC_pdk15 79 | ihrcr = *((const unsigned char*)(0x8bed)); // Use PFS173 factory calibration value for IHRC at 16 Mhz. 80 | #else 81 | ihrcr = *((const unsigned char*)(0x87ed)); // Use PFC154 / PFC232 / PFS154 factory calibration value for IHRC at 16 Mhz. 82 | #endif 83 | 84 | clkmd = 0x34; // Use IHRC / 2 = 8 Mhz for system clock, disable watchdog. 85 | clkmd = 0x30; // Disable ILRC 86 | 87 | return 0; // perform normal initialization 88 | } 89 | 90 | void main(void) 91 | { 92 | // Set timer 2 for interrupt for 9600 baud. 93 | tm2c = 0x10; // Use CLK (8 Mhz) 94 | tm2s = 0x06; // Divide by 6 + 1 ~> 1142857 Hz 95 | tm2b = 118; // Divide by 118 + 1 ~> 9604 Hz 96 | inten = 0x40; 97 | __asm 98 | engint 99 | __endasm; 100 | 101 | pac = 0x01; 102 | 103 | for(;;) 104 | { 105 | printf("Hello, World!\n"); 106 | for(unsigned long int i = 0; i < 150000; i++); // Wait approx. 3s. 107 | } 108 | } 109 | 110 | -------------------------------------------------------------------------------- /timer_irq_blink/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 free-pdk 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /timer_irq_blink/timer_irq_blink.c: -------------------------------------------------------------------------------- 1 | // A port of the Mini-C TimerIrqBlink example code from https://github.com/free-pdk/simple-pdk-code-examples to the SDCC-based toolchain 2 | // Written by Philipp Klaus Krause in 2019. 3 | // Source code under MIT, like the original. 4 | 5 | /* Original Mini-C code 6 | void FPPA0 (void) 7 | { 8 | .ADJUST_IC SYSCLK=IHRC/16 // SYSCLK=IHRC/16 = 1MHz 9 | 10 | PAC.3 = 1; // set PA.3 as output 11 | 12 | $ T16M SYSCLK, /64, BIT12; // timer base = SYSCLK/64 = 15625 Hz 13 | // generate INTRQ.T16 when overflow to bit 12 (4096) 14 | // first interrupt triggered after 4096 cycles (13 bit 0 change to 1) 15 | // next interrupt after next 8192 cycles (13 bit 1 needs to change to 0 first and then back to 1) 16 | 17 | WORD tmp = 0; // store 0 to timer value (first run) 18 | stt16 tmp; 19 | 20 | $ INTEN T16; // enable T16 interrupt 21 | 22 | INTRQ = 0; // clear any pending interrupt requests 23 | ENGINT; // enable global interrupts 24 | 25 | while (1) { } // endless loop (empty) 26 | } 27 | 28 | 29 | void Interrupt(void) 30 | { 31 | PUSHAF; // save A and FLAGs 32 | 33 | if( INTRQ.T16 ) // interrupt source = timer T16? 34 | { 35 | PA ^= (1<<3); // toggle bit of PA.3 output 36 | INTRQ.T16 = 0; // clear interrupt request for T16 37 | } 38 | 39 | POPAF; // restore A and FLAGs 40 | } 41 | */ 42 | 43 | __sfr __at(0x03) clkmd; 44 | __sfr __at(0x04) inten; 45 | __sfr __at(0x05) intrq; 46 | __sfr __at(0x06) t16m; 47 | __sfr __at(0x10) pa; 48 | __sfr __at(0x11) pac; 49 | __sfr16 t16cnt; 50 | 51 | #define INT_T16 0x04 52 | 53 | #define LEDpin 0 // Modify this to select the PIN the LED is connected to. Default: PA.0 54 | 55 | unsigned char _sdcc_external_startup(void) 56 | { 57 | clkmd = 0x18; // Use IHRC / 16 = 1 Mhz for system clock, disable watchdog. Enable IHRC 58 | return 0; // perform normal initialization 59 | } 60 | 61 | void main(void) 62 | { 63 | pac |= (1 << LEDpin); 64 | 65 | t16m = (1 << 5) | (3 << 3) | 4; // timer clock=system clock (1MHz), Divide by 64, use bit 12 of timer as irq source 66 | 67 | t16cnt = 0; 68 | 69 | inten |= INT_T16; 70 | 71 | intrq = 0; 72 | 73 | __asm 74 | engint 75 | __endasm; 76 | 77 | while(1); 78 | } 79 | 80 | void handler(void) __interrupt(0) 81 | { 82 | if (intrq & INT_T16) 83 | { 84 | pa ^= (1 << LEDpin); 85 | intrq &= ~INT_T16; 86 | } 87 | } 88 | 89 | -------------------------------------------------------------------------------- /watchdog/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 free-pdk 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /watchdog/watchdog.c: -------------------------------------------------------------------------------- 1 | // A port of the Mini-C Watchdog example code from https://github.com/free-pdk/simple-pdk-code-examples to the SDCC-based toolchain 2 | // Written by Philipp Klaus Krause in 2019. 3 | // Source code under MIT, like the original. 4 | 5 | /* Original Mini-C code 6 | void FPPA0 (void) 7 | { 8 | .ADJUST_IC SYSCLK=IHRC/16, IHRC=16MHz, VDD=3.3V 9 | 10 | CLKMD.En_ILRC = 1; //enable Internal Low speed RC (required for watchdog to run) 11 | // ILRC runs at around 70kHz +/- 10kHz on PMx154 (depending on VDD and ambient temperature) 12 | 13 | $ MISC = WDT_256K; //watchdog timeout is 262144 ILRC periods = apx. 3.8 seconds (Slow_WakeUp,LCD_Disabled,LVR_Enabled) 14 | // -> wdreset must be called at least every 3.8 seconds, otherwise reset is triggered 15 | // NOTE: ICE watchdog timeouts are completely different, check datasheet 16 | 17 | wdreset; //reset watchdog 18 | CLKMD.En_WatchDog = 1; //enable watchdog 19 | 20 | 21 | PAC.3 = 1; //PA.3 as output 22 | PA.3 = 1; //PA.3 high (LED on) 23 | 24 | .delay 1000000; //wait 1 second 25 | 26 | wdreset; //reset watchdog 27 | PA.3 = 0; //PA.3 low (LED off) 28 | 29 | while(1) {} //endless loop which does not 'feeds' the watch 'dog' 30 | // -> reset will be triggered (cpu will restart, LED will go on again for 1 second and so on...) 31 | // without watchdog beeing triggered the LED would stay off for evers 32 | } 33 | */ 34 | 35 | __sfr __at(0x03) clkmd; 36 | __sfr __at(0x08) misc; 37 | __sfr __at(0x10) pa; 38 | __sfr __at(0x11) pac; 39 | 40 | // This function is called before initializing global and static variables. 41 | // Place stuff here that needs to be done immediately after reset (such as disabling a watchdog). 42 | // For small examples it doesn't matter, but for large programs with many global or static variables, 43 | // a watchdog that is active after reset otherwise might bite before main() gets executed. 44 | #if __SDCC_REVISION >= 13762 45 | unsigned char __sdcc_external_startup(void) 46 | #else 47 | unsigned char _sdcc_external_startup(void) 48 | #endif 49 | { 50 | clkmd = 0x08; // Use IHRC / 16 = 1 Mhz for system clock, disable watchdog. 51 | 52 | return 0; // perform normal initialization 53 | } 54 | 55 | void main(void) 56 | { 57 | misc = 0x03; 58 | 59 | __asm 60 | wdreset 61 | __endasm; 62 | 63 | clkmd |= 0x02; // Enable watchdog 64 | 65 | pac |= 0x08; 66 | pa |= 0x08; 67 | 68 | for(unsigned long int i = 0; i < 50000; i++); // Wait approx. 1s. 69 | 70 | __asm 71 | wdreset 72 | __endasm; 73 | 74 | pa &= 0xf7; 75 | 76 | while (1); 77 | } 78 | 79 | --------------------------------------------------------------------------------