diff --git a/src/main.zig b/src/main.zig index 494347a..b83db83 100644 --- a/src/main.zig +++ b/src/main.zig @@ -36,6 +36,7 @@ pub fn main() anyerror!void { .allocator = allocator, .arena = std.heap.ArenaAllocator.init(allocator), .articles = std.ArrayList(Article).init(allocator), + .tutorials = std.ArrayList(Tutorial).init(allocator), }; defer website.deinit(); @@ -44,6 +45,35 @@ pub fn main() anyerror!void { var root_dir = try std.fs.cwd().openDir("website", .{}); defer root_dir.close(); + // Tutorials are maintained manually right now + try website.addTutorial(Tutorial{ + .src_file = "website/tutorials/01-embedded-basics.md", + }); + try website.addTutorial(Tutorial{ + .src_file = "website/tutorials/02-embedded-programming.md", + }); + try website.addTutorial(Tutorial{ + .src_file = "website/tutorials/03-lpc1768.md", + }); + try website.addTutorial(Tutorial{ + .src_file = "website/tutorials/03-nrf52.md", + }); + try website.addTutorial(Tutorial{ + .src_file = "website/tutorials/03-avr.md", + }); + try website.addTutorial(Tutorial{ + .src_file = "website/tutorials/03-pi-pico.md", + }); + try website.addTutorial(Tutorial{ + .src_file = "website/tutorials/03-stm32.md", + }); + try website.addTutorial(Tutorial{ + .src_file = "website/tutorials/04-chose-device.md", + }); + try website.addTutorial(Tutorial{ + .src_file = "website/tutorials/05-hal.md", + }); + // gather articles { var dir = try root_dir.openDir("articles", .{ .iterate = true }); @@ -92,7 +122,12 @@ pub fn main() anyerror!void { var art_dir = try root_dir.makeOpenPath("articles", .{}); defer art_dir.close(); + var tut_dir = try root_dir.makeOpenPath("tutorials", .{}); + defer tut_dir.close(); + try website.renderArticles(art_dir); + + try website.renderTutorials(tut_dir); } } @@ -143,7 +178,12 @@ const Date = struct { const Article = struct { date: Date, src_file: []const u8, - title: []const u8, + title: []const u8 = "", +}; + +const Tutorial = struct { + src_file: []const u8, + title: []const u8 = "", }; const Website = struct { @@ -153,8 +193,10 @@ const Website = struct { allocator: *std.mem.Allocator, arena: std.heap.ArenaAllocator, articles: std.ArrayList(Article), + tutorials: std.ArrayList(Tutorial), fn deinit(self: *Self) void { + self.tutorials.deinit(); self.articles.deinit(); self.arena.deinit(); self.* = undefined; @@ -169,41 +211,63 @@ const Website = struct { }); } - fn prepareRendering(self: *Self) !void { - std.sort.sort(Article, self.articles.items, self.*, sortArticlesDesc); + fn addTutorial(self: *Self, tutorial: Tutorial) !void { + self.is_prepared = false; + try self.tutorials.append(Tutorial{ + .src_file = try self.arena.allocator.dupe(u8, tutorial.src_file), + .title = try self.arena.allocator.dupe(u8, tutorial.title), + }); + } - for (self.articles.items) |*article| { - var doc = blk: { - var p = try koino.parser.Parser.init(self.allocator, markdown_options); - defer p.deinit(); + fn findTitle(self: *Self, file: []const u8) !?[]const u8 { + var doc = blk: { + var p = try koino.parser.Parser.init(self.allocator, markdown_options); + defer p.deinit(); - const markdown = try std.fs.cwd().readFileAlloc(self.allocator, article.src_file, 10_000_000); - defer self.allocator.free(markdown); + const markdown = try std.fs.cwd().readFileAlloc(self.allocator, file, 10_000_000); + defer self.allocator.free(markdown); - try p.feed(markdown); + try p.feed(markdown); - break :blk try p.finish(); - }; - defer doc.deinit(); + break :blk try p.finish(); + }; + defer doc.deinit(); - std.debug.assert(doc.data.value == .Document); + std.debug.assert(doc.data.value == .Document); - var iter = doc.first_child; - var heading_or_null: ?*koino.nodes.AstNode = while (iter) |item| : (iter = item.next) { - if (item.data.value == .Heading) { - if (item.data.value.Heading.level == 1) { - break item; - } + var iter = doc.first_child; + var heading_or_null: ?*koino.nodes.AstNode = while (iter) |item| : (iter = item.next) { + if (item.data.value == .Heading) { + if (item.data.value.Heading.level == 1) { + break item; } - } else null; + } + } else null; + + if (heading_or_null) |heading| { + const string = try koino.html.print(&self.arena.allocator, markdown_options, heading); - if (heading_or_null) |heading| { - const string = try koino.html.print(&self.arena.allocator, markdown_options, heading); + std.debug.assert(std.mem.startsWith(u8, string, "

")); + std.debug.assert(std.mem.endsWith(u8, string, "

\n")); + + return string[4 .. string.len - 6]; + } else { + return null; + } + } - std.debug.assert(std.mem.startsWith(u8, string, "

")); - std.debug.assert(std.mem.endsWith(u8, string, "

\n")); + fn prepareRendering(self: *Self) !void { + std.sort.sort(Article, self.articles.items, self.*, sortArticlesDesc); - article.title = string[4 .. string.len - 6]; + for (self.articles.items) |*article| { + if (try self.findTitle(article.src_file)) |title| { + article.title = title; + } + } + + for (self.tutorials.items) |*tutorial| { + if (try self.findTitle(tutorial.src_file)) |title| { + tutorial.title = title; } } @@ -270,6 +334,17 @@ const Website = struct { } } + fn renderTutorials(self: *Self, dst_dir: std.fs.Dir) !void { + std.debug.assert(self.is_prepared); + for (self.tutorials.items) |tut| { + try self.renderMarkdownFile( + tut.src_file, + dst_dir, + try self.changeExtension(std.fs.path.basename(tut.src_file), ".htm"), + ); + } + } + /// Renders the root file and replaces `` with the first 10 articles, /// in descending order fn renderIndexFile(self: *Self, src_path: []const u8, dst_dir: std.fs.Dir, file_name: []const u8) !void { diff --git a/website/index.md b/website/index.md index dca8a92..6fdd918 100644 --- a/website/index.md +++ b/website/index.md @@ -14,19 +14,19 @@ This group was formed to document and improve the embedded programming experienc If you've never done any embedded development before, it's a good point to start with one of our tutorials: -- [Embedded Basics](articles/01-embedded-basics.htm) -- [Embedded Programming for Beginners](#) +- [Embedded Basics](tutorials/01-embedded-basics.htm) +- [Embedded Programming for Beginners](tutorials/02-embedded-programming.htm) - Getting started with... - - [Arduino/AVR](#) - - [LPC1768](#) - - [STM32](#) - - [MSP430](#) - - [ESP2866/ESP32](#) - - [NRF52](#) - - [Raspberry PI](#) - - [Raspberry PI Pico](#) -- [What device to chose?](#) -- [Introduction to HAL9001](#) + - [Arduino/AVR](tutorials/03-avr.htm) + - [LPC1768](tutorials/03-lpc1768.htm) + - [NRF52](tutorials/03-nrf52.htm) + - [Raspberry PI Pico](tutorials/03-pi-pico.htm) + - [STM32](tutorials/03-stm32.htm) + - [MSP430](#) (*missing*) + - [ESP2866/ESP32](#) (*missing*) + - [Raspberry PI](#) (*missing*) +- [What device to chose?](tutorials/04-chose-device.htm) +- [Introduction to HAL 9001](tutorials/05-hal.htm) ## Latest Articles diff --git a/website/tutorials/01-embedded-basics.md b/website/tutorials/01-embedded-basics.md index 3e17739..50ff712 100644 --- a/website/tutorials/01-embedded-basics.md +++ b/website/tutorials/01-embedded-basics.md @@ -1,3 +1,20 @@ # Embedded Basics -This is a stub. \ No newline at end of file +In this tutorial, you'll learn the absolute basics of the embedded world: + +## Contents + +- What are embedded systems? +- Electronics 101 + - Current, voltage, power and all + - Diodes, Resistors, Capacitors + - Ohm's law + - LEDs and pre-resistors + - MosFETs +- Breadboard vs. Soldering +- Digital I/O +- Analog I/O +- Bus Systems + - UART + - SPI + - I²C / TWI \ No newline at end of file diff --git a/website/tutorials/02-embedded-programming.md b/website/tutorials/02-embedded-programming.md new file mode 100644 index 0000000..e930292 --- /dev/null +++ b/website/tutorials/02-embedded-programming.md @@ -0,0 +1,10 @@ +# Embedded Programming + +In this tutorial, you'll learn the ways of the embedded programmer and how to master your MCU. + +## Contents + +- Differences to desktop programming +- The startup procedure +- Interacting with peripherials +- Interrupts and how to get them \ No newline at end of file diff --git a/website/tutorials/03-avr.md b/website/tutorials/03-avr.md new file mode 100644 index 0000000..5ce4d0a --- /dev/null +++ b/website/tutorials/03-avr.md @@ -0,0 +1 @@ +# Getting started with Arduino/AVR \ No newline at end of file diff --git a/website/tutorials/03-lpc1768.md b/website/tutorials/03-lpc1768.md new file mode 100644 index 0000000..77ef59e --- /dev/null +++ b/website/tutorials/03-lpc1768.md @@ -0,0 +1 @@ +# Getting started with LPC1768 \ No newline at end of file diff --git a/website/tutorials/03-nrf52.md b/website/tutorials/03-nrf52.md new file mode 100644 index 0000000..ed51cde --- /dev/null +++ b/website/tutorials/03-nrf52.md @@ -0,0 +1,2 @@ +# Getting started with NRF52 + diff --git a/website/tutorials/03-pi-pico.md b/website/tutorials/03-pi-pico.md new file mode 100644 index 0000000..ed46e0a --- /dev/null +++ b/website/tutorials/03-pi-pico.md @@ -0,0 +1 @@ +# Getting started with Raspberry Pi Pico \ No newline at end of file diff --git a/website/tutorials/03-stm32.md b/website/tutorials/03-stm32.md new file mode 100644 index 0000000..0f7d792 --- /dev/null +++ b/website/tutorials/03-stm32.md @@ -0,0 +1 @@ +# Getting started with STM32 \ No newline at end of file diff --git a/website/tutorials/04-chose-device.md b/website/tutorials/04-chose-device.md new file mode 100644 index 0000000..1c8509a --- /dev/null +++ b/website/tutorials/04-chose-device.md @@ -0,0 +1,7 @@ +# What device to chose? + +Consider: +- Project +- Experience +- Personal taste +- Price \ No newline at end of file diff --git a/website/tutorials/05-hal.md b/website/tutorials/05-hal.md new file mode 100644 index 0000000..2bddb7d --- /dev/null +++ b/website/tutorials/05-hal.md @@ -0,0 +1 @@ +# Introduction to HAL 9001 \ No newline at end of file